X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device%2Flib%2Fmalloc.c;h=33f8feddb806cb42203944e4befbdc3c9a48ca4c;hb=018a6f8c8ded8202afb6e3eb0becf7b98e76a93c;hp=e9a67e11f97a15e67b1f65057ae145ee85a425cb;hpb=dac58057deb9119f7b888ba84449466720c268b5;p=fw%2Fsdcc diff --git a/device/lib/malloc.c b/device/lib/malloc.c index e9a67e11..33f8fedd 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 @@ -16,105 +143,93 @@ MEMHEADER { - MEMHEADER _xdata * next; - MEMHEADER _xdata * prev; - unsigned int len; - unsigned char mem[1]; + MEMHEADER __xdata * next; + unsigned int len; + unsigned char mem[]; }; - #define HEADER_SIZE (sizeof(MEMHEADER)-1) - #define NULL (void _xdata * ) 0 + #define HEADER_SIZE sizeof(MEMHEADER) + MEMHEADER xdata * _sdcc_first_memheader = NULL; - //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) + extern xdata char _sdcc_heap[]; + extern const unsigned int _sdcc_heap_size; + + static void init_dynamic_memory(void) { + char xdata * heap = (char xdata *)_sdcc_heap; + unsigned int size = _sdcc_heap_size; - //This function MUST be called after the RESET. - //Parameters: array - pointer to memory allocated by the linker - // size - size of this memory pool - //Example: - // #define DYNAMIC_MEMORY_SIZE 0x2000 - // ..... - // unsigned char xdata dynamic_memory_pool[DYNAMIC_MEMORY_SIZE]; - // unsigned char xdata * current_buffer; - // ..... - // void main(void) - // { - // ... - // init_dynamic_memory(dynamic_memory_pool,DYNAMIC_MEMORY_SIZE); - // Now it is possible to use malloc. - // ... - // current_buffer = malloc(0x100); - // - // - - if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/ + if ( !heap ) //Reserved memory starts at 0x0000 but that's NULL... { //So, we lost one byte! - array = (MEMHEADER _xdata * )((char _xdata * ) array + 1) ; - size --; + heap++; + size--; } - FIRST_MEMORY_HEADER_PTR = array; + _sdcc_first_memheader = (MEMHEADER xdata * ) heap; //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 * )(heap + 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 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 - // | 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); - } + if (!_sdcc_first_memheader) + init_dynamic_memory(); - void free (MEMHEADER _xdata * p) - { - register MEMHEADER _xdata * prev_header; - if ( p ) //For allocated pointers only! + current_header = _sdcc_first_memheader; + CRITICAL { - 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; + 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; } - else p->len = 0; //For the first header + 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; + } + } } + return ret; } - //END OF MODULE + //END OF MODULE +#endif