home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / rc / part04 / nalloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  2.2 KB  |  119 lines

  1. /* nalloc.c: a simple single-arena allocator for command-line-lifetime allocation */
  2.  
  3. #include "rc.h"
  4. #include "utils.h"
  5. #include "nalloc.h"
  6.  
  7. static struct Block {
  8.     SIZE_T used;
  9.     SIZE_T size;
  10.     char *mem;
  11.     Block *n;
  12. } *fl, *ul;
  13.  
  14. /* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */
  15. #define alignto(m, n)   ((m + n - 1) & ~(n - 1))
  16. #define BLOCKSIZE 4096
  17.  
  18. /* gets a block from malloc space and places it at the head of the used-list */
  19.  
  20. static void getblock(SIZE_T n) {
  21.     Block *r, *p;
  22.  
  23.     for (r = fl, p = NULL; r != NULL; p = r, r = r->n)
  24.         if (n <= r->size)
  25.             break;
  26.  
  27.     if (r != NULL) {
  28.         if (p != NULL)
  29.             p->n = r->n;
  30.         else
  31.             fl = r->n;
  32.     } else {
  33.         r = enew(Block);
  34.         r->mem = ealloc(alignto(n, BLOCKSIZE));
  35.         r->size = alignto(n, BLOCKSIZE);
  36.     }
  37.  
  38.     r->used = 0;
  39.     r->n = ul;
  40.     ul = r;
  41. }
  42.  
  43. /*
  44.    A fast single-arena allocator. Looks at the current block, and if there is not enough room,
  45.    it goes to getblock() for more. "ul" stands for "used list", and the head of the list is the
  46.    current block.
  47. */
  48.  
  49. void *nalloc(SIZE_T n) {
  50.     char *ret;
  51.  
  52.         n = alignto(n, sizeof (ALIGN_T));
  53.  
  54.     if (ul == NULL || n + ul->used >= ul->size)
  55.         getblock(n);
  56.  
  57.     ret = ul->mem + ul->used;
  58.     ul->used += n;
  59.     return ret;
  60. }
  61.  
  62. /*
  63.    Frees memory from nalloc space by putting it on the freelist. Returns free blocks to the
  64.    system, retaining at least MAXMEM bytes worth of blocks for nalloc.
  65. */
  66.  
  67. #define MAXMEM 500000
  68.  
  69. void nfree() {
  70.     Block *r;
  71.     SIZE_T count;
  72.  
  73.     if (ul == NULL)
  74.         return;
  75.  
  76.     for (r = ul; r->n != NULL; r = r->n)
  77.         ;
  78.  
  79.     r->n = fl;
  80.     fl = ul;
  81.     ul = NULL;
  82.  
  83.     for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) {
  84.         if (count >= MAXMEM) {
  85.             Block *tmp = r;
  86.  
  87.             r = r->n;
  88.             tmp->n = NULL;        /* terminate the freelist */
  89.  
  90.             while (r != NULL) {    /* free memory off the tail of the freelist */
  91.                 tmp = r->n;
  92.                 efree(r->mem);
  93.                 efree(r);
  94.                 r = tmp;
  95.             }
  96.         return;
  97.         }
  98.     }
  99. }
  100.  
  101. /*
  102.    "allocates" a new arena by zeroing out the old one. Up to the calling routine to keep
  103.    the old value of the block around.
  104. */
  105.  
  106. Block *newblock() {
  107.     Block *ret = ul;
  108.  
  109.     ul = NULL;
  110.     return ret;
  111. }
  112.  
  113. /* "restores" an arena to its saved value. */
  114.  
  115. void restoreblock(Block *b) {
  116.     nfree();
  117.     ul = b;
  118. }
  119.