syslinux-3.08-2 sources from FC4
[bootcd.git] / syslinux / com32 / lib / free.c
1 /*
2  * free.c
3  *
4  * Very simple linked-list based malloc()/free().
5  */
6
7 #include <stdlib.h>
8 #include "malloc.h"
9
10 static struct free_arena_header *
11 __free_block(struct free_arena_header *ah)
12 {
13   struct free_arena_header *pah, *nah;
14
15   pah = ah->a.prev;
16   nah = ah->a.next;
17   if ( pah->a.type == ARENA_TYPE_FREE &&
18        (char *)pah+pah->a.size == (char *)ah ) {
19     /* Coalesce into the previous block */
20     pah->a.size += ah->a.size;
21     pah->a.next = nah;
22     nah->a.prev = pah;
23
24 #ifdef DEBUG_MALLOC
25     ah->a.type = ARENA_TYPE_DEAD;
26 #endif
27
28     ah = pah;
29     pah = ah->a.prev;
30   } else {
31     /* Need to add this block to the free chain */
32     ah->a.type = ARENA_TYPE_FREE;
33
34     ah->next_free = __malloc_head.next_free;
35     ah->prev_free = &__malloc_head;
36     __malloc_head.next_free = ah;
37     ah->next_free->prev_free = ah;
38   }
39
40   /* In either of the previous cases, we might be able to merge
41      with the subsequent block... */
42   if ( nah->a.type == ARENA_TYPE_FREE &&
43        (char *)ah+ah->a.size == (char *)nah ) {
44     ah->a.size += nah->a.size;
45
46     /* Remove the old block from the chains */
47     nah->next_free->prev_free = nah->prev_free;
48     nah->prev_free->next_free = nah->next_free;
49     ah->a.next = nah->a.next;
50     nah->a.next->a.prev = ah;
51
52 #ifdef DEBUG_MALLOC
53     nah->a.type = ARENA_TYPE_DEAD;
54 #endif
55   }
56
57   /* Return the block that contains the called block */
58   return ah;
59 }
60
61 void free(void *ptr)
62 {
63   struct free_arena_header *ah;
64
65   if ( !ptr )
66     return;
67
68   ah = (struct free_arena_header *)
69     ((struct arena_header *)ptr - 1);
70
71 #ifdef DEBUG_MALLOC
72   assert( ah->a.type == ARENA_TYPE_USED );
73 #endif
74
75   __free_block(ah);
76
77   /* Here we could insert code to return memory to the system. */
78 }