home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / pico / part01 / alloc.c next >
Encoding:
C/C++ Source or Header  |  1991-12-14  |  2.1 KB  |  100 lines

  1. /* alloc.c: a simple single-arena allocator for command-line-lifetime allocation */
  2.  
  3. #include "pico.h"
  4.  
  5. typedef struct Block Block;
  6.  
  7. static struct Block {
  8.     size_t used, size;
  9.     char *mem;
  10.     Block *n;
  11. } *fl, *ul;
  12.  
  13. /* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */
  14. #define alignto(m, n)   ((m + n - 1) & ~(n - 1))
  15. #define BLOCKSIZE ((size_t) 4096)
  16.  
  17. extern void *ealloc(size_t n) {
  18.     extern void *malloc(size_t);
  19.     void *p = malloc(n);
  20.     if (p == NULL) {
  21.         perror("malloc");
  22.         exit(1);
  23.     }
  24.     return p;
  25. }
  26.  
  27. /* gets a block from malloc space and places it at the head of the used-list */
  28.  
  29. static void getblock(size_t n) {
  30.     Block *r, *p;
  31.  
  32.     for (r = fl, p = NULL; r != NULL; p = r, r = r->n)
  33.         if (n <= r->size)
  34.             break;
  35.  
  36.     if (r != NULL) {
  37.         if (p != NULL)
  38.             p->n = r->n;
  39.         else
  40.             fl = r->n;
  41.     } else {
  42.         r = ealloc(sizeof *r);
  43.         r->mem = ealloc(alignto(n, BLOCKSIZE));
  44.         r->size = alignto(n, BLOCKSIZE);
  45.     }
  46.  
  47.     r->used = 0;
  48.     r->n = ul;
  49.     ul = r;
  50. }
  51.  
  52. /*
  53.    A fast single-arena allocator. Looks at the current block, and if there is not enough room,
  54.    it goes to getblock() for more. "ul" stands for "used list", and the head of the list is the
  55.    current block.
  56. */
  57.  
  58. extern void *alloc(size_t n) {
  59.     char *ret;
  60.         n = alignto(n, sizeof (size_t)); /* a good guess about how to align data? */
  61.     if (ul == NULL || n + ul->used >= ul->size)
  62.         getblock(n);
  63.     ret = ul->mem + ul->used;
  64.     ul->used += n;
  65.     return ret;
  66. }
  67.  
  68. /*
  69.    Frees memory from nalloc space by putting it on the freelist. Returns free blocks to the
  70.    system, retaining at least MAXMEM bytes worth of blocks for nalloc.
  71. */
  72.  
  73. #define MAXMEM 500000
  74.  
  75. extern void afree() {
  76.     Block *r;
  77.     size_t count;
  78.     if (ul == NULL)
  79.         return;
  80.     for (r = ul; r->n != NULL; r = r->n)
  81.         ;
  82.     r->n = fl;
  83.     fl = ul;
  84.     ul = NULL;
  85.     for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) {
  86.         if (count >= MAXMEM) {
  87.             Block *tmp = r;
  88.             r = r->n;
  89.             tmp->n = NULL;        /* terminate the freelist */
  90.             while (r != NULL) {    /* free memory off the tail of the freelist */
  91.                 tmp = r->n;
  92.                 free(r->mem);
  93.                 free(r);
  94.                 r = tmp;
  95.             }
  96.         return;
  97.         }
  98.     }
  99. }
  100.