3 /* replace undef by define */
4 #define ALIGN_EIGHT_BYTES /* Use 8-byte alignment. */
5 #define DEBUG /* check assertions */
6 #undef SLOWDEBUG /* some extra test loops (requires DEBUG) */
17 #if _EM_WSIZE == _EM_PSIZE
28 #ifdef ALIGN_EIGHT_BYTES
31 #define PTRSIZE ((int) sizeof(void *))
33 #define Align(x,a) (((x) + (a - 1)) & ~(a - 1))
34 #define NextSlot(p) (* (void **) ((p) - PTRSIZE))
35 #define NextFree(p) (* (void **) (p))
38 * A short explanation of the data structure and algorithms.
39 * An area returned by malloc() is called a slot. Each slot
40 * contains the number of bytes requested, but preceeded by
41 * an extra pointer to the next the slot in memory.
42 * '_bottom' and '_top' point to the first/last slot.
43 * More memory is asked for using brk() and appended to top.
44 * The list of free slots is maintained to keep malloc() fast.
45 * '_empty' points the the first free slot. Free slots are
46 * linked together by a pointer at the start of the
47 * user visable part, so just after the next-slot pointer.
48 * Free slots are merged together by free().
50 * Since modern processors prefer 8-byte alignment, we now pretend
51 * our pointers are 8 bytes wide.
54 extern void *_sbrk(int);
55 extern int _brk(void *);
56 static void *_bottom
, *_top
, *_empty
;
58 static int grow(size_t len
)
62 assert(NextSlot((char *)_top
) == 0);
63 if ((char *) _top
+ len
< (char *) _top
64 || (p
= (char *)Align((ptrint
)_top
+ len
, BRKSIZE
)) < (char *) _top
) {
70 NextSlot((char *)_top
) = p
;
78 malloc(const size_t size
)
80 register char *prev
, *p
, *next
, *new;
86 for (ntries
= 0; ntries
< 2; ntries
++) {
87 unsigned len
= Align(size
, PTRSIZE
) + PTRSIZE
;
88 if (len
< 2 * PTRSIZE
) {
93 if ((p
= _sbrk(2 * PTRSIZE
)) == (char *) -1)
95 p
= (char *) Align((ptrint
)p
, PTRSIZE
);
101 for (p
= _bottom
; (next
= NextSlot(p
)) != 0; p
= next
)
105 for (prev
= 0, p
= _empty
; p
!= 0; prev
= p
, p
= NextFree(p
)) {
107 new = p
+ len
; /* easily overflows!! */
108 if (new > next
|| new <= p
)
109 continue; /* too small */
110 if (new + PTRSIZE
< next
) { /* too big, so split */
111 /* + PTRSIZE avoids tiny slots on free list */
112 NextSlot(new) = next
;
114 NextFree(new) = NextFree(p
);
118 NextFree(prev
) = NextFree(p
);
120 _empty
= NextFree(p
);
131 realloc(void *oldp
, size_t size
)
133 register char *prev
, *p
, *next
, *new;
135 register size_t len
, n
;
143 len
= Align(size
, PTRSIZE
) + PTRSIZE
;
144 next
= NextSlot(old
);
145 n
= (int)(next
- old
); /* old length */
147 * extend old if there is any free space just behind it
149 for (prev
= 0, p
= _empty
; p
!= 0; prev
= p
, p
= NextFree(p
)) {
152 if (p
== next
) { /* 'next' is a free slot: merge */
153 NextSlot(old
) = NextSlot(p
);
155 NextFree(prev
) = NextFree(p
);
157 _empty
= NextFree(p
);
158 next
= NextSlot(old
);
164 * Can we use the old, possibly extended slot?
166 if (new <= next
&& new >= old
) { /* it does fit */
167 if (new + PTRSIZE
< next
) { /* too big, so split */
168 /* + PTRSIZE avoids tiny slots on free list */
169 NextSlot(new) = next
;
175 if ((new = malloc(size
)) == NULL
) /* it didn't fit */
177 memcpy(new, old
, n
); /* n < size */
185 register char *prev
, *next
;
196 /* block must be in block list */
199 for (curr
= _bottom
; (next
= NextSlot(curr
)) != 0; curr
= next
) {
201 if (curr
== p
) found
= 1;
203 if (curr
== p
) found
= 1;
206 /* block must not be in free list */
209 for (curr
= _empty
; (next
= NextFree(curr
)) != 0; curr
= next
) {
211 if (curr
== p
) found
= 1;
213 if (curr
== p
) found
= 1;
219 assert((char *) NextSlot(p
) > p
);
220 for (prev
= 0, next
= _empty
; next
!= 0; prev
= next
, next
= NextFree(next
))
229 assert((char *) NextSlot(p
) <= next
);
230 if (NextSlot(p
) == next
) { /* merge p and next */
231 NextSlot(p
) = NextSlot(next
);
232 NextFree(p
) = NextFree(next
);
236 assert((char *) NextSlot(prev
) <= p
);
237 if (NextSlot(prev
) == p
) { /* merge prev and p */
238 NextSlot(prev
) = NextSlot(p
);
239 NextFree(prev
) = NextFree(p
);