diff options
Diffstat (limited to 'libc/malloc2/malloc.c')
-rw-r--r-- | libc/malloc2/malloc.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/libc/malloc2/malloc.c b/libc/malloc2/malloc.c new file mode 100644 index 0000000..143d324 --- /dev/null +++ b/libc/malloc2/malloc.c @@ -0,0 +1,127 @@ +/* simplified linux malloc.h + Copyright (C) 1995 Joel N. Weber II + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <malloc.h> + +typedef struct __malloc_struct malloc_struct; + +typedef union __malloc_union +{ + char *c; + malloc_struct *m; +} malloc_union; + + +struct __malloc_struct +{ + unsigned char status; +#define ALLOC 0x53 +#define FREE 0x55 +#define END_OF_WORLD 0x57 + malloc_union next; +} *malloc_start; + +extern int __STACKSIZE; + +/* WARNING: this init will only work if there is a hard limit on the + amount of RAM that can be allocated. + */ + +#ifdef __AS386_16__ +#asm + loc 1 ! Make sure the pointer is in the correct segment +auto_func: ! Label for bcc -M to work. + .word _malloc_init ! Pointer to the autorun function + .word no_op ! Space filler cause segs are padded to 4 bytes. + .text ! So the function after is also in the correct seg. +#endasm +#endif + +malloc_init() +{ + extern unsigned int sbrk(); + + unsigned int ptr, sz, count; + + malloc_start = (malloc_struct*) ((sbrk(16)+1)&~1); + malloc_start->status = FREE; + + count=254; + for(sz=16384; sz>64; ) + { + ptr= sbrk(sz); + if( ptr == (unsigned)-1 ) sz>>=1; + else count+=sz; + } + if( __STACKSIZE > count || __STACKSIZE <= 0 ) __STACKSIZE = ((count>>1)&-2); + ptr = sbrk(-__STACKSIZE); + + malloc_start->next.m = ((malloc_struct*)ptr) - 1; + + malloc_start->next.m->status = END_OF_WORLD; +} + +char *malloc(size) +size_t size; +{ + register malloc_union tmp, tmp2; + + /* Make sure we don't lose the alignment */ + size = (size+sizeof(malloc_struct)-1)/sizeof(malloc_struct); + + tmp.m = malloc_start; + while ( ( tmp.m->next.m - tmp.m - 2 ) < size + || ( tmp.m->status == ALLOC )) + tmp.m = tmp.m->next.m; + + if (tmp.m->status == FREE){ + tmp2.m = size + tmp.m + 1; + tmp2.m->status = FREE; + tmp2.m->next.c = tmp.m->next.c; + tmp.m->status = ALLOC; + tmp.m->next.c = tmp2.c; + } + else return 0; + tmp.m++; + return tmp.c; +} + +__malloc_cleanup() /* finds consecutive free blocks and joins them */ +{ + malloc_struct *tmp; + + tmp = malloc_start; + while ((tmp->status != END_OF_WORLD)&&(tmp->next.m->status != END_OF_WORLD)){ + if ((tmp->status==FREE)&&(tmp->next.m->status==FREE)) + tmp->next.m = tmp->next.m->next.m; + else tmp = tmp->next.m; + } +} + +free(what) +char *what; +{ + malloc_union tmp; + + tmp.c = what; tmp.m--; + if( tmp.m->status == ALLOC ) + { + tmp.m->status = FREE; + __malloc_cleanup; + } +} |