ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mem.c
Go to the documentation of this file.
00001 
00023 /*
00024  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00025  * All rights reserved.
00026  *
00027  * Redistribution and use in source and binary forms, with or without modification,
00028  * are permitted provided that the following conditions are met:
00029  *
00030  * 1. Redistributions of source code must retain the above copyright notice,
00031  *    this list of conditions and the following disclaimer.
00032  * 2. Redistributions in binary form must reproduce the above copyright notice,
00033  *    this list of conditions and the following disclaimer in the documentation
00034  *    and/or other materials provided with the distribution.
00035  * 3. The name of the author may not be used to endorse or promote products
00036  *    derived from this software without specific prior written permission.
00037  *
00038  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00040  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00041  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00042  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00043  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00044  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00045  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00046  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00047  * OF SUCH DAMAGE.
00048  *
00049  * This file is part of the lwIP TCP/IP stack.
00050  *
00051  * Author: Adam Dunkels <adam@sics.se>
00052  *         Simon Goldschmidt
00053  *
00054  */
00055 
00056 #include "lwip/opt.h"
00057 
00058 #if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */
00059 
00060 #include "lwip/def.h"
00061 #include "lwip/mem.h"
00062 #include "lwip/sys.h"
00063 #include "lwip/stats.h"
00064 #include "lwip/err.h"
00065 
00066 #include <string.h>
00067 
00068 #if MEM_USE_POOLS
00069 /* lwIP head implemented with different sized pools */
00070 
00078 void *
00079 mem_malloc(mem_size_t size)
00080 {
00081   struct memp_malloc_helper *element;
00082   memp_t poolnr;
00083   mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
00084 
00085   for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
00086 #if MEM_USE_POOLS_TRY_BIGGER_POOL
00087 again:
00088 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
00089     /* is this pool big enough to hold an element of the required size
00090        plus a struct memp_malloc_helper that saves the pool this element came from? */
00091     if (required_size <= memp_sizes[poolnr]) {
00092       break;
00093     }
00094   }
00095   if (poolnr > MEMP_POOL_LAST) {
00096     LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
00097     return NULL;
00098   }
00099   element = (struct memp_malloc_helper*)memp_malloc(poolnr);
00100   if (element == NULL) {
00101     /* No need to DEBUGF or ASSERT: This error is already
00102        taken care of in memp.c */
00103 #if MEM_USE_POOLS_TRY_BIGGER_POOL
00104 
00105     if (poolnr < MEMP_POOL_LAST) {
00106       poolnr++;
00107       goto again;
00108     }
00109 #endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
00110     return NULL;
00111   }
00112 
00113   /* save the pool number this element came from */
00114   element->poolnr = poolnr;
00115   /* and return a pointer to the memory directly after the struct memp_malloc_helper */
00116   element++;
00117 
00118   return element;
00119 }
00120 
00128 void
00129 mem_free(void *rmem)
00130 {
00131   struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
00132 
00133   LWIP_ASSERT("rmem != NULL", (rmem != NULL));
00134   LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
00135 
00136   /* get the original struct memp_malloc_helper */
00137   hmem--;
00138 
00139   LWIP_ASSERT("hmem != NULL", (hmem != NULL));
00140   LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
00141   LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
00142 
00143   /* and put it in the pool we saved earlier */
00144   memp_free(hmem->poolnr, hmem);
00145 }
00146 
00147 #else /* MEM_USE_POOLS */
00148 /* lwIP replacement for your libc malloc() */
00149 
00155 struct mem {
00157   mem_size_t next;
00159   mem_size_t prev;
00161   u8_t used;
00162 };
00163 
00167 #ifndef MIN_SIZE
00168 #define MIN_SIZE             12
00169 #endif /* MIN_SIZE */
00170 /* some alignment macros: we define them here for better source code layout */
00171 #define MIN_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
00172 #define SIZEOF_STRUCT_MEM    LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
00173 #define MEM_SIZE_ALIGNED     LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
00174 
00179 #ifndef LWIP_RAM_HEAP_POINTER
00180 
00181 u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
00182 #define LWIP_RAM_HEAP_POINTER ram_heap
00183 #endif /* LWIP_RAM_HEAP_POINTER */
00184 
00186 static u8_t *ram;
00188 static struct mem *ram_end;
00190 static struct mem *lfree;
00191 
00193 static sys_mutex_t mem_mutex;
00194 
00195 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00196 
00197 static volatile u8_t mem_free_count;
00198 
00199 /* Allow mem_free from other (e.g. interrupt) context */
00200 #define LWIP_MEM_FREE_DECL_PROTECT()  SYS_ARCH_DECL_PROTECT(lev_free)
00201 #define LWIP_MEM_FREE_PROTECT()       SYS_ARCH_PROTECT(lev_free)
00202 #define LWIP_MEM_FREE_UNPROTECT()     SYS_ARCH_UNPROTECT(lev_free)
00203 #define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
00204 #define LWIP_MEM_ALLOC_PROTECT()      SYS_ARCH_PROTECT(lev_alloc)
00205 #define LWIP_MEM_ALLOC_UNPROTECT()    SYS_ARCH_UNPROTECT(lev_alloc)
00206 
00207 #else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00208 
00209 /* Protect the heap only by using a semaphore */
00210 #define LWIP_MEM_FREE_DECL_PROTECT()
00211 #define LWIP_MEM_FREE_PROTECT()    sys_mutex_lock(&mem_mutex)
00212 #define LWIP_MEM_FREE_UNPROTECT()  sys_mutex_unlock(&mem_mutex)
00213 /* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
00214 #define LWIP_MEM_ALLOC_DECL_PROTECT()
00215 #define LWIP_MEM_ALLOC_PROTECT()
00216 #define LWIP_MEM_ALLOC_UNPROTECT()
00217 
00218 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00219 
00220 
00232 static void
00233 plug_holes(struct mem *mem)
00234 {
00235   struct mem *nmem;
00236   struct mem *pmem;
00237 
00238   LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
00239   LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
00240   LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
00241 
00242   /* plug hole forward */
00243   LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
00244 
00245   nmem = (struct mem *)(void *)&ram[mem->next];
00246   if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
00247     /* if mem->next is unused and not end of ram, combine mem and mem->next */
00248     if (lfree == nmem) {
00249       lfree = mem;
00250     }
00251     mem->next = nmem->next;
00252     ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
00253   }
00254 
00255   /* plug hole backward */
00256   pmem = (struct mem *)(void *)&ram[mem->prev];
00257   if (pmem != mem && pmem->used == 0) {
00258     /* if mem->prev is unused, combine mem and mem->prev */
00259     if (lfree == mem) {
00260       lfree = pmem;
00261     }
00262     pmem->next = mem->next;
00263     ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
00264   }
00265 }
00266 
00270 void
00271 mem_init(void)
00272 {
00273   struct mem *mem;
00274 
00275   LWIP_ASSERT("Sanity check alignment",
00276     (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
00277 
00278   /* align the heap */
00279   ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
00280   /* initialize the start of the heap */
00281   mem = (struct mem *)(void *)ram;
00282   mem->next = MEM_SIZE_ALIGNED;
00283   mem->prev = 0;
00284   mem->used = 0;
00285   /* initialize the end of the heap */
00286   ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
00287   ram_end->used = 1;
00288   ram_end->next = MEM_SIZE_ALIGNED;
00289   ram_end->prev = MEM_SIZE_ALIGNED;
00290 
00291   /* initialize the lowest-free pointer to the start of the heap */
00292   lfree = (struct mem *)(void *)ram;
00293 
00294   MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
00295 
00296   if(sys_mutex_new(&mem_mutex) != ERR_OK) {
00297     LWIP_ASSERT("failed to create mem_mutex", 0);
00298   }
00299 }
00300 
00307 void
00308 mem_free(void *rmem)
00309 {
00310   struct mem *mem;
00311   LWIP_MEM_FREE_DECL_PROTECT();
00312 
00313   if (rmem == NULL) {
00314     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
00315     return;
00316   }
00317   LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
00318 
00319   LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
00320     (u8_t *)rmem < (u8_t *)ram_end);
00321 
00322   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
00323     SYS_ARCH_DECL_PROTECT(lev);
00324     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
00325     /* protect mem stats from concurrent access */
00326     SYS_ARCH_PROTECT(lev);
00327     MEM_STATS_INC(illegal);
00328     SYS_ARCH_UNPROTECT(lev);
00329     return;
00330   }
00331   /* protect the heap from concurrent access */
00332   LWIP_MEM_FREE_PROTECT();
00333   /* Get the corresponding struct mem ... */
00334   mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
00335   /* ... which has to be in a used state ... */
00336   LWIP_ASSERT("mem_free: mem->used", mem->used);
00337   /* ... and is now unused. */
00338   mem->used = 0;
00339 
00340   if (mem < lfree) {
00341     /* the newly freed struct is now the lowest */
00342     lfree = mem;
00343   }
00344 
00345   MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
00346 
00347   /* finally, see if prev or next are free also */
00348   plug_holes(mem);
00349 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00350   mem_free_count = 1;
00351 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00352   LWIP_MEM_FREE_UNPROTECT();
00353 }
00354 
00365 void *
00366 mem_trim(void *rmem, mem_size_t newsize)
00367 {
00368   mem_size_t size;
00369   mem_size_t ptr, ptr2;
00370   struct mem *mem, *mem2;
00371   /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
00372   LWIP_MEM_FREE_DECL_PROTECT();
00373 
00374   /* Expand the size of the allocated memory region so that we can
00375      adjust for alignment. */
00376   newsize = LWIP_MEM_ALIGN_SIZE(newsize);
00377 
00378   if(newsize < MIN_SIZE_ALIGNED) {
00379     /* every data block must be at least MIN_SIZE_ALIGNED long */
00380     newsize = MIN_SIZE_ALIGNED;
00381   }
00382 
00383   if (newsize > MEM_SIZE_ALIGNED) {
00384     return NULL;
00385   }
00386 
00387   LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
00388    (u8_t *)rmem < (u8_t *)ram_end);
00389 
00390   if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
00391     SYS_ARCH_DECL_PROTECT(lev);
00392     LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
00393     /* protect mem stats from concurrent access */
00394     SYS_ARCH_PROTECT(lev);
00395     MEM_STATS_INC(illegal);
00396     SYS_ARCH_UNPROTECT(lev);
00397     return rmem;
00398   }
00399   /* Get the corresponding struct mem ... */
00400   mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
00401   /* ... and its offset pointer */
00402   ptr = (mem_size_t)((u8_t *)mem - ram);
00403 
00404   size = mem->next - ptr - SIZEOF_STRUCT_MEM;
00405   LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
00406   if (newsize > size) {
00407     /* not supported */
00408     return NULL;
00409   }
00410   if (newsize == size) {
00411     /* No change in size, simply return */
00412     return rmem;
00413   }
00414 
00415   /* protect the heap from concurrent access */
00416   LWIP_MEM_FREE_PROTECT();
00417 
00418   mem2 = (struct mem *)(void *)&ram[mem->next];
00419   if(mem2->used == 0) {
00420     /* The next struct is unused, we can simply move it at little */
00421     mem_size_t next;
00422     /* remember the old next pointer */
00423     next = mem2->next;
00424     /* create new struct mem which is moved directly after the shrinked mem */
00425     ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
00426     if (lfree == mem2) {
00427       lfree = (struct mem *)(void *)&ram[ptr2];
00428     }
00429     mem2 = (struct mem *)(void *)&ram[ptr2];
00430     mem2->used = 0;
00431     /* restore the next pointer */
00432     mem2->next = next;
00433     /* link it back to mem */
00434     mem2->prev = ptr;
00435     /* link mem to it */
00436     mem->next = ptr2;
00437     /* last thing to restore linked list: as we have moved mem2,
00438      * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
00439      * the end of the heap */
00440     if (mem2->next != MEM_SIZE_ALIGNED) {
00441       ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
00442     }
00443     MEM_STATS_DEC_USED(used, (size - newsize));
00444     /* no need to plug holes, we've already done that */
00445   } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
00446     /* Next struct is used but there's room for another struct mem with
00447      * at least MIN_SIZE_ALIGNED of data.
00448      * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
00449      * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
00450      * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
00451      *       region that couldn't hold data, but when mem->next gets freed,
00452      *       the 2 regions would be combined, resulting in more free memory */
00453     ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
00454     mem2 = (struct mem *)(void *)&ram[ptr2];
00455     if (mem2 < lfree) {
00456       lfree = mem2;
00457     }
00458     mem2->used = 0;
00459     mem2->next = mem->next;
00460     mem2->prev = ptr;
00461     mem->next = ptr2;
00462     if (mem2->next != MEM_SIZE_ALIGNED) {
00463       ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
00464     }
00465     MEM_STATS_DEC_USED(used, (size - newsize));
00466     /* the original mem->next is used, so no need to plug holes! */
00467   }
00468   /* else {
00469     next struct mem is used but size between mem and mem2 is not big enough
00470     to create another struct mem
00471     -> don't do anyhting. 
00472     -> the remaining space stays unused since it is too small
00473   } */
00474 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00475   mem_free_count = 1;
00476 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00477   LWIP_MEM_FREE_UNPROTECT();
00478   return rmem;
00479 }
00480 
00490 void *
00491 mem_malloc(mem_size_t size)
00492 {
00493   mem_size_t ptr, ptr2;
00494   struct mem *mem, *mem2;
00495 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00496   u8_t local_mem_free_count = 0;
00497 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00498   LWIP_MEM_ALLOC_DECL_PROTECT();
00499 
00500   if (size == 0) {
00501     return NULL;
00502   }
00503 
00504   /* Expand the size of the allocated memory region so that we can
00505      adjust for alignment. */
00506   size = LWIP_MEM_ALIGN_SIZE(size);
00507 
00508   if(size < MIN_SIZE_ALIGNED) {
00509     /* every data block must be at least MIN_SIZE_ALIGNED long */
00510     size = MIN_SIZE_ALIGNED;
00511   }
00512 
00513   if (size > MEM_SIZE_ALIGNED) {
00514     return NULL;
00515   }
00516 
00517   /* protect the heap from concurrent access */
00518   sys_mutex_lock(&mem_mutex);
00519   LWIP_MEM_ALLOC_PROTECT();
00520 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00521   /* run as long as a mem_free disturbed mem_malloc */
00522   do {
00523     local_mem_free_count = 0;
00524 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00525 
00526     /* Scan through the heap searching for a free block that is big enough,
00527      * beginning with the lowest free block.
00528      */
00529     for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;
00530          ptr = ((struct mem *)(void *)&ram[ptr])->next) {
00531       mem = (struct mem *)(void *)&ram[ptr];
00532 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00533       mem_free_count = 0;
00534       LWIP_MEM_ALLOC_UNPROTECT();
00535       /* allow mem_free to run */
00536       LWIP_MEM_ALLOC_PROTECT();
00537       if (mem_free_count != 0) {
00538         local_mem_free_count = mem_free_count;
00539       }
00540       mem_free_count = 0;
00541 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00542 
00543       if ((!mem->used) &&
00544           (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
00545         /* mem is not used and at least perfect fit is possible:
00546          * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
00547 
00548         if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
00549           /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing
00550            * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
00551            * -> split large block, create empty remainder,
00552            * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
00553            * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
00554            * struct mem would fit in but no data between mem2 and mem2->next
00555            * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
00556            *       region that couldn't hold data, but when mem->next gets freed,
00557            *       the 2 regions would be combined, resulting in more free memory
00558            */
00559           ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
00560           /* create mem2 struct */
00561           mem2 = (struct mem *)(void *)&ram[ptr2];
00562           mem2->used = 0;
00563           mem2->next = mem->next;
00564           mem2->prev = ptr;
00565           /* and insert it between mem and mem->next */
00566           mem->next = ptr2;
00567           mem->used = 1;
00568 
00569           if (mem2->next != MEM_SIZE_ALIGNED) {
00570             ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
00571           }
00572           MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
00573         } else {
00574           /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
00575            * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
00576            * take care of this).
00577            * -> near fit or excact fit: do not split, no mem2 creation
00578            * also can't move mem->next directly behind mem, since mem->next
00579            * will always be used at this point!
00580            */
00581           mem->used = 1;
00582           MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram));
00583         }
00584 
00585         if (mem == lfree) {
00586           /* Find next free block after mem and update lowest free pointer */
00587           while (lfree->used && lfree != ram_end) {
00588             LWIP_MEM_ALLOC_UNPROTECT();
00589             /* prevent high interrupt latency... */
00590             LWIP_MEM_ALLOC_PROTECT();
00591             lfree = (struct mem *)(void *)&ram[lfree->next];
00592           }
00593           LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
00594         }
00595         LWIP_MEM_ALLOC_UNPROTECT();
00596         sys_mutex_unlock(&mem_mutex);
00597         LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
00598          (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
00599         LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
00600          ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
00601         LWIP_ASSERT("mem_malloc: sanity check alignment",
00602           (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
00603 
00604         return (u8_t *)mem + SIZEOF_STRUCT_MEM;
00605       }
00606     }
00607 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00608     /* if we got interrupted by a mem_free, try again */
00609   } while(local_mem_free_count != 0);
00610 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
00611   LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
00612   MEM_STATS_INC(err);
00613   LWIP_MEM_ALLOC_UNPROTECT();
00614   sys_mutex_unlock(&mem_mutex);
00615   return NULL;
00616 }
00617 
00618 #endif /* MEM_USE_POOLS */
00619 
00629 void *mem_calloc(mem_size_t count, mem_size_t size)
00630 {
00631   void *p;
00632 
00633   /* allocate 'count' objects of size 'size' */
00634   p = mem_malloc(count * size);
00635   if (p) {
00636     /* zero the memory */
00637     memset(p, 0, count * size);
00638   }
00639   return p;
00640 }
00641 
00642 #endif /* !MEM_LIBC_MALLOC */

Generated on Fri May 25 2012 04:34:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.