1 /*-------------------------------------------------------------------------
2 malloc.c - allocate memory.
4 Copyright (C) 2004 - Maarten Brock, sourceforge.brock@dse.nl
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 -------------------------------------------------------------------------*/
24 #if defined(SDCC_STACK_AUTO) || defined(SDCC_z80) || defined(SDCC_gbz80)
25 #define CRITICAL critical
30 #if _SDCC_MALLOC_TYPE_MLH
32 typedef struct _MEMHEADER MEMHEADER;
42 #define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
44 /* These variables are defined through the crt0 functions. */
45 /* Base of this variable is the first byte of the heap. */
46 extern MEMHEADER _sdcc_heap_start;
47 /* Address of this variable is the last byte of the heap. */
48 extern char _sdcc_heap_end;
53 MEMHEADER *pbase = &_sdcc_heap_start;
54 unsigned int size = &_sdcc_heap_end - (char *)pbase;
56 pbase->next = (MEMHEADER *)((char *)pbase + size - HEADER_SIZE);
57 pbase->next->next = NULL; //And mark it as last
58 pbase->prev = NULL; //and mark first as first
59 pbase->len = 0; //Empty and ready.
63 malloc (unsigned int size)
65 register MEMHEADER * current_header;
66 register MEMHEADER * new_header;
69 if (size>(0xFFFF-HEADER_SIZE))
71 return NULL; //To prevent overflow in next line
74 size += HEADER_SIZE; //We need a memory for header too
75 current_header = &_sdcc_heap_start;
84 //....*****.........******....
88 if ((((unsigned int)current_header->next) -
89 ((unsigned int)current_header) -
90 current_header->len) >= size)
91 { //if spare is more than needed
92 ret = ¤t_header->mem;
95 current_header = current_header->next; //else try next
96 if (!current_header->next)
97 { //if end_of_list reached
105 if (!current_header->len)
106 { //This code works only for first_header in the list and only
107 current_header->len = size; //for first allocation
111 //else create new header at the begin of spare
112 new_header = (MEMHEADER * )((char *)current_header + current_header->len);
113 new_header->next = current_header->next; //and plug it into the chain
114 new_header->prev = current_header;
115 current_header->next = new_header;
116 if (new_header->next)
118 new_header->next->prev = new_header;
120 new_header->len = size; //mark as used
121 ret = &new_header->mem;
130 //--------------------------------------------------------------------
131 //Written by Dmitry S. Obukhov, 1997
133 //--------------------------------------------------------------------
134 //Modified for SDCC by Sandeep Dutta, 1999
135 //sandeep.dutta@usa.net
136 //--------------------------------------------------------------------
137 //malloc and free functions implementation for embedded system
138 //Non-ANSI keywords are C51 specific.
139 // xdata - variable in external memory (just RAM)
140 //--------------------------------------------------------------------
142 #define HEADER_SIZE sizeof(MEMHEADER)
144 MEMHEADER xdata * _sdcc_first_memheader;
146 void init_dynamic_memory(void xdata * heap, unsigned int size)
149 //This function MUST be called after the RESET.
150 //Parameters: heap - pointer to memory allocated by the linker
151 // size - size of this memory pool
153 // #define DYNAMIC_MEMORY_SIZE 0x2000
155 // unsigned char xdata dynamic_memory_pool[DYNAMIC_MEMORY_SIZE];
156 // unsigned char xdata * current_buffer;
161 // init_dynamic_memory(dynamic_memory_pool,DYNAMIC_MEMORY_SIZE);
162 // Now it is possible to use malloc.
164 // current_buffer = malloc(0x100);
167 char xdata * array = (char xdata *)heap;
169 if ( !array ) //Reserved memory starts at 0x0000 but that's NULL...
170 { //So, we lost one byte!
174 _sdcc_first_memheader = (MEMHEADER xdata * ) array;
175 //Reserve a mem for last header
176 _sdcc_first_memheader->next = (MEMHEADER xdata * )(array + size - sizeof(MEMHEADER xdata *));
177 _sdcc_first_memheader->next->next = (MEMHEADER xdata * ) NULL; //And mark it as last
178 _sdcc_first_memheader->len = 0; //Empty and ready.
181 void xdata * malloc (unsigned int size)
183 register MEMHEADER xdata * current_header;
184 register MEMHEADER xdata * new_header;
185 register void xdata * ret;
187 if (size>(0xFFFF-HEADER_SIZE)) return (void xdata *) NULL; //To prevent overflow in next line
188 size += HEADER_SIZE; //We need a memory for header too
189 current_header = _sdcc_first_memheader;
198 //....*****.........******....
202 if ((((unsigned int)current_header->next) -
203 ((unsigned int)current_header) -
204 current_header->len) >= size)
205 { //if spare is more than needed
206 ret = current_header->mem;
209 current_header = current_header->next; //else try next
210 if (!current_header->next)
211 { //if end_of_list reached
212 ret = (void xdata *) NULL;
218 if (!current_header->len)
219 { //This code works only for first_header in the list and only
220 current_header->len = size; //for first allocation
223 { //else create new header at the begin of spare
224 new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
225 new_header->next = current_header->next; //and plug it into the chain
226 current_header->next = new_header;
227 new_header->len = size; //mark as used
228 ret = new_header->mem;