4 #if _SDCC_MALLOC_TYPE_MLH
6 typedef struct _MEMHEADER MEMHEADER;
16 #define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
18 /* These veriables are defined through the crt0 functions. */
19 /* Base of this variable is the first byte of the heap. */
20 extern MEMHEADER _sdcc_heap_start;
21 /* Address of this variable is the last byte of the heap. */
22 extern char _sdcc_heap_end;
27 MEMHEADER *pbase = &_sdcc_heap_start;
28 unsigned int size = &_sdcc_heap_end - (char *)pbase;
30 pbase->next = (MEMHEADER *)((char *)pbase + size - HEADER_SIZE);
31 pbase->next->next = NULL; //And mark it as last
32 pbase->prev = NULL; //and mark first as first
33 pbase->len = 0; //Empty and ready.
37 malloc (unsigned int size)
39 MEMHEADER * current_header;
40 MEMHEADER * new_header;
42 if (size>(0xFFFF-HEADER_SIZE))
44 return NULL; //To prevent overflow in next line
47 size += HEADER_SIZE; //We need a memory for header too
48 current_header = &_sdcc_heap_start;
55 //....*****.........******....
59 if ((((unsigned int)current_header->next) -
60 ((unsigned int)current_header) -
61 current_header->len) >= size)
63 break; //if spare is more than need
65 current_header = current_header->next; //else try next
66 if (!current_header->next)
68 return NULL; //if end_of_list reached
72 if (!current_header->len)
73 { //This code works only for first_header in the list and only
74 current_header->len = size; //for first allocation
75 return ¤t_header->mem;
79 //else create new header at the begin of spare
80 new_header = (MEMHEADER * )((char *)current_header + current_header->len);
81 new_header->next = current_header->next; //and plug it into the chain
82 new_header->prev = current_header;
83 current_header->next = new_header;
86 new_header->next->prev = new_header;
88 new_header->len = size; //mark as used
89 return &new_header->mem;
96 MEMHEADER *prev_header, *pthis;
98 if ( p ) //For allocated pointers only!
100 pthis = (MEMHEADER * )((char *) p - HEADER_SIZE); //to start of header
101 if ( pthis->prev ) // For the regular header
103 prev_header = pthis->prev;
104 prev_header->next = pthis->next;
107 pthis->next->prev = prev_header;
112 pthis->len = 0; //For the first header
119 //--------------------------------------------------------------------
120 //Written by Dmitry S. Obukhov, 1997
122 //--------------------------------------------------------------------
123 //Modified for SDCC by Sandeep Dutta, 1999
124 //sandeep.dutta@usa.net
125 //--------------------------------------------------------------------
126 //malloc and free functions implementation for embedded system
127 //Non-ANSI keywords are C51 specific.
128 // xdata - variable in external memory (just RAM)
129 //--------------------------------------------------------------------
131 #define MEMHEADER struct MAH// Memory Allocation Header
135 MEMHEADER xdata * next;
136 MEMHEADER xdata * prev;
141 #define HEADER_SIZE (sizeof(MEMHEADER)-1)
143 //Static here means: can be accessed from this module only
144 static MEMHEADER xdata * FIRST_MEMORY_HEADER_PTR;
145 void init_dynamic_memory(MEMHEADER xdata * array, unsigned int size)
148 //This function MUST be called after the RESET.
149 //Parameters: array - pointer to memory allocated by the linker
150 // size - size of this memory pool
152 // #define DYNAMIC_MEMORY_SIZE 0x2000
154 // unsigned char xdata dynamic_memory_pool[DYNAMIC_MEMORY_SIZE];
155 // unsigned char xdata * current_buffer;
160 // init_dynamic_memory(dynamic_memory_pool,DYNAMIC_MEMORY_SIZE);
161 // Now it is possible to use malloc.
163 // current_buffer = malloc(0x100);
167 if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/
168 { //So, we lost one byte!
169 array = (MEMHEADER xdata * )((char xdata * ) array + 1) ;
172 FIRST_MEMORY_HEADER_PTR = array;
173 //Reserve a mem for last header
174 array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - HEADER_SIZE);
175 array->next->next = (void xdata * ) NULL; //And mark it as last
176 array->prev = (void xdata * ) NULL; //and mark first as first
177 array->len = 0; //Empty and ready.
180 void xdata * malloc (unsigned int size)
182 register MEMHEADER xdata * current_header;
183 register MEMHEADER xdata * new_header;
185 if (size>(0xFFFF-HEADER_SIZE)) return (void xdata *) NULL; //To prevent overflow in next line
186 size += HEADER_SIZE; //We need a memory for header too
187 current_header = FIRST_MEMORY_HEADER_PTR;
194 //....*****.........******....
198 if ((((unsigned int)current_header->next) -
199 ((unsigned int)current_header) -
200 current_header->len) >= size) break; //if spare is more than need
201 current_header = current_header->next; //else try next
202 if (!current_header->next) return (void xdata *) NULL; //if end_of_list reached
204 if (!current_header->len)
205 { //This code works only for first_header in the list and only
206 current_header->len = size; //for first allocation
207 return ((xdata *)&(current_header->mem));
208 } //else create new header at the begin of spare
209 new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
210 new_header->next = current_header->next; //and plug it into the chain
211 new_header->prev = current_header;
212 current_header->next = new_header;
213 if (new_header->next) new_header->next->prev = new_header;
214 new_header->len = size; //mark as used
215 return ((xdata *)&(new_header->mem));
218 void free (void xdata * p)
220 register MEMHEADER xdata * prev_header;
221 if ( p ) //For allocated pointers only!
223 p = (MEMHEADER xdata * )((char xdata *) p - HEADER_SIZE); //to start of header
224 if ( ((MEMHEADER xdata * ) p)->prev ) // For the regular header
226 prev_header = ((MEMHEADER xdata * ) p)->prev;
227 prev_header->next = ((MEMHEADER xdata * ) p)->next;
228 if (((MEMHEADER xdata * ) p)->next)
229 ((MEMHEADER xdata * ) p)->next->prev = prev_header;
231 else ((MEMHEADER xdata * ) p)->len = 0; //For the first header