3 /* replace undef by define */
4 #undef DEBUG /* check assertions */
5 #undef SLOWDEBUG /* some extra test loops (requires DEBUG) */
16 #if _EM_WSIZE == _EM_PSIZE
27 #define PTRSIZE ((int) sizeof(void *))
28 #define Align(x,a) (((x) + (a - 1)) & ~(a - 1))
29 #define NextSlot(p) (* (void **) ((p) - PTRSIZE))
30 #define NextFree(p) (* (void **) (p))
33 * A short explanation of the data structure and algorithms.
34 * An area returned by malloc() is called a slot. Each slot
35 * contains the number of bytes requested, but preceeded by
36 * an extra pointer to the next the slot in memory.
37 * '_bottom' and '_top' point to the first/last slot.
38 * More memory is asked for using brk() and appended to top.
39 * The list of free slots is maintained to keep malloc() fast.
40 * '_empty' points the the first free slot. Free slots are
41 * linked together by a pointer at the start of the
42 * user visable part, so just after the next-slot pointer.
43 * Free slots are merged together by free().
46 extern void *_sbrk(int);
47 extern int _brk(void *);
48 static void *_bottom
, *_top
, *_empty
;
50 static int grow(size_t len
)
54 assert(NextSlot((char *)_top
) == 0);
55 if ((char *) _top
+ len
< (char *) _top
56 || (p
= (char *)Align((ptrint
)_top
+ len
, BRKSIZE
)) < (char *) _top
) {
62 NextSlot((char *)_top
) = p
;
72 register char *prev
, *p
, *next
, *new;
73 register unsigned len
, ntries
;
78 for (ntries
= 0; ntries
< 2; ntries
++) {
79 if ((len
= Align(size
, PTRSIZE
) + PTRSIZE
) < 2 * PTRSIZE
) {
84 if ((p
= _sbrk(2 * PTRSIZE
)) == (char *) -1)
86 p
= (char *) Align((ptrint
)p
, PTRSIZE
);
92 for (p
= _bottom
; (next
= NextSlot(p
)) != 0; p
= next
)
96 for (prev
= 0, p
= _empty
; p
!= 0; prev
= p
, p
= NextFree(p
)) {
98 new = p
+ len
; /* easily overflows!! */
99 if (new > next
|| new <= p
)
100 continue; /* too small */
101 if (new + PTRSIZE
< next
) { /* too big, so split */
102 /* + PTRSIZE avoids tiny slots on free list */
103 NextSlot(new) = next
;
105 NextFree(new) = NextFree(p
);
109 NextFree(prev
) = NextFree(p
);
111 _empty
= NextFree(p
);
122 realloc(void *oldp
, size_t size
)
124 register char *prev
, *p
, *next
, *new;
126 register size_t len
, n
;
134 len
= Align(size
, PTRSIZE
) + PTRSIZE
;
135 next
= NextSlot(old
);
136 n
= (int)(next
- old
); /* old length */
138 * extend old if there is any free space just behind it
140 for (prev
= 0, p
= _empty
; p
!= 0; prev
= p
, p
= NextFree(p
)) {
143 if (p
== next
) { /* 'next' is a free slot: merge */
144 NextSlot(old
) = NextSlot(p
);
146 NextFree(prev
) = NextFree(p
);
148 _empty
= NextFree(p
);
149 next
= NextSlot(old
);
155 * Can we use the old, possibly extended slot?
157 if (new <= next
&& new >= old
) { /* it does fit */
158 if (new + PTRSIZE
< next
) { /* too big, so split */
159 /* + PTRSIZE avoids tiny slots on free list */
160 NextSlot(new) = next
;
166 if ((new = malloc(size
)) == NULL
) /* it didn't fit */
168 memcpy(new, old
, n
); /* n < size */
176 register char *prev
, *next
;
182 assert(NextSlot(p
) > p
);
183 for (prev
= 0, next
= _empty
; next
!= 0; prev
= next
, next
= NextFree(next
))
192 assert(NextSlot(p
) <= next
);
193 if (NextSlot(p
) == next
) { /* merge p and next */
194 NextSlot(p
) = NextSlot(next
);
195 NextFree(p
) = NextFree(next
);
199 assert(NextSlot(prev
) <= p
);
200 if (NextSlot(prev
) == p
) { /* merge prev and p */
201 NextSlot(prev
) = NextSlot(p
);
202 NextFree(prev
) = NextFree(p
);