BSD 4 release
[unix-history] / usr / src / cmd / px / malloc.c
CommitLineData
31cef89c
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2
3static char sccsid[] = "@(#)malloc.c 4.1 10/10/80";
4
5/*
6 * Patched up version of malloc to do an integrity check
7 * on each allocation or free.
8 */
9
b202b2da
CH
10#ifdef debug
11#define ASSERT(p,t) if(!(p))return(t(TRASHED));else
12#else
13#define ASSERT(p,t)
14#endif
15
16/* avoid break bug */
17#ifdef pdp11
18#define GRANULE 64
19#else
20#define GRANULE 0
21#endif
22/* C storage allocator
23 * circular first-fit strategy
24 * works with noncontiguous, but monotonically linked, arena
25 * each block is preceded by a ptr to the (pointer of)
26 * the next following block
27 * blocks are exact number of words long
28 * aligned to the data type requirements of ALIGN
29 * pointers to blocks must have BUSY bit 0
30 * bit in ptr is 1 for busy, 0 for idle
31 * gaps in arena are merely noted as busy blocks
32 * last block of arena (pointed to by alloct) is empty and
33 * has a pointer to first
34 * idle blocks are coalesced during space search
35 *
36 * a different implementation may need to redefine
37 * ALIGN, NALIGN, BLOCK, BUSY, INT
38 * where INT is integer type to which a pointer can be cast
39*/
40#define INT int
41#define ALIGN int
42#define NALIGN 1
43#define WORD sizeof(union store)
44#define BLOCK 1024 /* a multiple of WORD*/
45#define BUSY 1
46#define NULL 0
47#define TRASHED -1
48#define testbusy(p) ((INT)(p)&BUSY)
49#define setbusy(p) (union store *)((INT)(p)|BUSY)
50#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
51
52union store { union store *ptr;
53 ALIGN dummy[NALIGN];
54 int calloc; /*calloc clears an array of integers*/
55};
56
57static union store allocs[2]; /*initial arena*/
58static union store *allocp; /*search ptr*/
59static union store *alloct; /*arena top*/
b202b2da
CH
60char *sbrk();
61
62char *
63malloc(nbytes)
31cef89c
BJ
64
65 unsigned nbytes;
b202b2da
CH
66{
67 register union store *p, *q;
68 register nw;
69 static temp; /*coroutines assume no auto*/
70
71 if(allocs[0].ptr==0) { /*first time*/
72 allocs[0].ptr = setbusy(&allocs[1]);
73 allocs[1].ptr = setbusy(&allocs[0]);
74 alloct = &allocs[1];
75 allocp = &allocs[0];
76 }
77 nw = (nbytes+WORD+WORD-1)/WORD;
78 ASSERT(allocp>=allocs && allocp<=alloct,(char *));
79 ASSERT(allock(),(char *));
80 for(p=allocp; ; ) {
81 for(temp=0; ; ) {
82 if(!testbusy(p->ptr)) {
83 while(!testbusy((q=p->ptr)->ptr)) {
84 ASSERT(q>p&&q<alloct,(char *));
85 p->ptr = q->ptr;
86 }
87 if(q>=p+nw && p+nw>=p)
88 goto found;
89 }
90 q = p;
91 p = clearbusy(p->ptr);
92 if(p>q)
93 ASSERT(p<=alloct,(char *));
94 else if(q!=alloct || p!=allocs) {
95 ASSERT(q==alloct&&p==allocs,(char *));
96 return(NULL);
97 } else if(++temp>1)
98 break;
99 }
100 temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD);
101 q = (union store *)sbrk(0);
102 if(q+temp+GRANULE < q) {
103 return(NULL);
104 }
105 q = (union store *)sbrk(temp*WORD);
106 if((INT)q == -1) {
107 return(NULL);
108 }
109 ASSERT(q>alloct,(char *));
110 alloct->ptr = q;
111 if(q!=alloct+1)
112 alloct->ptr = setbusy(alloct->ptr);
113 alloct = q->ptr = q+temp-1;
114 alloct->ptr = setbusy(allocs);
115 }
116found:
117 allocp = p + nw;
118 ASSERT(allocp<=alloct,(char *));
119 if(q>allocp) {
b202b2da
CH
120 allocp->ptr = p->ptr;
121 }
122 p->ptr = setbusy(allocp);
123 return((char *)(p+1));
124}
125
31cef89c
BJ
126/*
127 * freeing strategy tuned for LIFO allocation
128 */
129
b202b2da 130free(ap)
31cef89c
BJ
131
132 register char *ap;
b202b2da
CH
133{
134 register union store *p = (union store *)ap;
135
136 ASSERT(p != 0,(long));
137 ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct,(long));
138 ASSERT(allock(),(long));
139 allocp = --p;
140 ASSERT(testbusy(p->ptr),(long));
141 p->ptr = clearbusy(p->ptr);
142 ASSERT(p->ptr > allocp && p->ptr <= alloct,(long));
143 return(NULL);
144}
145
b202b2da
CH
146#ifdef debug
147allock()
148{
149#ifdef longdebug
150 register union store *p;
151 int x;
152 x = 0;
153 for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) {
154 if(p==allocp)
155 x++;
156 }
157 ASSERT(p==alloct,(long));
158 return(x==1|p==allocp);
159#else
160 return(1);
161#endif
162}
163#endif