Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / core / mem.c
1 /**
2  * @file
3  * Dynamic memory manager
4  *
5  * This is a lightweight replacement for the standard C library malloc().
6  *
7  * If you want to use the standard C library malloc() instead, define
8  * MEM_LIBC_MALLOC to 1 in your lwipopts.h
9  *
10  * To let mem_malloc() use pools (prevents fragmentation and is much faster than
11  * a heap but might waste some memory), define MEM_USE_POOLS to 1, define
12  * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list
13  * of pools like this (more pools can be added between _START and _END):
14  *
15  * Define three pools with sizes 256, 512, and 1512 bytes
16  * LWIP_MALLOC_MEMPOOL_START
17  * LWIP_MALLOC_MEMPOOL(20, 256)
18  * LWIP_MALLOC_MEMPOOL(10, 512)
19  * LWIP_MALLOC_MEMPOOL(5, 1512)
20  * LWIP_MALLOC_MEMPOOL_END
21  */
22
23 /*
24  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
25  * All rights reserved.
26  *
27  * Redistribution and use in source and binary forms, with or without modification,
28  * are permitted provided that the following conditions are met:
29  *
30  * 1. Redistributions of source code must retain the above copyright notice,
31  *    this list of conditions and the following disclaimer.
32  * 2. Redistributions in binary form must reproduce the above copyright notice,
33  *    this list of conditions and the following disclaimer in the documentation
34  *    and/or other materials provided with the distribution.
35  * 3. The name of the author may not be used to endorse or promote products
36  *    derived from this software without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
39  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
41  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
43  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
46  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
47  * OF SUCH DAMAGE.
48  *
49  * This file is part of the lwIP TCP/IP stack.
50  *
51  * Author: Adam Dunkels <adam@sics.se>
52  *         Simon Goldschmidt
53  *
54  */
55
56 #include "lwip/opt.h"
57
58 #if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */
59
60 #include "lwip/def.h"
61 #include "lwip/mem.h"
62 #include "lwip/sys.h"
63 #include "lwip/stats.h"
64
65 #include <string.h>
66
67 #if MEM_USE_POOLS
68 /* lwIP head implemented with different sized pools */
69
70 /**
71  * This structure is used to save the pool one element came from.
72  */
73 struct mem_helper
74 {
75    memp_t poolnr;
76 };
77
78 /**
79  * Allocate memory: determine the smallest pool that is big enough
80  * to contain an element of 'size' and get an element from that pool.
81  *
82  * @param size the size in bytes of the memory needed
83  * @return a pointer to the allocated memory or NULL if the pool is empty
84  */
85 void *
86 mem_malloc(mem_size_t size)
87 {
88   struct mem_helper *element;
89   memp_t poolnr;
90
91   for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
92     /* is this pool big enough to hold an element of the required size
93        plus a struct mem_helper that saves the pool this element came from? */
94     if ((size + sizeof(struct mem_helper)) <= memp_sizes[poolnr]) {
95       break;
96     }
97   }
98   if (poolnr > MEMP_POOL_LAST) {
99     LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
100     return NULL;
101   }
102   element = (struct mem_helper*)memp_malloc(poolnr);
103   if (element == NULL) {
104     /* No need to DEBUGF or ASSERT: This error is already
105        taken care of in memp.c */
106     /** @todo: we could try a bigger pool if this one is empty! */
107     return NULL;
108   }
109
110   /* save the pool number this element came from */
111   element->poolnr = poolnr;
112   /* and return a pointer to the memory directly after the struct mem_helper */
113   element++;
114
115   return element;
116 }
117
118 /**
119  * Free memory previously allocated by mem_malloc. Loads the pool number
120  * and calls memp_free with that pool number to put the element back into
121  * its pool
122  *
123  * @param rmem the memory element to free
124  */
125 void
126 mem_free(void *rmem)
127 {
128   struct mem_helper *hmem = (struct mem_helper*)rmem;
129
130   LWIP_ASSERT("rmem != NULL", (rmem != NULL));
131   LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
132
133   /* get the original struct mem_helper */
134   hmem--;
135
136   LWIP_ASSERT("hmem != NULL", (hmem != NULL));
137   LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
138   LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
139
140   /* and put it in the pool we saved earlier */
141   memp_free(hmem->poolnr, hmem);
142 }
143
144 #else /* MEM_USE_POOLS */
145 /* lwIP replacement for your libc malloc() */
146
147 /**
148  * The heap is made up as a list of structs of this type.
149  * This does not have to be aligned since for getting its size,
150  * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes.
151  */
152 struct mem {
153   /** index (-> ram[next]) of the next struct */
154   mem_size_t next;
155   /** index (-> ram[next]) of the next struct */
156   mem_size_t prev;
157   /** 1: this area is used; 0: this area is unused */
158   u8_t used;
159 };
160
161 /** All allocated blocks will be MIN_SIZE bytes big, at least!
162  * MIN_SIZE can be overridden to suit your needs. Smaller values save space,
163  * larger values could prevent too small blocks to fragment the RAM too much. */
164 #ifndef MIN_SIZE
165 #define MIN_SIZE             12
166 #endif /* MIN_SIZE */
167 /* some alignment macros: we define them here for better source code layout */
168 #define MIN_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
169 #define SIZEOF_STRUCT_MEM    LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
170 #define MEM_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
171
172 /** the heap. we need one struct mem at the end and some room for alignment */
173 static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
174 /** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */
175 static u8_t *ram;
176 /** the last entry, always unused! */
177 static struct mem *ram_end;
178 /** pointer to the lowest free block, this is used for faster search */
179 static struct mem *lfree;
180 /** concurrent access protection */
181 static sys_sem_t mem_sem;
182
183 /**
184  * "Plug holes" by combining adjacent empty struct mems.
185  * After this function is through, there should not exist
186  * one empty struct mem pointing to another empty struct mem.
187  *
188  * @param mem this points to a struct mem which just has been freed
189  * @internal this function is only called by mem_free() and mem_realloc()
190  *
191  * This assumes access to the heap is protected by the calling function
192  * already.
193  */
194 static void
195 plug_holes(struct mem *mem)
196 {
197   struct mem *nmem;
198   struct mem *pmem;
199
200   LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
201   LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
202   LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
203
204   /* plug hole forward */
205   LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
206
207   nmem = (struct mem *)&ram[mem->next];
208   if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
209     /* if mem->next is unused and not end of ram, combine mem and mem->next */
210     if (lfree == nmem) {
211       lfree = mem;
212     }
213     mem->next = nmem->next;
214     ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
215   }
216
217   /* plug hole backward */
218   pmem = (struct mem *)&ram[mem->prev];
219   if (pmem != mem && pmem->used == 0) {
220     /* if mem->prev is unused, combine mem and mem->prev */
221     if (lfree == mem) {
222       lfree = pmem;
223     }
224     pmem->next = mem->next;
225     ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
226   }
227 }
228
229 /**
230  * Zero the heap and initialize start, end and lowest-free
231  */
232 void
233 mem_init(void)
234 {
235   struct mem *mem;
236
237   LWIP_ASSERT("Sanity check alignment",
238     (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
239
240   /* align the heap */
241   ram = LWIP_MEM_ALIGN(ram_heap);
242   /* initialize the start of the heap */
243   mem = (struct mem *)ram;
244   mem->next = MEM_SIZE_ALIGNED;
245   mem->prev = 0;
246   mem->used = 0;
247   /* initialize the end of the heap */
248   ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];
249   ram_end->used = 1;
250   ram_end->next = MEM_SIZE_ALIGNED;
251   ram_end->prev = MEM_SIZE_ALIGNED;
252
253   mem_sem = sys_sem_new(1);
254
255   /* initialize the lowest-free pointer to the start of the heap */
256   lfree = (struct mem *)ram;
257
258 #if MEM_STATS
259   lwip_stats.mem.avail = MEM_SIZE_ALIGNED;
260 #endif /* MEM_STATS */
261 }
262
263 /**
264  * Put a struct mem back on the heap
265  *
266  * @param rmem is the data portion of a struct mem as returned by a previous
267  *             call to mem_malloc()
268  */
269 void
270 mem_free(void *rmem)
271 {
272   struct mem *mem;
273
274   if (rmem == NULL) {
275     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
276     return;
277   }
278   LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
279
280   /* protect the heap from concurrent access */
281   sys_arch_sem_wait(mem_sem, 0);
282
283   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
284     (u8_t *)rmem < (u8_t *)ram_end);
285
286   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
287     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
288 #if MEM_STATS
289     ++lwip_stats.mem.err;
290 #endif /* MEM_STATS */
291     sys_sem_signal(mem_sem);
292     return;
293   }
294   /* Get the corresponding struct mem ... */
295   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
296   /* ... which has to be in a used state ... */
297   LWIP_ASSERT("mem_free: mem->used", mem->used);
298   /* ... and is now unused. */
299   mem->used = 0;
300
301   if (mem < lfree) {
302     /* the newly freed struct is now the lowest */
303     lfree = mem;
304   }
305
306 #if MEM_STATS
307   lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
308 #endif /* MEM_STATS */
309
310   /* finally, see if prev or next are free also */
311   plug_holes(mem);
312   sys_sem_signal(mem_sem);
313 }
314
315 /**
316  * In contrast to its name, mem_realloc can only shrink memory, not expand it.
317  * Since the only use (for now) is in pbuf_realloc (which also can only shrink),
318  * this shouldn't be a problem!
319  *
320  * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked
321  * @param newsize required size after shrinking (needs to be smaller than or
322  *                equal to the previous size)
323  * @return for compatibility reasons: is always == rmem, at the moment
324  */
325 void *
326 mem_realloc(void *rmem, mem_size_t newsize)
327 {
328   mem_size_t size;
329   mem_size_t ptr, ptr2;
330   struct mem *mem, *mem2;
331
332   /* Expand the size of the allocated memory region so that we can
333      adjust for alignment. */
334   newsize = LWIP_MEM_ALIGN_SIZE(newsize);
335
336   if(newsize < MIN_SIZE_ALIGNED) {
337     /* every data block must be at least MIN_SIZE_ALIGNED long */
338     newsize = MIN_SIZE_ALIGNED;
339   }
340
341   if (newsize > MEM_SIZE_ALIGNED) {
342     return NULL;
343   }
344
345   LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
346    (u8_t *)rmem < (u8_t *)ram_end);
347
348   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
349     LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
350     return rmem;
351   }
352   /* Get the corresponding struct mem ... */
353   mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
354   /* ... and its offset pointer */
355   ptr = (u8_t *)mem - ram;
356
357   size = mem->next - ptr - SIZEOF_STRUCT_MEM;
358   LWIP_ASSERT("mem_realloc can only shrink memory", newsize <= size);
359   if (newsize > size) {
360     /* not supported */
361     return NULL;
362   }
363   if (newsize == size) {
364     /* No change in size, simply return */
365     return rmem;
366   }
367
368   /* protect the heap from concurrent access */
369   sys_arch_sem_wait(mem_sem, 0);
370
371 #if MEM_STATS
372   lwip_stats.mem.used -= (size - newsize);
373 #endif /* MEM_STATS */
374
375   mem2 = (struct mem *)&ram[mem->next];
376   if(mem2->used == 0) {
377     /* The next struct is unused, we can simply move it at little */
378     mem_size_t next;
379     /* remember the old next pointer */
380     next = mem2->next;
381     /* create new struct mem which is moved directly after the shrinked mem */
382     ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
383     if (lfree == mem2) {
384       lfree = (struct mem *)&ram[ptr2];
385     }
386     mem2 = (struct mem *)&ram[ptr2];
387     mem2->used = 0;
388     /* restore the next pointer */
389     mem2->next = next;
390     /* link it back to mem */
391     mem2->prev = ptr;
392     /* link mem to it */
393     mem->next = ptr2;
394     /* last thing to restore linked list: as we have moved mem2,
395      * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
396      * the end of the heap */
397     if (mem2->next != MEM_SIZE_ALIGNED) {
398       ((struct mem *)&ram[mem2->next])->prev = ptr2;
399     }
400     /* no need to plug holes, we've already done that */
401   } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
402     /* Next struct is used but there's room for another struct mem with
403      * at least MIN_SIZE_ALIGNED of data.
404      * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
405      * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
406      * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
407      *       region that couldn't hold data, but when mem->next gets freed,
408      *       the 2 regions would be combined, resulting in more free memory */
409     ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
410     mem2 = (struct mem *)&ram[ptr2];
411     if (mem2 < lfree) {
412       lfree = mem2;
413     }
414     mem2->used = 0;
415     mem2->next = mem->next;
416     mem2->prev = ptr;
417     mem->next = ptr2;
418     if (mem2->next != MEM_SIZE_ALIGNED) {
419       ((struct mem *)&ram[mem2->next])->prev = ptr2;
420     }
421     /* the original mem->next is used, so no need to plug holes! */
422   }
423   /* else {
424     next struct mem is used but size between mem and mem2 is not big enough
425     to create another struct mem
426     -> don't do anyhting. 
427     -> the remaining space stays unused since it is too small
428   } */
429   sys_sem_signal(mem_sem);
430   return rmem;
431 }
432
433 /**
434  * Adam's mem_malloc() plus solution for bug #17922
435  * Allocate a block of memory with a minimum of 'size' bytes.
436  *
437  * @param size is the minimum size of the requested block in bytes.
438  * @return pointer to allocated memory or NULL if no free memory was found.
439  *
440  * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT).
441  */
442 void *
443 mem_malloc(mem_size_t size)
444 {
445   mem_size_t ptr, ptr2;
446   struct mem *mem, *mem2;
447
448   if (size == 0) {
449     return NULL;
450   }
451
452   /* Expand the size of the allocated memory region so that we can
453      adjust for alignment. */
454   size = LWIP_MEM_ALIGN_SIZE(size);
455
456   if(size < MIN_SIZE_ALIGNED) {
457     /* every data block must be at least MIN_SIZE_ALIGNED long */
458     size = MIN_SIZE_ALIGNED;
459   }
460
461   if (size > MEM_SIZE_ALIGNED) {
462     return NULL;
463   }
464
465   /* protect the heap from concurrent access */
466   sys_arch_sem_wait(mem_sem, 0);
467
468   /* Scan through the heap searching for a free block that is big enough,
469    * beginning with the lowest free block.
470    */
471   for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
472        ptr = ((struct mem *)&ram[ptr])->next) {
473     mem = (struct mem *)&ram[ptr];
474
475     if ((!mem->used) &&
476         (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
477       /* mem is not used and at least perfect fit is possible:
478        * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
479
480       if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
481         /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
482          * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
483          * -> split large block, create empty remainder,
484          * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
485          * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
486          * struct mem would fit in but no data between mem2 and mem2->next
487          * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
488          *       region that couldn't hold data, but when mem->next gets freed,
489          *       the 2 regions would be combined, resulting in more free memory
490          */
491         ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
492         /* create mem2 struct */
493         mem2 = (struct mem *)&ram[ptr2];
494         mem2->used = 0;
495         mem2->next = mem->next;
496         mem2->prev = ptr;
497         /* and insert it between mem and mem->next */
498         mem->next = ptr2;
499         mem->used = 1;
500
501         if (mem2->next != MEM_SIZE_ALIGNED) {
502           ((struct mem *)&ram[mem2->next])->prev = ptr2;
503         }
504 #if MEM_STATS
505         lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
506         if (lwip_stats.mem.max < lwip_stats.mem.used) {
507           lwip_stats.mem.max = lwip_stats.mem.used;
508         }
509 #endif /* MEM_STATS */
510       } else {
511         /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
512          * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
513          * take care of this).
514          * -> near fit or excact fit: do not split, no mem2 creation
515          * also can't move mem->next directly behind mem, since mem->next
516          * will always be used at this point!
517          */
518         mem->used = 1;
519 #if MEM_STATS
520         lwip_stats.mem.used += mem->next - ((u8_t *)mem - ram);
521         if (lwip_stats.mem.max < lwip_stats.mem.used) {
522           lwip_stats.mem.max = lwip_stats.mem.used;
523         }
524 #endif /* MEM_STATS */
525       }
526
527       if (mem == lfree) {
528         /* Find next free block after mem and update lowest free pointer */
529         while (lfree->used && lfree != ram_end) {
530           lfree = (struct mem *)&ram[lfree->next];
531         }
532         LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
533       }
534       sys_sem_signal(mem_sem);
535       LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
536        (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
537       LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
538        (unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
539       LWIP_ASSERT("mem_malloc: sanity check alignment",
540         (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
541
542       return (u8_t *)mem + SIZEOF_STRUCT_MEM;
543     }
544   }
545   LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
546 #if MEM_STATS
547   ++lwip_stats.mem.err;
548 #endif /* MEM_STATS */
549   sys_sem_signal(mem_sem);
550   return NULL;
551 }
552
553 #endif /* MEM_USE_POOLS */
554 /**
555  * Contiguously allocates enough space for count objects that are size bytes
556  * of memory each and returns a pointer to the allocated memory.
557  *
558  * The allocated memory is filled with bytes of value zero.
559  *
560  * @param count number of objects to allocate
561  * @param size size of the objects to allocate
562  * @return pointer to allocated memory / NULL pointer if there is an error
563  */
564 void *mem_calloc(mem_size_t count, mem_size_t size)
565 {
566   void *p;
567
568   /* allocate 'count' objects of size 'size' */
569   p = mem_malloc(count * size);
570   if (p) {
571     /* zero the memory */
572     memset(p, 0, count * size);
573   }
574   return p;
575 }
576
577 #endif /* !MEM_LIBC_MALLOC */