home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / mint / mntlib16.lzh / MNTLIB16 / MALLOC.C < prev    next >
C/C++ Source or Header  |  1993-08-03  |  6KB  |  283 lines

  1. /* from the TOS GCC library */
  2. /* malloc, free, realloc: dynamic memory allocation */
  3.  
  4. #include <stddef.h>    /* for size_t */
  5. #include <memory.h>
  6. #include <string.h>
  7. #include <assert.h>
  8.  
  9. extern long _stksize;
  10. extern void *_sbrk();
  11.  
  12. /* minimum chunk to ask OS for */
  13. static size_t MINHUNK =    4096L;    /* default */
  14. static size_t MAXHUNK = 32*1024L; /* max. default */
  15.  
  16.     /* CAUTION: use _mallocChunkSize() to tailor to your environment,
  17.             do not make the default too large, as the compiler
  18.             gets screwed on a 1M machine otherwise (stack/heap clash)
  19.      */
  20.  
  21. struct mem_chunk 
  22.     {
  23.     long valid;
  24. #define VAL_FREE  0xf4ee0abc
  25. #define VAL_ALLOC 0xa11c0abc
  26.  
  27.     struct mem_chunk *next;
  28.     long size;
  29.     };
  30.  
  31. /* linked list of free blocks */
  32.  
  33. static struct mem_chunk _mchunk_free_list = { VAL_FREE, NULL, 0L };
  34.  
  35. /* flag to control zero'ing of malloc'ed chunks */
  36. static int _ZeroMallocs = 0;
  37.  
  38.  
  39. #if 0
  40. asm(".text; .even; .globl _mlalloc; _mlalloc:"); /* dept of dirty tricks */
  41. #endif
  42.  
  43. void * malloc(n)
  44. size_t n; 
  45. {
  46.   struct mem_chunk *p, *q;
  47.   long sz;
  48.   extern void *_heapbase;
  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 ((_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.     p->next = q;
  79.     q->size = sz;
  80.     q->next = NULL;
  81.     q->valid = VAL_FREE;
  82.     }
  83.         
  84.   if (q->size > n + sizeof(struct mem_chunk))
  85.     {                /* split, leave part of free list */
  86.     q->size -= n;
  87.     q = (struct mem_chunk * )(((long) q) + q->size);
  88.     q->size = n;
  89.     q->valid = VAL_ALLOC;
  90.     }
  91.     else
  92.     {                /* just unlink it */
  93.     p->next = q->next;
  94.     q->valid = VAL_ALLOC;
  95.     }
  96.  
  97.   q->next = NULL;    
  98.   q++;    /* hand back ptr to after chunk desc */
  99.   if(_ZeroMallocs != 0)
  100.       bzero((void *)q, (size_t)(n - sizeof(struct mem_chunk)));
  101.   
  102.   return((void * )q);
  103. }
  104.  
  105. void free(param)
  106.     void *param;
  107. {
  108.   struct mem_chunk *o, *p, *q, *s;
  109.   struct mem_chunk *r = (struct mem_chunk *) param;
  110.   extern void *_heapbase;
  111.  
  112. /* free(NULL) should do nothing */
  113.   if (r == 0)
  114.      return;
  115.  
  116. /* move back to uncover the mem_chunk */
  117.   r--;            /* there it is! */
  118.  
  119.   if (r->valid != VAL_ALLOC)
  120.     return;
  121.  
  122.   r->valid = VAL_FREE;
  123.  
  124. /* stick it into free list, preserving ascending address order */
  125.   o = NULL;
  126.   p = &_mchunk_free_list;
  127.   q = _mchunk_free_list.next;
  128.   while (q != NULL && q < r) 
  129.     {
  130.     o = p;
  131.     p = q;
  132.     q = q->next;
  133.     }
  134.  
  135. /* merge after if possible */
  136.   s = (struct mem_chunk * )(((long) r) + r->size);
  137.   if (q != NULL && s >= q) 
  138.     {
  139.     assert(s == q);
  140.     r->size += q->size;
  141.     q = q->next;
  142.     s->size = 0;
  143.     s->next = NULL;
  144.     }
  145.   r->next = q;
  146.     
  147. /* merge before if possible, otherwise link it in */
  148.   s = (struct mem_chunk * )(((long) p) + p->size);
  149.   if (s >= r && p != &_mchunk_free_list)
  150.     /* remember: r may be below &_mchunk_free_list in memory */
  151.     {
  152.     assert(s == r);
  153.     p->size += r->size;
  154.     p->next = r->next;
  155.     r->size = 0;
  156.     r->next = NULL;
  157.     s = (struct mem_chunk * )(((long) p) + p->size);
  158.     if (_heapbase != NULL && s >= (struct mem_chunk *) _heapbase) {
  159.       assert(s == _heapbase);
  160.       _heapbase = (char *) p;
  161.       _stksize += p->size;
  162.       o->next = NULL;    /* o is always != NULL here */
  163.     }
  164.     }
  165.     else
  166.         {
  167.       s = (struct mem_chunk * )(((long) r) + r->size);
  168.       if (_heapbase != NULL && s >= (struct mem_chunk *) _heapbase) {
  169.         assert(s == _heapbase);
  170.         _heapbase = (char *) r;
  171.         _stksize += r->size;
  172.         p->next = NULL;
  173.       } else p->next = r;
  174.     }
  175. }
  176.  
  177. #if 0
  178. asm(".text; .even; .globl _relalloc,_realloc; _relalloc: jra _realloc");
  179. #ifdef NDEBUG
  180. static char *__dummy = ""; /* otherwise we get a bra with 0 offset above */
  181. #endif
  182. #endif
  183.  
  184. void * realloc(_r, n)
  185. void *_r;
  186. size_t n;
  187. {
  188.   struct mem_chunk *p, *q, *r = _r;
  189.   long sz;
  190.  
  191. /* obscure features: realloc(NULL,n) is the same as malloc(n)
  192.  *               realloc(p, 0) is the same as free(p)
  193.  */
  194.   if (!r)
  195.     return malloc(n);
  196.   if (n == 0) {
  197.     free(_r);
  198.     return NULL;
  199.   }
  200.   p = r - 1;
  201.   sz = (n + sizeof(struct mem_chunk) + 7) & ~7;
  202.  
  203.   if (p->size > sz) 
  204.     {            /* block too big, split in two */
  205.     q = (struct mem_chunk * )(((long) p) + sz);
  206.     q->size = p->size - sz;
  207.         q->valid = VAL_ALLOC;
  208.     free(q + 1);
  209.     p->size = sz;
  210.     }
  211.     else 
  212.   if (p->size < sz)
  213.     {            /* block too small, get new one */
  214.     struct mem_chunk *s, *t;
  215.     q = &_mchunk_free_list;
  216.     t = _mchunk_free_list.next;
  217.     while (t != NULL && t < p)
  218.       {
  219.       q = t;
  220.       t = t->next;
  221.       }
  222.  
  223.     /* merge after if possible */
  224.     s = (struct mem_chunk * )(((long) p) + p->size);
  225.     if (t != NULL && s >= t && p->size + t->size >= sz)
  226.       {
  227.       assert(s == t);
  228.       p->size += t->size;
  229.       q->next = t->next;
  230.       t->size = 0;
  231.       t->next = NULL;
  232.       }
  233.     else
  234.       {
  235.       q = (struct mem_chunk * )malloc(n);
  236.       if (q != NULL)
  237.     {
  238.     n = p->size - sizeof(struct mem_chunk);
  239.     bcopy(r, q, n);
  240.         free(r);    /* free r only if we got a new block */
  241.         }
  242.       r = q;
  243.     }
  244.   }
  245.   /* else current block will do just fine */
  246.   return((void * )r);
  247. }
  248.  
  249. #if 0
  250. asm(".text; .even; .globl _clalloc; _clalloc:");
  251. #endif
  252.  
  253. void * calloc(n, sz)
  254. size_t n, sz;
  255. {
  256.   char *r;
  257.   size_t total;
  258.  
  259.   total = n * sz;
  260.   if ((r = malloc(total)) != NULL) {
  261.     bzero(r, total);
  262.   }
  263.   return(r);
  264. }
  265.  
  266. /*
  267.  * Set zero block after malloc flag
  268.  */
  269. void _malloczero(yes)
  270. int yes;
  271. {
  272.     _ZeroMallocs = yes;
  273. }
  274.  
  275. /*
  276.  * tune chunk size
  277.  */
  278. void _mallocChunkSize (siz)
  279. size_t siz;
  280. {
  281.     MAXHUNK = MINHUNK = siz;
  282. }
  283.