home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib32.zoo / malloc.c < prev    next >
C/C++ Source or Header  |  1992-09-17  |  5KB  |  211 lines

  1. /* from the TOS GCC library */
  2. /* malloc, free, realloc: dynamic memory allocation */
  3. /* ERS: added mlalloc, relalloc, etc. for 16 bit compilers. Changed
  4.    argument of malloc, etc.,  to size_t (per ANSI draft). */
  5. /* 5/2/92 sb -- modified for Heat-n-Serve C to accomodate its 16-bit size_t */
  6. /* 5/5/92 sb -- split off realloc() & calloc() to reduce library drag */
  7.  
  8. #include <compiler.h>
  9. #include <stddef.h>    /* for size_t */
  10. #include <stdlib.h>
  11. #include <memory.h>
  12. #include <string.h>
  13. #include <assert.h>
  14. #include <unistd.h>
  15. #include "lib.h"
  16.  
  17. extern long _stksize;
  18. void *_malloc __PROTO((unsigned long));
  19.  
  20. /* minimum chunk to ask OS for */
  21. static size_t MINHUNK =    4096L;    /* default */
  22. static size_t MAXHUNK = 32*1024L; /* max. default */
  23.  
  24.     /* CAUTION: use _mallocChunkSize() to tailor to your environment,
  25.             do not make the default too large, as the compiler
  26.             gets screwed on a 1M machine otherwise (stack/heap clash)
  27.      */
  28.  
  29. /* linked list of free blocks struct defined in lib.h */
  30.  
  31. struct mem_chunk _mchunk_free_list = { VAL_FREE, NULL, 0L };
  32.  
  33. /* flag to control zero'ing of malloc'ed chunks */
  34. static int _ZeroMallocs = 0;
  35.  
  36. __EXTERN void _bzero __PROTO((void *, unsigned long));
  37.  
  38. #ifdef __GNUC__
  39. asm(".stabs \"_malloc\",5,0,0,__malloc"); /* dept of clean tricks */
  40. #endif
  41.  
  42. void * _malloc(n)
  43. unsigned long n; 
  44. {
  45.   struct mem_chunk *p, *q;
  46.   long sz;
  47.   extern void *_heapbase;
  48.   extern short _split_mem;
  49.  
  50. /* add a mem_chunk to required size and round up */
  51.   n = n + sizeof(struct mem_chunk);
  52.   n = (7 + n) & ~7;
  53. /* look for first block big enough in free list */
  54.   p = &_mchunk_free_list;
  55.   q = _mchunk_free_list.next;
  56.  
  57.   while ((q != NULL) && (q->size < n))
  58.     {
  59.     p = q;
  60.     q = q->next;
  61.     }
  62.  
  63. /* if not enough memory, get more from the system */
  64.   if (q == NULL) 
  65.     {
  66.     if (((!_split_mem) && (_heapbase != NULL)) || (n > MINHUNK))
  67.         sz = n;
  68.     else {
  69.         sz = MINHUNK;
  70.         if (MINHUNK < MAXHUNK)
  71.             MINHUNK *= 2;
  72.     }
  73.     q = (struct mem_chunk * )_sbrk(sz);
  74.  
  75.     if (((long)q) == -1)         /* can't alloc any more? */
  76.         return(NULL);
  77.  
  78.     /* Note: q may be below the highest allocated chunk */
  79.     p = &_mchunk_free_list;
  80.     while (p->next != NULL && q > p->next)
  81.       p = p->next;
  82.     q->size = sz;
  83.     q->next = p->next;
  84.     q->valid = VAL_FREE;
  85.     p->next = q;
  86.     }
  87.         
  88.   if (q->size > n + sizeof(struct mem_chunk))
  89.     {                /* split, leave part of free list */
  90.     q->size -= n;
  91.     q = (struct mem_chunk * )(((long) q) + q->size);
  92.     q->size = n;
  93.     q->valid = VAL_ALLOC;
  94.     }
  95.     else
  96.     {                /* just unlink it */
  97.     p->next = q->next;
  98.     q->valid = VAL_ALLOC;
  99.     }
  100.  
  101.   q->next = NULL;    
  102.   q++;    /* hand back ptr to after chunk desc */
  103.   if(_ZeroMallocs != 0)
  104.       _bzero((void *)q, (long)(n - sizeof(struct mem_chunk)));
  105.   
  106.   return((void * )q);
  107. }
  108.  
  109. void free(param)
  110.     void *param;
  111. {
  112.   struct mem_chunk *o, *p, *q, *s;
  113.   struct mem_chunk *r = (struct mem_chunk *) param;
  114.   extern void *_heapbase;
  115.   extern short _split_mem;
  116.  
  117. /* free(NULL) should do nothing */
  118.   if (r == 0)
  119.      return;
  120.  
  121. /* move back to uncover the mem_chunk */
  122.   r--;            /* there it is! */
  123.  
  124.   if (r->valid != VAL_ALLOC)
  125.     return;
  126.  
  127.   r->valid = VAL_FREE;
  128.  
  129. /* stick it into free list, preserving ascending address order */
  130.   o = NULL;
  131.   p = &_mchunk_free_list;
  132.   q = _mchunk_free_list.next;
  133.   while (q != NULL && q < r) 
  134.     {
  135.     o = p;
  136.     p = q;
  137.     q = q->next;
  138.     }
  139.  
  140. /* merge after if possible */
  141.   s = (struct mem_chunk * )(((long) r) + r->size);
  142.   if (q != NULL && s >= q) 
  143.     {
  144.     assert(s == q);
  145.     r->size += q->size;
  146.     q = q->next;
  147.     s->size = 0;
  148.     s->next = NULL;
  149.     }
  150.   r->next = q;
  151.     
  152. /* merge before if possible, otherwise link it in */
  153.   s = (struct mem_chunk * )(((long) p) + p->size);
  154.   if (s >= r && p != &_mchunk_free_list)
  155.     /* remember: r may be below &_mchunk_free_list in memory */
  156.     {
  157.     assert(s == r);
  158.     p->size += r->size;
  159.     p->next = r->next;
  160.     r->size = 0;
  161.     r->next = NULL;
  162.     s = (struct mem_chunk * )(((long) p) + p->size);
  163.     if ((!_split_mem) && _heapbase != NULL &&
  164.         s >= (struct mem_chunk *) _heapbase &&
  165.         s < (struct mem_chunk *) ((char *)_heapbase + _stksize)) {
  166.       assert(s == (struct mem_chunk *) _heapbase);
  167.       _heapbase = (void *) p;
  168.       _stksize += p->size;
  169.       o->next = p->next;    /* o is always != NULL here */
  170.     }
  171.     }
  172.     else
  173.         {
  174.       s = (struct mem_chunk * )(((long) r) + r->size);
  175.       if ((!_split_mem) && _heapbase != NULL &&
  176.           s >= (struct mem_chunk *) _heapbase &&
  177.           s < (struct mem_chunk *) ((char *)_heapbase + _stksize)) {
  178.         assert(s == (struct mem_chunk *) _heapbase);
  179.         _heapbase = (void *) r;
  180.         _stksize += r->size;
  181.         p->next = r->next;
  182.       } else p->next = r;
  183.     }
  184. }
  185.  
  186. /*
  187.  * Set zero block after malloc flag
  188.  */
  189. void _malloczero(yes)
  190. int yes;
  191. {
  192.     _ZeroMallocs = yes;
  193. }
  194.  
  195. /*
  196.  * tune chunk size
  197.  */
  198. void _mallocChunkSize (siz)
  199. size_t siz;
  200. {
  201.     MAXHUNK = MINHUNK = siz;
  202. }
  203.  
  204. #ifndef __GNUC__
  205. void * malloc(n)
  206. size_t n; 
  207. {
  208.   return _malloc((unsigned long) n);
  209. }
  210. #endif
  211.