+/*-------------------------------------------------------------------------
+ malloc.c - allocate memory.
+
+ Copyright (C) 2004 - Maarten Brock, sourceforge.brock@dse.nl
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-------------------------------------------------------------------------*/
+
#include <sdcc-lib.h>
#include <malloc.h>
+#if defined(SDCC_STACK_AUTO) || defined(SDCC_z80) || defined(SDCC_gbz80)
+ #define CRITICAL critical
+#else
+ #define CRITICAL
+#endif
+
#if _SDCC_MALLOC_TYPE_MLH
typedef struct _MEMHEADER MEMHEADER;
void *
malloc (unsigned int size)
{
- MEMHEADER * current_header;
- MEMHEADER * new_header;
+ register MEMHEADER * current_header;
+ register MEMHEADER * new_header;
+ register void * ret;
if (size>(0xFFFF-HEADER_SIZE))
{
size += HEADER_SIZE; //We need a memory for header too
current_header = &_sdcc_heap_start;
- while (1)
+ CRITICAL
{
- // current
- // | len next
- // v v v
- //....*****.........******....
- // ^^^^^^^^^
- // spare
-
- if ((((unsigned int)current_header->next) -
- ((unsigned int)current_header) -
- current_header->len) >= size)
+ while (1)
{
- break; //if spare is more than need
+ // current
+ // | len next
+ // v v v
+ //....*****.........******....
+ // ^^^^^^^^^
+ // spare
+
+ if ((((unsigned int)current_header->next) -
+ ((unsigned int)current_header) -
+ current_header->len) >= size)
+ { //if spare is more than needed
+ ret = ¤t_header->mem;
+ break;
+ }
+ current_header = current_header->next; //else try next
+ if (!current_header->next)
+ { //if end_of_list reached
+ ret = NULL;
+ break;
+ }
}
- current_header = current_header->next; //else try next
- if (!current_header->next)
+
+ if (ret)
{
- return NULL; //if end_of_list reached
+ if (!current_header->len)
+ { //This code works only for first_header in the list and only
+ current_header->len = size; //for first allocation
}
- }
-
- if (!current_header->len)
- { //This code works only for first_header in the list and only
- current_header->len = size; //for first allocation
- return ¤t_header->mem;
- }
- else
- {
- //else create new header at the begin of spare
- new_header = (MEMHEADER * )((char *)current_header + current_header->len);
- new_header->next = current_header->next; //and plug it into the chain
- new_header->prev = current_header;
- current_header->next = new_header;
- if (new_header->next)
+ else
{
- new_header->next->prev = new_header;
+ //else create new header at the begin of spare
+ new_header = (MEMHEADER * )((char *)current_header + current_header->len);
+ new_header->next = current_header->next; //and plug it into the chain
+ new_header->prev = current_header;
+ current_header->next = new_header;
+ if (new_header->next)
+ {
+ new_header->next->prev = new_header;
+ }
+ new_header->len = size; //mark as used
+ ret = &new_header->mem;
}
- new_header->len = size; //mark as used
- return &new_header->mem;
}
}
+ return ret;
+}
#else
// current_buffer = malloc(0x100);
//
//
- MEMHEADER xdata * array = (MEMHEADER xdata *)heap;
+ char xdata * array = (char xdata *)heap;
if ( !array ) //Reserved memory starts at 0x0000 but that's NULL...
{ //So, we lost one byte!
- array = (MEMHEADER xdata * )((char xdata * ) array + 1) ;
+ array++;
size--;
}
- _sdcc_first_memheader = array;
+ _sdcc_first_memheader = (MEMHEADER xdata * ) array;
//Reserve a mem for last header
- array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - sizeof(MEMHEADER xdata *));
- array->next->next = (MEMHEADER xdata * ) NULL; //And mark it as last
- array->len = 0; //Empty and ready.
+ _sdcc_first_memheader->next = (MEMHEADER xdata * )(array + size - sizeof(MEMHEADER xdata *));
+ _sdcc_first_memheader->next->next = (MEMHEADER xdata * ) NULL; //And mark it as last
+ _sdcc_first_memheader->len = 0; //Empty and ready.
}
void xdata * malloc (unsigned int size)
{
register MEMHEADER xdata * current_header;
register MEMHEADER xdata * new_header;
+ register void xdata * ret;
if (size>(0xFFFF-HEADER_SIZE)) return (void xdata *) NULL; //To prevent overflow in next line
size += HEADER_SIZE; //We need a memory for header too
current_header = _sdcc_first_memheader;
- while (1)
+ CRITICAL
{
-
- // current
- // | len next
- // v v v
- //....*****.........******....
- // ^^^^^^^^^
- // spare
-
- if ((((unsigned int)current_header->next) -
- ((unsigned int)current_header) -
- current_header->len) >= size) break; //if spare is more than need
- current_header = current_header->next; //else try next
- if (!current_header->next) return (void xdata *) NULL; //if end_of_list reached
+ while (1)
+ {
+
+ // current
+ // | len next
+ // v v v
+ //....*****.........******....
+ // ^^^^^^^^^
+ // spare
+
+ if ((((unsigned int)current_header->next) -
+ ((unsigned int)current_header) -
+ current_header->len) >= size)
+ { //if spare is more than needed
+ ret = current_header->mem;
+ break;
+ }
+ current_header = current_header->next; //else try next
+ if (!current_header->next)
+ { //if end_of_list reached
+ ret = (void xdata *) NULL;
+ break;
+ }
+ }
+ if (ret)
+ {
+ if (!current_header->len)
+ { //This code works only for first_header in the list and only
+ current_header->len = size; //for first allocation
+ }
+ else
+ { //else create new header at the begin of spare
+ new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
+ new_header->next = current_header->next; //and plug it into the chain
+ current_header->next = new_header;
+ new_header->len = size; //mark as used
+ ret = new_header->mem;
+ }
+ }
}
- if (!current_header->len)
- { //This code works only for first_header in the list and only
- current_header->len = size; //for first allocation
- return current_header->mem;
- } //else create new header at the begin of spare
- new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
- new_header->next = current_header->next; //and plug it into the chain
- current_header->next = new_header;
- new_header->len = size; //mark as used
- return new_header->mem;
+ return ret;
}
//END OF MODULE