123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #include "stdafx.h"
- #include "defs.h"
- // up to 100 blocks of 100,000 atoms (old)
- // up to 1000 blocks of 100 atoms
- #define M 100
- #define N 100
- U **mem;
- int mcount;
- U *free_list;
- int free_count;
- U *
- alloc(void)
- {
- U *p;
- if (free_count == 0) {
- if (mcount == 0)
- alloc_mem();
- else {
- gc();
- if (free_count < N * mcount / 2)
- alloc_mem();
- }
- if (free_count == 0)
- stop("atom space exhausted");
- }
- p = free_list;
- free_list = free_list->u.cons.cdr;
- free_count--;
- return p;
- }
- U *
- alloc_tensor(int nelem)
- {
- int i;
- U *p;
- p = alloc();
- p->k = TENSOR;
- p->u.tensor = (T *) malloc(sizeof (T) + nelem * sizeof (U *));
- if (p->u.tensor == NULL)
- out_of_memory();
- p->u.tensor->nelem = nelem;
- for (i = 0; i < nelem; i++)
- p->u.tensor->elem[i] = zero;
- return p;
- }
- // garbage collector
- void
- gc(void)
- {
- int i, j;
- U *p;
- // tag everything
- for (i = 0; i < mcount; i++) {
- p = mem[i];
- for (j = 0; j < N; j++)
- p[j].tag = 1;
- }
- // untag what's used
- untag(p0);
- untag(p1);
- untag(p2);
- untag(p3);
- untag(p4);
- untag(p5);
- untag(p6);
- untag(p7);
- untag(p8);
- untag(p9);
- untag(one);
- untag(zero);
- untag(imaginaryunit);
- for (i = 0; i < NSYM; i++) {
- untag(binding[i]);
- untag(arglist[i]);
- }
- for (i = 0; i < tos; i++)
- untag(stack[i]);
- for (i = (int) (frame - stack); i < TOS; i++)
- untag(stack[i]);
- // collect everything that's still tagged
- free_count = 0;
- for (i = 0; i < mcount; i++) {
- p = mem[i];
- for (j = 0; j < N; j++) {
- if (p[j].tag == 0)
- continue;
- // still tagged so it's unused, put on free list
- switch (p[j].k) {
- case TENSOR:
- free(p[j].u.tensor);
- break;
- case STR:
- free(p[j].u.str);
- break;
- case NUM:
- mfree(p[j].u.q.a);
- mfree(p[j].u.q.b);
- break;
- }
- p[j].k = CONS; // so no double free occurs above
- p[j].u.cons.cdr = free_list;
- free_list = p + j;
- free_count++;
- }
- }
- }
- void
- untag(U *p)
- {
- int i;
- if (iscons(p)) {
- do {
- if (p->tag == 0)
- return;
- p->tag = 0;
- untag(p->u.cons.car);
- p = p->u.cons.cdr;
- } while (iscons(p));
- untag(p);
- return;
- }
- if (p->tag) {
- p->tag = 0;
- if (istensor(p)) {
- for (i = 0; i < p->u.tensor->nelem; i++)
- untag(p->u.tensor->elem[i]);
- }
- }
- }
- // get memory for 100,000 atoms
- void
- alloc_mem(void)
- {
- int i;
- U *p;
- if (mcount == M)
- return;
- p = (U *) malloc(N * sizeof (struct U));
- if (p == NULL)
- return;
- mem[mcount++] = p;
- for (i = 0; i < N; i++) {
- p[i].k = CONS; // so no free in gc
- p[i].u.cons.cdr = p + i + 1;
- }
- p[N - 1].u.cons.cdr = free_list;
- free_list = p;
- free_count += N;
- }
- void
- print_mem_info(void)
- {
- char buf[100];
- sprintf(buf, "%d blocks (%d bytes/block)", N * mcount, (int) sizeof (U));
- printstr(buf);
- sprintf(buf, "%d free", free_count);
- printstr(buf);
- sprintf(buf, "%d used", N * mcount - free_count);
- printstr(buf);
- }
|