home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / C / DLIBSSRC.ZIP / MALLOC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-10-02  |  4.6 KB  |  182 lines

  1. #include <osbind.h>
  2. #include <stdio.h>
  3. #include <malloc.h>
  4.  
  5. #define    MAXBLK        16
  6. #define    FREE        0x00
  7. #define    USED        0x80
  8. #define    NULLBLK        0x80000000L
  9.  
  10. char    *_mblk[MAXBLK] = {        /* system memory heaps */
  11.     NULL, NULL, NULL, NULL,
  12.     NULL, NULL, NULL, NULL,
  13.     NULL, NULL, NULL, NULL,
  14.     NULL, NULL, NULL, NULL };
  15.  
  16. long    _msiz[MAXBLK] = {        /* allocated heap sizes */
  17.     0L, 0L, 0L, 0L,
  18.     0L, 0L, 0L, 0L,
  19.     0L, 0L, 0L, 0L,
  20.     0L, 0L, 0L, 0L };
  21.  
  22. /*
  23.  *    Up to 16 heaps are allocated from the operating system as they are
  24.  *    needed to fill requests for dynamic memory.  These heaps are them
  25.  *    divided into blocks for parcelling out by the user-callable memory
  26.  *    allocation routines.  If all the storage in a heap is freed, the heap
  27.  *    will be freed to the OS.  Each heap beings with a pointer to the first
  28.  *    free block, or NULL if there are no free blocks in this heap.  Each
  29.  *    block begins with a 4-byte header which defines the number of bytes
  30.  *    in the block, including the header.  Since blocks in a heap are known
  31.  *    to be contiguous, this value also defines the beginning of the next
  32.  *    block in the heap.  The high bit of the header is set if the block
  33.  *    is used and clear if it is free.  The heaps ends with a block header
  34.  *    which indicates a used block containing 0 bytes.  The is the constant
  35.  *    value NULLBLK.  Free blocks contain an additional pointer field,
  36.  *    immediatly following the header, which is a pointer to the header of
  37.  *    the next free block, or NULL.
  38.  */
  39.  
  40. static char *makeblk(size)
  41. long size;
  42. /*
  43.  *    Get a new major block from the system that will hold at least
  44.  *    <size> bytes.
  45.  */
  46. {
  47.     register int i;
  48.     register char *p;
  49.     register long n, minsiz, bsiz, *q;
  50.  
  51.     minsiz = (size + 0x200L) & ~0x1FFL;    /* round up to nearest 512 */
  52.     if(minsiz < _BLKSIZ)
  53.         bsiz = _BLKSIZ;
  54.     else
  55.         bsiz = minsiz;
  56.     for(i=0; i<MAXBLK; ++i) {
  57.         if(_mblk[i] != NULL)
  58.             continue;        /* skip used heaps */
  59.         n = Malloc(-1L);
  60.         n = ~0x1FFL & (n - 512L);    /* system memory available */
  61.         if(n < bsiz) {
  62.             if(n < minsiz)
  63.                 return(NULL);
  64.             else
  65.                 bsiz = minsiz;
  66.         }
  67.         _mblk[i] = p = Malloc(bsiz);
  68.         _msiz[i] = bsiz;
  69.         q = p + bsiz;            /* thread starting blocks */
  70.         q[-1] = NULLBLK;
  71.         q = p + 4L;
  72.         q[-1] = q;
  73.         q[0] = bsiz - 8L;
  74.         q[1] = NULL;
  75.         p[4] = FREE;
  76.         return(p);
  77.     }
  78.     return(NULL);
  79. }
  80.  
  81. static char *splitblk(addr, size)
  82. register long **addr;
  83. register long size;
  84. /*
  85.  *    Split block at *<addr> into a used block containing <size> bytes
  86.  *    and a free block containing the remainder.
  87.  */
  88. {
  89.     register long n, *p, *q;
  90.  
  91.     n = *(p = *addr);            /* get actual block size */
  92.     if(n > (size + 8L)) {            /* is it worth splitting? */
  93.         n -= size;
  94.         q = ((char *) p) + size;    /* calculate "break" point */
  95.         p[0] = size;
  96.         q[0] = n;
  97.         q[1] = p[1];
  98.         *addr = q;
  99.     }
  100.     else                    /* not worth splitting */
  101.         *addr = p[1];            /* remove from free list */
  102.     *((char *) p) = USED;            /* mark block "used" */
  103.     return(p);
  104. }
  105.  
  106. static char *findblk(size)
  107. register long size;
  108. /*
  109.  *    Find the smallest unused block containing at least <size> bytes.
  110.  */
  111. {
  112.     register int i;
  113.     register long n, tsiz = 0x7FFFFFFFL, **p, *q, *tptr = NULL;
  114.  
  115.     for(i=0; i<MAXBLK; ++i) {
  116.         if((p = _mblk[i]) == NULL)
  117.             continue;        /* skip unavailable heaps */
  118.         while(q = *p) {
  119.             n = *q;
  120.             if((n >= size) && (n < tsiz)) {        /* it fits */
  121.                 tsiz = n;
  122.                 tptr = p;
  123.             }
  124.             p = q + 1;
  125.         }
  126.     }
  127.     return(tptr);
  128. }
  129.  
  130. /*--------------------- Documented Functions ---------------------------*/
  131.  
  132. char *lalloc(size)
  133. register long size;
  134. /*
  135.  *    Allocate at least <size> bytes of memory.  A pointer to the
  136.  *    requested block is returned, or NULL if there is not enough
  137.  *    free memory available.
  138.  */
  139. {
  140.     register char *p;
  141.  
  142.     if (size <= 4L)
  143.         size = 8L;            /* minimum allocation */
  144.     else
  145.         size = (size + 5L) & ~1L;    /* header & alignment */
  146.     if((p = findblk(size)) == NULL)
  147.         if((p = makeblk(size)) == NULL)
  148.             return(NULL);
  149.     p = splitblk(p, size);
  150.     return(p + 4);            /* skip over header */
  151. }
  152.  
  153. char *malloc(size)
  154. unsigned int size;
  155. /*
  156.  *    Allocate at least <size> bytes of memory.  A pointer to the
  157.  *    requested block is returned, or NULL if there is not enough
  158.  *    free memory available.
  159.  */
  160. {
  161.     return(lalloc((long) size));
  162. }
  163.  
  164. char *calloc(n, size)
  165. unsigned int n;
  166. unsigned int size;
  167. /*
  168.  *    Allocate space for an array of <n> element of <size> bytes each.
  169.  *    If the storage can be allocated, it is initialized to all zero.
  170.  *    NULL is returned is there is not enough free memory.
  171.  */
  172. {
  173.     register long total;
  174.     register char *p, *q;
  175.  
  176.     total = (((long) n) * ((long) size));
  177.     if(p = lalloc(total))
  178.         for(q=p; total--; *q++ = 0)
  179.             ;
  180.     return(p);
  181. }
  182.