11 void *realloc(void *ptr
, size_t size
)
13 struct free_arena_header
*ah
, *nah
;
15 size_t newsize
, oldsize
, xsize
;
25 ah
= (struct free_arena_header
*)
26 ((struct arena_header
*)ptr
- 1);
28 /* Actual size of the old block */
31 /* Add the obligatory arena header, and round up */
32 newsize
= (size
+ 2 * sizeof(struct arena_header
) - 1) & ARENA_SIZE_MASK
;
34 if (oldsize
>= newsize
&& newsize
>= (oldsize
>> 2) &&
35 oldsize
- newsize
< 4096) {
36 /* This allocation is close enough already. */
42 if ((char *)nah
== (char *)ah
+ ah
->a
.size
&&
43 nah
->a
.type
== ARENA_TYPE_FREE
&&
44 oldsize
+ nah
->a
.size
>= newsize
) {
45 /* Merge in subsequent free block */
46 ah
->a
.next
= nah
->a
.next
;
47 ah
->a
.next
->a
.prev
= ah
;
48 nah
->next_free
->prev_free
= nah
->prev_free
;
49 nah
->prev_free
->next_free
= nah
->next_free
;
50 xsize
= (ah
->a
.size
+= nah
->a
.size
);
53 if (xsize
>= newsize
) {
54 /* We can reallocate in place */
55 if (xsize
>= newsize
+ 2 * sizeof(struct arena_header
)) {
56 /* Residual free block at end */
57 nah
= (struct free_arena_header
*)((char *)ah
+ newsize
);
58 nah
->a
.type
= ARENA_TYPE_FREE
;
59 nah
->a
.size
= xsize
- newsize
;
62 /* Insert into block list */
63 nah
->a
.next
= ah
->a
.next
;
65 nah
->a
.next
->a
.prev
= nah
;
68 /* Insert into free list */
69 if (newsize
> oldsize
) {
70 /* Hack: this free block is in the path of a memory object
71 which has already been grown at least once. As such, put
72 it at the *end* of the freelist instead of the beginning;
73 trying to save it for future realloc()s of the same block. */
74 nah
->prev_free
= __malloc_head
.prev_free
;
75 nah
->next_free
= &__malloc_head
;
76 __malloc_head
.prev_free
= nah
;
77 nah
->prev_free
->next_free
= nah
;
79 nah
->next_free
= __malloc_head
.next_free
;
80 nah
->prev_free
= &__malloc_head
;
81 __malloc_head
.next_free
= nah
;
82 nah
->next_free
->prev_free
= nah
;
85 /* otherwise, use up the whole block */
88 /* Last resort: need to allocate a new block and copy */
89 oldsize
-= sizeof(struct arena_header
);
90 newptr
= malloc(size
);
92 memcpy(newptr
, ptr
, min(size
, oldsize
));