]> git.sur5r.net Git - freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/core/mem.c
Update to V4.3.0 as described in http://www.FreeRTOS.org/History.txt
[freertos] / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / core / mem.c
1 /** @file\r
2  *\r
3  * Dynamic memory manager\r
4  *\r
5  */\r
6 \r
7 /* \r
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
9  * All rights reserved. \r
10  * \r
11  * Redistribution and use in source and binary forms, with or without modification, \r
12  * are permitted provided that the following conditions are met:\r
13  *\r
14  * 1. Redistributions of source code must retain the above copyright notice,\r
15  *    this list of conditions and the following disclaimer.\r
16  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
17  *    this list of conditions and the following disclaimer in the documentation\r
18  *    and/or other materials provided with the distribution.\r
19  * 3. The name of the author may not be used to endorse or promote products\r
20  *    derived from this software without specific prior written permission. \r
21  *\r
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED \r
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \r
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \r
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \r
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \r
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING \r
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY \r
31  * OF SUCH DAMAGE.\r
32  *\r
33  * This file is part of the lwIP TCP/IP stack.\r
34  * \r
35  * Author: Adam Dunkels <adam@sics.se>\r
36  *\r
37  */\r
38 \r
39 #include <string.h>\r
40 \r
41 #include "lwip/arch.h"\r
42 #include "lwip/opt.h"\r
43 #include "lwip/def.h"\r
44 #include "lwip/mem.h"\r
45 \r
46 #include "lwip/sys.h"\r
47 \r
48 #include "lwip/stats.h"\r
49 \r
50 struct mem {\r
51   mem_size_t next, prev;\r
52 #if MEM_ALIGNMENT == 1\r
53   u8_t used;\r
54 #elif MEM_ALIGNMENT == 2\r
55   u16_t used;\r
56 #elif MEM_ALIGNMENT == 4\r
57   u32_t used;\r
58 #elif MEM_ALIGNMENT == 8\r
59   u64_t used;\r
60 #else\r
61 #error "unhandled MEM_ALIGNMENT size"\r
62 #endif /* MEM_ALIGNMENT */\r
63 }; \r
64 \r
65 static struct mem *ram_end;\r
66 static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];\r
67 \r
68 #define MIN_SIZE 12\r
69 #if 0 /* this one does not align correctly for some, resulting in crashes */\r
70 #define SIZEOF_STRUCT_MEM (unsigned int)MEM_ALIGN_SIZE(sizeof(struct mem))\r
71 #else\r
72 #define SIZEOF_STRUCT_MEM (sizeof(struct mem) + \\r
73                           (((sizeof(struct mem) % MEM_ALIGNMENT) == 0)? 0 : \\r
74                           (4 - (sizeof(struct mem) % MEM_ALIGNMENT))))\r
75 #endif\r
76 \r
77 static struct mem *lfree;   /* pointer to the lowest free block */\r
78 \r
79 static sys_sem_t mem_sem;\r
80 \r
81 static void\r
82 plug_holes(struct mem *mem)\r
83 {\r
84   struct mem *nmem;\r
85   struct mem *pmem;\r
86 \r
87   LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);\r
88   LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);\r
89   LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);\r
90   \r
91   /* plug hole forward */\r
92   LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);\r
93   \r
94   nmem = (struct mem *)&ram[mem->next];\r
95   if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {\r
96     if (lfree == nmem) {\r
97       lfree = mem;\r
98     }\r
99     mem->next = nmem->next;\r
100     ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;\r
101   }\r
102 \r
103   /* plug hole backward */\r
104   pmem = (struct mem *)&ram[mem->prev];\r
105   if (pmem != mem && pmem->used == 0) {\r
106     if (lfree == mem) {\r
107       lfree = pmem;\r
108     }\r
109     pmem->next = mem->next;\r
110     ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;\r
111   }\r
112 \r
113 }\r
114 void\r
115 mem_init(void)\r
116 {\r
117   struct mem *mem;\r
118 \r
119   memset(ram, 0, MEM_SIZE);\r
120   mem = (struct mem *)ram;\r
121   mem->next = MEM_SIZE;\r
122   mem->prev = 0;\r
123   mem->used = 0;\r
124   ram_end = (struct mem *)&ram[MEM_SIZE];\r
125   ram_end->used = 1;\r
126   ram_end->next = MEM_SIZE;\r
127   ram_end->prev = MEM_SIZE;\r
128 \r
129   mem_sem = sys_sem_new(1);\r
130 \r
131   lfree = (struct mem *)ram;\r
132 \r
133 #if MEM_STATS\r
134   lwip_stats.mem.avail = MEM_SIZE;\r
135 #endif /* MEM_STATS */\r
136 }\r
137 void\r
138 mem_free(void *rmem)\r
139 {\r
140   struct mem *mem;\r
141 \r
142   if (rmem == NULL) {\r
143     LWIP_DEBUGF(MEM_DEBUG | DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));\r
144     return;\r
145   }\r
146   \r
147   sys_sem_wait(mem_sem);\r
148 \r
149   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&\r
150     (u8_t *)rmem < (u8_t *)ram_end);\r
151   \r
152   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {\r
153     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));\r
154 #if MEM_STATS\r
155     ++lwip_stats.mem.err;\r
156 #endif /* MEM_STATS */\r
157     sys_sem_signal(mem_sem);\r
158     return;\r
159   }\r
160   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);\r
161 \r
162   LWIP_ASSERT("mem_free: mem->used", mem->used);\r
163   \r
164   mem->used = 0;\r
165 \r
166   if (mem < lfree) {\r
167     lfree = mem;\r
168   }\r
169   \r
170 #if MEM_STATS\r
171   lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);\r
172   \r
173 #endif /* MEM_STATS */\r
174   plug_holes(mem);\r
175   sys_sem_signal(mem_sem);\r
176 }\r
177 void *\r
178 mem_reallocm(void *rmem, mem_size_t newsize)\r
179 {\r
180   void *nmem;\r
181   nmem = mem_malloc(newsize);\r
182   if (nmem == NULL) {\r
183     return mem_realloc(rmem, newsize);\r
184   }\r
185   memcpy(nmem, rmem, newsize);\r
186   mem_free(rmem);\r
187   return nmem;\r
188 }\r
189 \r
190 void *\r
191 mem_realloc(void *rmem, mem_size_t newsize)\r
192 {\r
193   mem_size_t size;\r
194   mem_size_t ptr, ptr2;\r
195   struct mem *mem, *mem2;\r
196 \r
197   /* Expand the size of the allocated memory region so that we can\r
198      adjust for alignment. */\r
199   if ((newsize % MEM_ALIGNMENT) != 0) {\r
200    newsize += MEM_ALIGNMENT - ((newsize + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);\r
201   }\r
202   \r
203   if (newsize > MEM_SIZE) {\r
204     return NULL;\r
205   }\r
206   \r
207   sys_sem_wait(mem_sem);\r
208   \r
209   LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&\r
210    (u8_t *)rmem < (u8_t *)ram_end);\r
211   \r
212   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {\r
213     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));\r
214     return rmem;\r
215   }\r
216   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);\r
217 \r
218   ptr = (u8_t *)mem - ram;\r
219 \r
220   size = mem->next - ptr - SIZEOF_STRUCT_MEM;\r
221 #if MEM_STATS\r
222   lwip_stats.mem.used -= (size - newsize);\r
223 #endif /* MEM_STATS */\r
224   \r
225   if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {\r
226     ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;\r
227     mem2 = (struct mem *)&ram[ptr2];\r
228     mem2->used = 0;\r
229     mem2->next = mem->next;\r
230     mem2->prev = ptr;\r
231     mem->next = ptr2;\r
232     if (mem2->next != MEM_SIZE) {\r
233       ((struct mem *)&ram[mem2->next])->prev = ptr2;\r
234     }\r
235 \r
236     plug_holes(mem2);\r
237   }\r
238   sys_sem_signal(mem_sem);  \r
239   return rmem;\r
240 }\r
241 void *\r
242 mem_malloc(mem_size_t size)\r
243 {\r
244   mem_size_t ptr, ptr2;\r
245   struct mem *mem, *mem2;\r
246 \r
247   if (size == 0) {\r
248     return NULL;\r
249   }\r
250 \r
251   /* Expand the size of the allocated memory region so that we can\r
252      adjust for alignment. */\r
253   if ((size % MEM_ALIGNMENT) != 0) {\r
254     size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);\r
255   }\r
256   \r
257   if (size > MEM_SIZE) {\r
258     return NULL;\r
259   }\r
260   \r
261   sys_sem_wait(mem_sem);\r
262 \r
263   for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {\r
264     mem = (struct mem *)&ram[ptr];\r
265     if (!mem->used &&\r
266        mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {\r
267       ptr2 = ptr + SIZEOF_STRUCT_MEM + size;\r
268       mem2 = (struct mem *)&ram[ptr2];\r
269 \r
270       mem2->prev = ptr;      \r
271       mem2->next = mem->next;\r
272       mem->next = ptr2;      \r
273       if (mem2->next != MEM_SIZE) {\r
274         ((struct mem *)&ram[mem2->next])->prev = ptr2;\r
275       }\r
276       \r
277       mem2->used = 0;      \r
278       mem->used = 1;\r
279 #if MEM_STATS\r
280       lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);\r
281       /*      if (lwip_stats.mem.max < lwip_stats.mem.used) {\r
282         lwip_stats.mem.max = lwip_stats.mem.used;\r
283   } */\r
284       if (lwip_stats.mem.max < ptr2) {\r
285         lwip_stats.mem.max = ptr2;\r
286       }      \r
287 #endif /* MEM_STATS */\r
288 \r
289       if (mem == lfree) {\r
290   /* Find next free block after mem */\r
291         while (lfree->used && lfree != ram_end) {\r
292     lfree = (struct mem *)&ram[lfree->next];\r
293         }\r
294         LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);\r
295       }\r
296       sys_sem_signal(mem_sem);\r
297       LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",\r
298        (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);\r
299       LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",\r
300        (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);\r
301       return (u8_t *)mem + SIZEOF_STRUCT_MEM;\r
302     }    \r
303   }\r
304   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));\r
305 #if MEM_STATS\r
306   ++lwip_stats.mem.err;\r
307 #endif /* MEM_STATS */  \r
308   sys_sem_signal(mem_sem);\r
309   return NULL;\r
310 }\r