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 #include "malloc-debug.h"
19 static int no_debug
= -1;
20 #define CHECK_DBG(statement) \
21 if (no_debug <= 0) { \
22 if (no_debug < 0) no_debug = getenv("MALLOC_DEBUG") ? 0 : 1; \
23 if (no_debug == 0) { statement; } \
29 #ifdef ALIGN_EIGHT_BYTES
32 #define PTRSIZE ((int) sizeof(void *))
34 #define Align(x,a) (((x) + (a - 1)) & ~(a - 1))
35 #define NextSlot(p) (* (void **) ((p) - PTRSIZE))
36 #define NextFree(p) (* (void **) (p))
39 * A short explanation of the data structure and algorithms.
40 * An area returned by malloc() is called a slot. Each slot
41 * contains the number of bytes requested, but preceeded by
42 * an extra pointer to the next the slot in memory.
43 * '_bottom' and '_top' point to the first/last slot.
44 * More memory is asked for using brk() and appended to top.
45 * The list of free slots is maintained to keep malloc() fast.
46 * '_empty' points the the first free slot. Free slots are
47 * linked together by a pointer at the start of the
48 * user visable part, so just after the next-slot pointer.
49 * Free slots are merged together by free().
51 * Since modern processors prefer 8-byte alignment, we now pretend
52 * our pointers are 8 bytes wide.
55 extern void *_sbrk(int);
56 extern int _brk(void *);
57 static void *_bottom
, *_top
, *_empty
;
59 static int grow(size_t len
)
63 assert(NextSlot((char *)_top
) == 0);
64 if ((char *) _top
+ len
< (char *) _top
65 || (p
= (char *)Align((ptrint
)_top
+ len
, BRKSIZE
)) < (char *) _top
) {
71 NextSlot((char *)_top
) = p
;
79 malloc(const size_t size
)
81 register char *prev
, *p
, *next
, *new;
87 CHECK_DBG(return _dbg_malloc(size
));
89 for (ntries
= 0; ntries
< 2; ntries
++) {
90 unsigned len
= Align(size
, PTRSIZE
) + PTRSIZE
;
91 if (len
< 2 * PTRSIZE
) {
96 if ((p
= _sbrk(2 * PTRSIZE
)) == (char *) -1)
98 p
= (char *) Align((ptrint
)p
, PTRSIZE
);
104 for (p
= _bottom
; (next
= NextSlot(p
)) != 0; p
= next
)
108 for (prev
= 0, p
= _empty
; p
!= 0; prev
= p
, p
= NextFree(p
)) {
110 new = p
+ len
; /* easily overflows!! */
111 if (new > next
|| new <= p
)
112 continue; /* too small */
113 if (new + PTRSIZE
< next
) { /* too big, so split */
114 /* + PTRSIZE avoids tiny slots on free list */
115 NextSlot(new) = next
;
117 NextFree(new) = NextFree(p
);
121 NextFree(prev
) = NextFree(p
);
123 _empty
= NextFree(p
);
134 realloc(void *oldp
, size_t size
)
136 register char *prev
, *p
, *next
, *new;
138 register size_t len
, n
;
147 CHECK_DBG(return _dbg_realloc(oldp
, size
));
149 len
= Align(size
, PTRSIZE
) + PTRSIZE
;
150 next
= NextSlot(old
);
151 n
= (int)(next
- old
); /* old length */
153 * extend old if there is any free space just behind it
155 for (prev
= 0, p
= _empty
; p
!= 0; prev
= p
, p
= NextFree(p
)) {
158 if (p
== next
) { /* 'next' is a free slot: merge */
159 NextSlot(old
) = NextSlot(p
);
161 NextFree(prev
) = NextFree(p
);
163 _empty
= NextFree(p
);
164 next
= NextSlot(old
);
170 * Can we use the old, possibly extended slot?
172 if (new <= next
&& new >= old
) { /* it does fit */
173 if (new + PTRSIZE
< next
) { /* too big, so split */
174 /* + PTRSIZE avoids tiny slots on free list */
175 NextSlot(new) = next
;
181 if ((new = malloc(size
)) == NULL
) /* it didn't fit */
183 memcpy(new, old
, n
); /* n < size */
191 register char *prev
, *next
;
197 CHECK_DBG(_dbg_free(ptr
); return);
204 /* block must be in block list */
207 for (curr
= _bottom
; (next
= NextSlot(curr
)) != 0; curr
= next
) {
209 if (curr
== p
) found
= 1;
211 if (curr
== p
) found
= 1;
214 /* block must not be in free list */
217 for (curr
= _empty
; (next
= NextFree(curr
)) != 0; curr
= next
) {
219 if (curr
== p
) found
= 1;
221 if (curr
== p
) found
= 1;
227 assert((char *) NextSlot(p
) > p
);
228 for (prev
= 0, next
= _empty
; next
!= 0; prev
= next
, next
= NextFree(next
))
237 assert((char *) NextSlot(p
) <= next
);
238 if (NextSlot(p
) == next
) { /* merge p and next */
239 NextSlot(p
) = NextSlot(next
);
240 NextFree(p
) = NextFree(next
);
244 assert((char *) NextSlot(prev
) <= p
);
245 if (NextSlot(prev
) == p
) { /* merge prev and p */
246 NextSlot(prev
) = NextSlot(p
);
247 NextFree(prev
) = NextFree(p
);