Imported Upstream version 2.9.0
[debian/cc1111] / device / lib / _free.c
1 /*-------------------------------------------------------------------------
2    free.c - release allocated memory.
3
4    Copyright (C) 2004 - Maarten Brock, sourceforge.brock@dse.nl
5
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.
10
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.
15
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 -------------------------------------------------------------------------*/
20
21 #include <sdcc-lib.h>
22 #include <malloc.h>
23
24 #if defined(SDCC_STACK_AUTO) || defined(SDCC_z80) || defined(SDCC_gbz80)
25   #define CRITICAL __critical
26 #else
27   #define CRITICAL
28 #endif
29
30 #if _SDCC_MALLOC_TYPE_MLH
31
32 typedef struct _MEMHEADER MEMHEADER;
33
34 struct _MEMHEADER
35 {
36   MEMHEADER *    next;
37   MEMHEADER *    prev;
38   unsigned int   len;
39   unsigned char  mem;
40 };
41
42 #define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
43
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;
49
50 MEMHEADER * _sdcc_prev_memheader;
51 // apart from finding the header
52 // this function also finds it's predecessor
53 MEMHEADER *
54 _sdcc_find_memheader(void * p)
55 {
56   register MEMHEADER * pthis;
57   if (!p)
58     return NULL;
59   pthis = (MEMHEADER * )((char *)  p - HEADER_SIZE); //to start of header
60   _sdcc_prev_memheader = pthis->prev;
61
62   return (pthis);
63 }
64
65 void
66 free (void *p)
67 {
68   MEMHEADER *prev_header, *pthis;
69
70   if ( p ) //For allocated pointers only!
71     CRITICAL
72     {
73       pthis = (MEMHEADER * )((char *)  p - HEADER_SIZE); //to start of header
74       if ( pthis->prev ) // For the regular header
75         {
76           prev_header = pthis->prev;
77           prev_header->next = pthis->next;
78           if (pthis->next)
79             {
80               pthis->next->prev = prev_header;
81             }
82         }
83       else
84         {
85           pthis->len = 0; //For the first header
86         }
87     }
88 }
89
90 #else
91
92             //--------------------------------------------------------------------
93             //Written by Dmitry S. Obukhov, 1997
94             //dso@usa.net
95             //--------------------------------------------------------------------
96             //Modified for SDCC by Sandeep Dutta, 1999
97             //sandeep.dutta@usa.net
98             //--------------------------------------------------------------------
99             //malloc and free functions implementation for embedded system
100             //Non-ANSI keywords are C51 specific.
101             // __xdata - variable in external memory (just RAM)
102             //--------------------------------------------------------------------
103
104             #define MEMHEADER   struct MAH// Memory Allocation Header
105
106             MEMHEADER
107             {
108               MEMHEADER __xdata *  next;
109               unsigned int         len;
110               unsigned char        mem[];
111             };
112
113             #define HEADER_SIZE sizeof(MEMHEADER)
114
115             //Static here means: can be accessed from this module only
116             extern MEMHEADER __xdata * _sdcc_first_memheader;
117
118             MEMHEADER __xdata * _sdcc_prev_memheader;
119             // apart from finding the header
120             // this function also finds it's predecessor
121             MEMHEADER __xdata * _sdcc_find_memheader(void __xdata * p)
122             {
123               register MEMHEADER __xdata * pthis;
124               register MEMHEADER __xdata * cur_header;
125
126               if (!p)
127                 return NULL;
128               pthis = (MEMHEADER __xdata *) p;
129               pthis -= 1; //to start of header
130               cur_header = _sdcc_first_memheader;
131               _sdcc_prev_memheader = NULL;
132               while (cur_header && pthis != cur_header)
133               {
134                 _sdcc_prev_memheader = cur_header;
135                 cur_header = cur_header->next;
136               }
137               return (cur_header);
138             }
139
140             void free (void * p)
141             {
142               register MEMHEADER __xdata * pthis;
143
144               CRITICAL
145               {
146                 pthis = _sdcc_find_memheader(p);
147                 if (pthis) //For allocated pointers only!
148                 {
149                   if (!_sdcc_prev_memheader)
150                   {
151                     pthis->len = 0;
152                   }
153                   else
154                   {
155                     _sdcc_prev_memheader->next = pthis->next;
156                   }
157                 }
158               }
159             }
160             //END OF MODULE
161 #endif