home *** CD-ROM | disk | FTP | other *** search
- /* alloc.c: a simple single-arena allocator for command-line-lifetime allocation */
-
- #include "pico.h"
-
- typedef struct Block Block;
-
- static struct Block {
- size_t used, size;
- char *mem;
- Block *n;
- } *fl, *ul;
-
- /* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */
- #define alignto(m, n) ((m + n - 1) & ~(n - 1))
- #define BLOCKSIZE ((size_t) 4096)
-
- extern void *ealloc(size_t n) {
- extern void *malloc(size_t);
- void *p = malloc(n);
- if (p == NULL) {
- perror("malloc");
- exit(1);
- }
- return p;
- }
-
- /* gets a block from malloc space and places it at the head of the used-list */
-
- static void getblock(size_t n) {
- Block *r, *p;
-
- for (r = fl, p = NULL; r != NULL; p = r, r = r->n)
- if (n <= r->size)
- break;
-
- if (r != NULL) {
- if (p != NULL)
- p->n = r->n;
- else
- fl = r->n;
- } else {
- r = ealloc(sizeof *r);
- r->mem = ealloc(alignto(n, BLOCKSIZE));
- r->size = alignto(n, BLOCKSIZE);
- }
-
- r->used = 0;
- r->n = ul;
- ul = r;
- }
-
- /*
- A fast single-arena allocator. Looks at the current block, and if there is not enough room,
- it goes to getblock() for more. "ul" stands for "used list", and the head of the list is the
- current block.
- */
-
- extern void *alloc(size_t n) {
- char *ret;
- n = alignto(n, sizeof (size_t)); /* a good guess about how to align data? */
- if (ul == NULL || n + ul->used >= ul->size)
- getblock(n);
- ret = ul->mem + ul->used;
- ul->used += n;
- return ret;
- }
-
- /*
- Frees memory from nalloc space by putting it on the freelist. Returns free blocks to the
- system, retaining at least MAXMEM bytes worth of blocks for nalloc.
- */
-
- #define MAXMEM 500000
-
- extern void afree() {
- Block *r;
- size_t count;
- if (ul == NULL)
- return;
- for (r = ul; r->n != NULL; r = r->n)
- ;
- r->n = fl;
- fl = ul;
- ul = NULL;
- for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) {
- if (count >= MAXMEM) {
- Block *tmp = r;
- r = r->n;
- tmp->n = NULL; /* terminate the freelist */
- while (r != NULL) { /* free memory off the tail of the freelist */
- tmp = r->n;
- free(r->mem);
- free(r);
- r = tmp;
- }
- return;
- }
- }
- }
-