Changed _xdata, _near, etc and removed _generic from library files
[fw/sdcc] / device / lib / malloc.c
1
2
3             //--------------------------------------------------------------------
4             //Written by Dmitry S. Obukhov, 1997
5             //dso@usa.net
6             //--------------------------------------------------------------------
7             //Modified for SDCC by Sandeep Dutta, 1999
8             //sandeep.dutta@usa.net
9             //--------------------------------------------------------------------
10             //malloc and free functions implementation for embedded system
11             //Non-ANSI keywords are C51 specific.
12             // xdata - variable in external memory (just RAM)
13             //--------------------------------------------------------------------
14
15             #define MEMHEADER   struct MAH// Memory Allocation Header
16
17             MEMHEADER
18             {
19               MEMHEADER xdata *  next;
20               MEMHEADER xdata *  prev;
21               unsigned int       len;
22               unsigned char      mem[1];
23             };
24
25             #define HEADER_SIZE (sizeof(MEMHEADER)-1)
26             #define NULL        (void xdata * ) 0
27
28
29             //Static here means: can be accessed from this module only
30             static MEMHEADER xdata * FIRST_MEMORY_HEADER_PTR;
31             void init_dynamic_memory(MEMHEADER xdata * array, unsigned int size) 
32             {
33
34             //This function MUST be called after the RESET.
35             //Parameters: array - pointer to memory allocated by the linker
36             //            size  - size of this memory pool
37             //Example:
38             //     #define DYNAMIC_MEMORY_SIZE 0x2000
39             //     .....
40             //     unsigned char xdata dynamic_memory_pool[DYNAMIC_MEMORY_SIZE];
41             //     unsigned char xdata * current_buffer;
42             //     .....
43             //     void main(void)
44             //     {
45             //         ...
46             //         init_dynamic_memory(dynamic_memory_pool,DYNAMIC_MEMORY_SIZE);
47             //         Now it is possible to use malloc.
48             //         ...
49             //         current_buffer = malloc(0x100);
50             //
51             //
52
53               if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/
54               {             //So, we lost one byte!
55                  array = (MEMHEADER xdata * )((char xdata * ) array + 1) ;
56                  size --;
57               }
58               FIRST_MEMORY_HEADER_PTR = array;
59               //Reserve a mem for last header
60               array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - HEADER_SIZE);
61               array->next->next = NULL; //And mark it as last
62               array->prev       = NULL; //and mark first as first
63               array->len        = 0;    //Empty and ready.
64             }
65
66             void  xdata * malloc (unsigned int size)
67             {
68               register MEMHEADER xdata * current_header;
69               register MEMHEADER xdata * new_header;
70
71               if (size>(0xFFFF-HEADER_SIZE)) return NULL; //To prevent overflow in next line
72               size += HEADER_SIZE; //We need a memory for header too
73               current_header = FIRST_MEMORY_HEADER_PTR;
74               while (1)
75               {
76
77                 //    current
78                 //    |   len       next
79                 //    v   v         v
80                 //....*****.........******....
81                 //         ^^^^^^^^^
82                 //           spare
83
84                 if ((((unsigned int)current_header->next) -
85                      ((unsigned int)current_header) -
86                      current_header->len) >= size) break; //if spare is more than need
87                 current_header = current_header->next;    //else try next             
88                 if (!current_header->next)  return NULL;  //if end_of_list reached    
89               }
90               if (!current_header->len)
91               { //This code works only for first_header in the list and only
92                  current_header->len = size; //for first allocation
93                  return (current_header->mem);
94               } //else create new header at the begin of spare
95               new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
96               new_header->next = current_header->next; //and plug it into the chain
97               new_header->prev = current_header;
98               current_header->next  = new_header;
99               if (new_header->next)  new_header->next->prev = new_header;
100               new_header->len  = size; //mark as used
101               return (new_header->mem);
102             }
103
104             void free (MEMHEADER xdata * p)
105             {
106               register MEMHEADER xdata * prev_header;
107               if ( p ) //For allocated pointers only!
108               {
109                   p = (MEMHEADER xdata * )((char xdata *)  p - HEADER_SIZE); //to start of header
110                   if ( p->prev ) // For the regular header
111                   {
112                     prev_header = p->prev;
113                     prev_header->next = p->next;
114                     if (p->next)  p->next->prev = prev_header;
115                   }
116                   else p->len = 0; //For the first header
117               }
118             }
119             //END OF MODULE
120