|
|
1.1 root 1: /* C storage allocator
2: * circular first-fit strategy
3: * works with noncontiguous, but monotonically linked, arena
4: * each block is preceded by a ptr to the (pointer of)
5: * the next following block
6: * blocks are exact number of words long; BUSY
7: * bit in ptr is 1 for busy, 0 for idle
8: * gaps in arena are merely noted as busy blocks
9: * last block of arena (pointed to by alloct) is empty and
10: * has a pointer to first
11: * idle blocks are coalesced during space search
12: */
13:
14: #include <stdio.h>
15:
16: /* all these defines must be powers of 2 */
17: #define WORD sizeof(struct store)
18: #define BLOCK 1024
19: #define BUSY 1
20: #define NULL 0
21: #define testbusy(p) ((int)(p)&BUSY)
22: #define setbusy(p) (struct store *)((int)(p)+BUSY)
23: #define clearbusy(p) (struct store *)((int)(p)&~BUSY)
24:
25: /*
26: #define debug YES
27: */
28:
29: #ifndef debug
30: #define ASSERT(p)
31: #endif
32:
33: #ifdef debug
34: #define ASSERT(p) if(!(p))botch("p");else
35:
36: botch(s) char *s;
37: {
38: fatal(119,s);
39: }
40: #endif
41:
42: struct store { struct store *ptr; };
43:
44: struct store allocs[] = { /*initial arena*/
45: setbusy(&allocs[1].ptr),
46: setbusy(&allocs[0].ptr)
47: };
48: struct store *allocp = &allocs[1]; /*search ptr*/
49: struct store *alloct = &allocs[1]; /*arena top*/
50: struct store *allocx = 0; /*for benefit of realloc*/
51: struct store *sbrk();
52:
53: struct store *
54: malloc(nbytes)
55: unsigned nbytes;
56: {
57: struct store *p, *q;
58: register nw;
59: static temp; /*coroutines assume no auto*/
60:
61: #ifdef verbose
62: printf("malloc(%d) ",nbytes);
63: #endif
64: nw = (nbytes+2*WORD-1)/WORD;
65: ASSERT(allocp>allocs && allocp<=alloct);
66: for(p=allocp; ; ) {
67: for(temp=0; ; ) {
68: if(!testbusy(p->ptr)) {
69: while(!testbusy((q=p->ptr)->ptr)) {
70: ASSERT(q>p&&q<alloct);
71: p->ptr = q->ptr;
72: }
73: if(q>=p+nw && p+nw>=p)
74: goto found;
75: }
76: q = p;
77: p = clearbusy(p->ptr);
78: if(p>q)
79: ASSERT(p<=alloct);
80: else if(q!=alloct || p!=allocs) {
81: fatal(119,"dballoc");
82: } else if(++temp>1)
83: break;
84: }
85: temp = (nw+BLOCK/WORD)&~(BLOCK/WORD-1);
86: q = sbrk(temp*WORD); /*SYSDEP*/
87: if((int)q == -1)
88: return(NULL);
89: ASSERT(q>alloct);
90: alloct->ptr = q;
91: if(q!=alloct+1)
92: alloct->ptr = setbusy(alloct->ptr);
93: alloct = q->ptr = q+temp-1;
94: alloct->ptr = setbusy(allocs);
95: }
96: found:
97: allocp = p + nw;
98: ASSERT(allocp<=alloct);
99: if(q>allocp) {
100: allocx = allocp->ptr;
101: allocp->ptr = p->ptr;
102: }
103: p->ptr = setbusy(allocp);
104: #ifdef verbose
105: printf("= %o\n",p+1);
106: #endif
107: return(p+1);
108: }
109:
110: /*
111: * freeing strategy tuned for LIFO allocation
112: */
113: free(p)
114: struct store *p;
115: {
116: struct store *savep=p;
117: #ifdef verbose
118: printf("free(%o)\n",p);
119: #endif
120: ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct);
121: allocp = --p;
122: ASSERT(testbusy(p->ptr));
123: p->ptr = clearbusy(p->ptr);
124: ASSERT(p->ptr > allocp && p->ptr <= alloct);
125: }
126:
127: char *calloc(nbytes,count)
128: { char *c;
129: c=(char *)malloc(nbytes*count);
130: return(c);
131: }
132:
133: struct store *
134: realloc(p, nbytes)
135: register struct store *p;
136: unsigned nbytes;
137: {
138: register struct store *q;
139: struct store *s, *t;
140: register unsigned nw;
141: unsigned onw;
142:
143: onw = p[-1].ptr - p;
144: q = malloc(nbytes);
145: if(q==NULL || q==p)
146: return(q);
147: s = p;
148: t = q;
149: nw = (nbytes+WORD-1)/WORD;
150: if(nw<onw)
151: onw = nw;
152: while(onw--!=0)
153: (t++)->ptr = (s++)->ptr;
154: if(q<p && q+nw>=p)
155: (q+(q+nw-p))->ptr = allocx;
156: return(q);
157: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.