|
|
1.1 root 1: /* garbage collecting storage allocator; definition of
2: * cell is compatible with malloc, but slightly less portable
3: */
4:
5: typedef struct dummy { struct dummy *ptr;} cell;
6:
7: #define GCMAX 5000
8: #define GCMIN 50
9: #define BPW (8*sizeof(*gcmap)) /*bits per word*/
10: #define QBPW >>LOGBPW /* quotient /BPW if BPW not power of 2 */
11: #define RBPW &(BPW-1) /* remainder %BPW if BPW not power of 2 */
12: #define MASK (sizeof(cell)-1) /*assumes cell aligned to power of 2*/
13: #define testbit(b,n) ((b[(n) QBPW]>>((n) RBPW))&1)
14: #define setbit(b,n) (b[(n) QBPW]|=1<<((n) RBPW))
15: #define clrbit(b,n) (b[(n) QBPW]&=~(1<<((n) RBPW)))
16: #define testbusy(p) (*(int*)((p)-1)&1)
17: #define clearbusy(p) (*(int*)((p)-1)&=~1)
18: #define setbusy(p) (*(int*)((p)-1)|=1)
19: #define endptr(p) (cell*)(*(int*)((p)-1)&~1)
20:
21: #ifdef pdp11
22: #define STACKTOP (cell*)(-2)
23: #define STATICBOT (cell*)2 /*appropriate for cc -i*/
24: #define LOGBPW 4
25: #endif
26: #ifdef vax
27: #define STACKTOP (cell*)0x7ffffffc
28: #define STATICBOT etext
29: #define LOGBPW 5
30: #endif
31: #define STATICTOP end
32:
33: static unsigned *gcmap; /*bitmap of busy blocks, grows by powers of 2*/
34: static unsigned gcsize; /*number of bits in gcmap*/
35: long gcmax = GCMAX; /*max number of allocations between collections*/
36: long gcmin = GCMIN; /*min number*/
37: extern cell end[];
38: extern cell etext[];
39:
40: char *
41: galloc(n)
42: unsigned n;
43: {
44: static long count; /*number of allocations since collection*/
45: register cell* q;
46: register unsigned d;
47: unsigned qd;
48: char *malloc();
49: while(++count >= gcmax ||
50: (q=(cell*)malloc(n)) == 0) { /* at most twice*/
51: if(count <= gcmin)
52: return(0);
53: garbage();
54: count = 0;
55: }
56: if(q < STATICTOP) /* probably due to ialloc() */
57: return((char*)q);
58: qd = q - STATICTOP;
59: if(qd >= gcsize) {
60: unsigned *tgmap;
61: register unsigned bsize;
62: if(BPW != 1<<LOGBPW)
63: abort();
64: if(gcsize==0) {
65: bsize = 16384 QBPW;
66: tgmap = (unsigned*)malloc(bsize*sizeof(*gcmap));
67: } else {
68: bsize = (gcsize QBPW)*2;
69: tgmap = (unsigned*)realloc((char*)gcmap,
70: bsize*sizeof(*gcmap));
71: }
72: if(tgmap==0)
73: return(0);
74: gcmap = tgmap;
75: for(d=gcsize QBPW; d<bsize; d++)
76: gcmap[d] = 0;
77: gcsize = bsize*BPW;
78: }
79: setbit(gcmap, qd);
80: return((char *)q);
81: }
82:
83: /* pointer reversal algorithm
84: * gcmap bit is set for first word of each galloc'ed block
85: * make all galloc'd blocks appear idle and mark them busy as
86: * the garbage collector reaches them
87: */
88: garbage()
89: {
90: cell fence; /* must really be on the stack*/
91: register cell *p, *q;
92: register unsigned d;
93: register cell *s, *t, *u; /* lots of regs to force full save */
94: register unsigned asize;
95: asize = (cell*)sbrk(0) - STATICTOP;
96: if(asize > gcsize)
97: asize = gcsize;
98: for(d=0; d<asize; d++)
99: if(testbit(gcmap,d))
100: clearbusy(STATICTOP+d);
101: q = 0;
102: for(s=STATICBOT; s<STACKTOP; s=(s==STATICTOP-1?&fence:s+1)) {
103: p = s->ptr;
104: for(;;) {
105: while(!((int)p&MASK) && /*is p a cell-aligned address?*/
106: p>=STATICTOP && /* pointing within */
107: (d=p-STATICTOP)<asize && /* bounds of arena? */
108: testbit(gcmap, d) && /*to galloc-ed block?*/
109: !testbusy(p)) { /* not yet visited?*/
110: setbusy(p);
111: /* q,p,*p = p,*p,q */
112: t = p;
113: p = p->ptr;
114: t->ptr = q;
115: q = t;
116: }
117: while(q!=0) {
118: for(d=q-STATICTOP; !testbit(gcmap,d); d--)
119: continue;
120: if(q<endptr(t=STATICTOP+d)-1)
121: break;
122: /* q,*q,p = *q,p,t */
123: u = q;
124: q = q->ptr;
125: u->ptr = p;
126: p = t;
127: }
128: if(q==0)
129: break;
130: /* *q,p,q[1] = p,q[1],*q; q++ */
131: t = q->ptr;
132: q->ptr = p;
133: q++;
134: p = q->ptr;
135: q->ptr = t;
136: }
137: }
138: for(d=0; d<asize; d++) {
139: if(testbit(gcmap,d)&&!testbusy(STATICTOP+d))
140: clrbit(gcmap,d);
141: }
142: }
143:
144: gfree(p)
145: cell *p;
146: {
147: free((char*)p);
148: clrbit(gcmap,p-STATICTOP);
149: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.