* sdcc/device/lib/Makefile.in: added library sources for mcs51, small,
[fw/sdcc] / 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 HEADER_SIZE sizeof(MEMHEADER)
105
106             //Static here means: can be accessed from this module only
107             extern MEMHEADER xdata * _sdcc_first_memheader;
108
109             MEMHEADER xdata * _sdcc_prev_memheader;
110             // apart from finding the header
111             // this function also finds it's predecessor
112             MEMHEADER xdata * _sdcc_find_memheader(void xdata * p)
113             {
114               register MEMHEADER xdata * pthis;
115               register MEMHEADER xdata * cur_header;
116
117               if (!p)
118                 return NULL;
119               pthis = (MEMHEADER xdata *) p;
120               pthis -= 1; //to start of header
121               cur_header = _sdcc_first_memheader;
122               _sdcc_prev_memheader = NULL;
123               while (cur_header && pthis != cur_header)
124               {
125                 _sdcc_prev_memheader = cur_header;
126                 cur_header = cur_header->next;
127               }
128               return (cur_header);
129             }
130
131             void free (void * p)
132             {
133               register MEMHEADER xdata * pthis;
134
135               CRITICAL
136               {
137                 pthis = _sdcc_find_memheader(p);
138                 if (pthis) //For allocated pointers only!
139                 {
140                   if (!_sdcc_prev_memheader)
141                   {
142                     pthis->len = 0;
143                   }
144                   else
145                   {
146                     _sdcc_prev_memheader->next = pthis->next;
147                   }
148                 }
149               }
150             }
151             //END OF MODULE
152 #endif