X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device%2Flib%2Fmalloc.c;h=4754095cc3149e75810537490d6a157143be309f;hb=6d5732239ca066c1757ae16f69942fd4b320e612;hp=189879018eadce8d4b10a276d6d2836c57496eab;hpb=cb7d8a8cab26fa0c173006da313fcc3e0bbb8d33;p=fw%2Fsdcc diff --git a/device/lib/malloc.c b/device/lib/malloc.c index 18987901..4754095c 100644 --- a/device/lib/malloc.c +++ b/device/lib/malloc.c @@ -1,4 +1,131 @@ +/*------------------------------------------------------------------------- + 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 +#include + +#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; + +struct _MEMHEADER +{ + MEMHEADER * next; + MEMHEADER * prev; + unsigned int len; + unsigned char mem; +}; + +#define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char)) + +/* These variables are defined through the crt0 functions. */ +/* Base of this variable is the first byte of the heap. */ +extern MEMHEADER _sdcc_heap_start; +/* Address of this variable is the last byte of the heap. */ +extern char _sdcc_heap_end; + +void +_sdcc_heap_init(void) +{ + MEMHEADER *pbase = &_sdcc_heap_start; + unsigned int size = &_sdcc_heap_end - (char *)pbase; + + pbase->next = (MEMHEADER *)((char *)pbase + size - HEADER_SIZE); + pbase->next->next = NULL; //And mark it as last + pbase->prev = NULL; //and mark first as first + pbase->len = 0; //Empty and ready. +} + +void * +malloc (unsigned int size) +{ + register MEMHEADER * current_header; + register MEMHEADER * new_header; + register void * ret; + + if (size>(0xFFFF-HEADER_SIZE)) + { + return NULL; //To prevent overflow in next line + } + + size += HEADER_SIZE; //We need a memory for header too + current_header = &_sdcc_heap_start; + + CRITICAL + { + 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 = ¤t_header->mem; + break; + } + current_header = current_header->next; //else try next + if (!current_header->next) + { //if end_of_list reached + ret = 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 * )((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; + } + } +} + return ret; +} + +#else //-------------------------------------------------------------------- //Written by Dmitry S. Obukhov, 1997 @@ -12,28 +139,16 @@ // xdata - variable in external memory (just RAM) //-------------------------------------------------------------------- - #define MEMHEADER struct MAH// Memory Allocation Header + #define HEADER_SIZE sizeof(MEMHEADER) - MEMHEADER - { - MEMHEADER xdata * next; - MEMHEADER xdata * prev; - unsigned int len; - unsigned char mem[1]; - }; - - #define HEADER_SIZE (sizeof(MEMHEADER)-1) - #define NULL (void xdata * ) 0 + MEMHEADER xdata * _sdcc_first_memheader; - - //Static here means: can be accessed from this module only - static MEMHEADER xdata * FIRST_MEMORY_HEADER_PTR; - void init_dynamic_memory(MEMHEADER xdata * array, unsigned int size) + void init_dynamic_memory(void xdata * heap, unsigned int size) { //This function MUST be called after the RESET. - //Parameters: array - pointer to memory allocated by the linker - // size - size of this memory pool + //Parameters: heap - pointer to memory allocated by the linker + // size - size of this memory pool //Example: // #define DYNAMIC_MEMORY_SIZE 0x2000 // ..... @@ -49,72 +164,73 @@ // current_buffer = malloc(0x100); // // + char xdata * array = (char xdata *)heap; - if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/ + if ( !array ) //Reserved memory starts at 0x0000 but that's NULL... { //So, we lost one byte! - array = (MEMHEADER xdata * )((char xdata * ) array + 1) ; - size --; + array++; + size--; } - FIRST_MEMORY_HEADER_PTR = array; + _sdcc_first_memheader = (MEMHEADER xdata * ) array; //Reserve a mem for last header - array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - HEADER_SIZE); - array->next->next = NULL; //And mark it as last - array->prev = NULL; //and mark first as first - 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) + 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 NULL; //To prevent overflow in next line + 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 = FIRST_MEMORY_HEADER_PTR; - while (1) + current_header = _sdcc_first_memheader; + CRITICAL { + while (1) + { - // 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 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 - 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 - 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 - return (new_header->mem); - } + // current + // | len next + // v v v + //....*****.........******.... + // ^^^^^^^^^ + // spare - void free (MEMHEADER xdata * p) - { - register MEMHEADER xdata * prev_header; - if ( p ) //For allocated pointers only! - { - p = (MEMHEADER xdata * )((char xdata *) p - HEADER_SIZE); //to start of header - if ( p->prev ) // For the regular header - { - prev_header = p->prev; - prev_header->next = p->next; - if (p->next) p->next->prev = prev_header; + 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; } - else p->len = 0; //For the first header + } + 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; + } + } } + return ret; } - //END OF MODULE + //END OF MODULE +#endif