mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_memp.c Source File

lwip_memp.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Dynamic pool memory manager
00004  *
00005  * lwIP has dedicated pools for many structures (netconn, protocol control blocks,
00006  * packet buffers, ...). All these pools are managed here.
00007  *
00008  * @defgroup mempool Memory pools
00009  * @ingroup infrastructure
00010  * Custom memory pools
00011 
00012  */
00013 
00014 /*
00015  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00016  * All rights reserved.
00017  *
00018  * Redistribution and use in source and binary forms, with or without modification,
00019  * are permitted provided that the following conditions are met:
00020  *
00021  * 1. Redistributions of source code must retain the above copyright notice,
00022  *    this list of conditions and the following disclaimer.
00023  * 2. Redistributions in binary form must reproduce the above copyright notice,
00024  *    this list of conditions and the following disclaimer in the documentation
00025  *    and/or other materials provided with the distribution.
00026  * 3. The name of the author may not be used to endorse or promote products
00027  *    derived from this software without specific prior written permission.
00028  *
00029  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00030  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00031  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00032  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00033  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00034  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00035  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00036  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00037  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00038  * OF SUCH DAMAGE.
00039  *
00040  * This file is part of the lwIP TCP/IP stack.
00041  *
00042  * Author: Adam Dunkels <adam@sics.se>
00043  *
00044  */
00045 
00046 #include "lwip/opt.h"
00047 
00048 #include "lwip/memp.h"
00049 #include "lwip/sys.h"
00050 #include "lwip/stats.h"
00051 
00052 #include <string.h>
00053 
00054 /* Make sure we include everything we need for size calculation required by memp_std.h */
00055 #include "lwip/pbuf.h"
00056 #include "lwip/raw.h"
00057 #include "lwip/udp.h"
00058 #include "lwip/tcp.h"
00059 #include "lwip/priv/tcp_priv.h"
00060 #include "lwip/ip4_frag.h"
00061 #include "lwip/netbuf.h"
00062 #include "lwip/api.h"
00063 #include "lwip/priv/tcpip_priv.h"
00064 #include "lwip/priv/api_msg.h"
00065 #include "lwip/sockets.h"
00066 #include "lwip/netifapi.h"
00067 #include "lwip/etharp.h"
00068 #include "lwip/igmp.h"
00069 #include "lwip/timeouts.h"
00070 /* needed by default MEMP_NUM_SYS_TIMEOUT */
00071 #include "netif/ppp/ppp_opts.h"
00072 #include "lwip/netdb.h"
00073 #include "lwip/dns.h"
00074 #include "lwip/priv/nd6_priv.h"
00075 #include "lwip/ip6_frag.h"
00076 #include "lwip/mld6.h"
00077 
00078 
00079 #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
00080 #include "lwip/priv/memp_std.h"
00081 
00082 const struct memp_desc* const memp_pools[MEMP_MAX] = {
00083 #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
00084 #include "lwip/priv/memp_std.h"
00085 };
00086 
00087 #if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
00088 #undef MEMP_OVERFLOW_CHECK
00089 /* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
00090 #define MEMP_OVERFLOW_CHECK 1
00091 #endif
00092 
00093 #if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC
00094 /**
00095  * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
00096  */
00097 static int
00098 memp_sanity(const struct memp_desc *desc)
00099 {
00100   struct memp *t, *h;
00101 
00102   t = *desc->tab;
00103   if (t != NULL) {
00104     for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
00105       h = ((h->next != NULL) ? h->next->next : NULL)) {
00106       if (t == h) {
00107         return 0;
00108       }
00109     }
00110   }
00111 
00112   return 1;
00113 }
00114 #endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */
00115 
00116 #if MEMP_OVERFLOW_CHECK
00117 /**
00118  * Check if a memp element was victim of an overflow
00119  * (e.g. the restricted area after it has been altered)
00120  *
00121  * @param p the memp element to check
00122  * @param desc the pool p comes from
00123  */
00124 static void
00125 memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc)
00126 {
00127 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
00128   u16_t k;
00129   u8_t *m;
00130   m = (u8_t*)p + MEMP_SIZE + desc->size;
00131   for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
00132     if (m[k] != 0xcd) {
00133       char errstr[128] = "detected memp overflow in pool ";
00134       strcat(errstr, desc->desc);
00135       LWIP_ASSERT(errstr, 0);
00136     }
00137   }
00138 #else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
00139   LWIP_UNUSED_ARG(p);
00140   LWIP_UNUSED_ARG(desc);
00141 #endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
00142 }
00143 
00144 /**
00145  * Check if a memp element was victim of an underflow
00146  * (e.g. the restricted area before it has been altered)
00147  *
00148  * @param p the memp element to check
00149  * @param desc the pool p comes from
00150  */
00151 static void
00152 memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc)
00153 {
00154 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
00155   u16_t k;
00156   u8_t *m;
00157   m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
00158   for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
00159     if (m[k] != 0xcd) {
00160       char errstr[128] = "detected memp underflow in pool ";
00161       strcat(errstr, desc->desc);
00162       LWIP_ASSERT(errstr, 0);
00163     }
00164   }
00165 #else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */
00166   LWIP_UNUSED_ARG(p);
00167   LWIP_UNUSED_ARG(desc);
00168 #endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */
00169 }
00170 
00171 /**
00172  * Initialize the restricted area of on memp element.
00173  */
00174 static void
00175 memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
00176 {
00177 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0
00178   u8_t *m;
00179 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
00180   m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
00181   memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED);
00182 #endif
00183 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
00184   m = (u8_t*)p + MEMP_SIZE + desc->size;
00185   memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED);
00186 #endif
00187 #else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
00188   LWIP_UNUSED_ARG(p);
00189   LWIP_UNUSED_ARG(desc);
00190 #endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */
00191 }
00192 
00193 #if MEMP_OVERFLOW_CHECK >= 2
00194 /**
00195  * Do an overflow check for all elements in every pool.
00196  *
00197  * @see memp_overflow_check_element for a description of the check
00198  */
00199 static void
00200 memp_overflow_check_all(void)
00201 {
00202   u16_t i, j;
00203   struct memp *p;
00204   SYS_ARCH_DECL_PROTECT(old_level);
00205   SYS_ARCH_PROTECT(old_level);
00206 
00207   for (i = 0; i < MEMP_MAX; ++i) {
00208     p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base);
00209     for (j = 0; j < memp_pools[i]->num; ++j) {
00210       memp_overflow_check_element_overflow(p, memp_pools[i]);
00211       memp_overflow_check_element_underflow(p, memp_pools[i]);
00212       p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED));
00213     }
00214   }
00215   SYS_ARCH_UNPROTECT(old_level);
00216 }
00217 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00218 #endif /* MEMP_OVERFLOW_CHECK */
00219 
00220 /**
00221  * Initialize custom memory pool.
00222  * Related functions: memp_malloc_pool, memp_free_pool
00223  *
00224  * @param desc pool to initialize
00225  */
00226 void
00227 memp_init_pool(const struct memp_desc *desc)
00228 {
00229 #if MEMP_MEM_MALLOC
00230   LWIP_UNUSED_ARG(desc);
00231 #else
00232   int i;
00233   struct memp *memp;
00234 
00235   *desc->tab = NULL;
00236   memp = (struct memp*)LWIP_MEM_ALIGN(desc->base);
00237   /* create a linked list of memp elements */
00238   for (i = 0; i < desc->num; ++i) {
00239     memp->next = *desc->tab;
00240     *desc->tab = memp;
00241 #if MEMP_OVERFLOW_CHECK
00242     memp_overflow_init_element(memp, desc);
00243 #endif /* MEMP_OVERFLOW_CHECK */
00244    /* cast through void* to get rid of alignment warnings */
00245    memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
00246 #if MEMP_OVERFLOW_CHECK
00247       + MEMP_SANITY_REGION_AFTER_ALIGNED
00248 #endif
00249     );
00250   }
00251 #if MEMP_STATS
00252   desc->stats->avail = desc->num;
00253 #endif /* MEMP_STATS */
00254 #endif /* !MEMP_MEM_MALLOC */
00255 
00256 #if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
00257   desc->stats->name  = desc->desc;
00258 #endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
00259 }
00260 
00261 /**
00262  * Initializes lwIP built-in pools.
00263  * Related functions: memp_malloc, memp_free
00264  *
00265  * Carves out memp_memory into linked lists for each pool-type.
00266  */
00267 void
00268 memp_init(void)
00269 {
00270   u16_t i;
00271 
00272   /* for every pool: */
00273   for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
00274     memp_init_pool(memp_pools[i]);
00275 
00276 #if LWIP_STATS && MEMP_STATS
00277     lwip_stats.memp[i] = memp_pools[i]->stats;
00278 #endif
00279   }
00280 
00281 #if MEMP_OVERFLOW_CHECK >= 2
00282   /* check everything a first time to see if it worked */
00283   memp_overflow_check_all();
00284 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00285 }
00286 
00287 static void*
00288 #if !MEMP_OVERFLOW_CHECK
00289 do_memp_malloc_pool(const struct memp_desc *desc)
00290 #else
00291 do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
00292 #endif
00293 {
00294   struct memp *memp;
00295   SYS_ARCH_DECL_PROTECT(old_level);
00296 
00297 #if MEMP_MEM_MALLOC
00298   memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
00299   SYS_ARCH_PROTECT(old_level);
00300 #else /* MEMP_MEM_MALLOC */
00301   SYS_ARCH_PROTECT(old_level);
00302 
00303   memp = *desc->tab;
00304 #endif /* MEMP_MEM_MALLOC */
00305 
00306   if (memp != NULL) {
00307 #if !MEMP_MEM_MALLOC
00308 #if MEMP_OVERFLOW_CHECK == 1
00309     memp_overflow_check_element_overflow(memp, desc);
00310     memp_overflow_check_element_underflow(memp, desc);
00311 #endif /* MEMP_OVERFLOW_CHECK */
00312 
00313     *desc->tab = memp->next;
00314 #if MEMP_OVERFLOW_CHECK
00315     memp->next = NULL;
00316 #endif /* MEMP_OVERFLOW_CHECK */
00317 #endif /* !MEMP_MEM_MALLOC */
00318 #if MEMP_OVERFLOW_CHECK
00319     memp->file = file;
00320     memp->line = line;
00321 #if MEMP_MEM_MALLOC
00322     memp_overflow_init_element(memp, desc);
00323 #endif /* MEMP_MEM_MALLOC */
00324 #endif /* MEMP_OVERFLOW_CHECK */
00325     LWIP_ASSERT("memp_malloc: memp properly aligned",
00326                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
00327 #if MEMP_STATS
00328     desc->stats->used++;
00329     if (desc->stats->used > desc->stats->max) {
00330       desc->stats->max = desc->stats->used;
00331     }
00332 #endif
00333     SYS_ARCH_UNPROTECT(old_level);
00334     /* cast through u8_t* to get rid of alignment warnings */
00335     return ((u8_t*)memp + MEMP_SIZE);
00336   } else {
00337     LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
00338 #if MEMP_STATS
00339     desc->stats->err++;
00340 #endif
00341   }
00342 
00343   SYS_ARCH_UNPROTECT(old_level);
00344   return NULL;
00345 }
00346 
00347 /**
00348  * Get an element from a custom pool.
00349  *
00350  * @param desc the pool to get an element from
00351  *
00352  * @return a pointer to the allocated memory or a NULL pointer on error
00353  */
00354 void *
00355 #if !MEMP_OVERFLOW_CHECK
00356 memp_malloc_pool(const struct memp_desc *desc)
00357 #else
00358 memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line)
00359 #endif
00360 {
00361   LWIP_ASSERT("invalid pool desc", desc != NULL);
00362   if (desc == NULL) {
00363     return NULL;
00364   }
00365 
00366 #if !MEMP_OVERFLOW_CHECK
00367   return do_memp_malloc_pool(desc);
00368 #else
00369   return do_memp_malloc_pool_fn(desc, file, line);
00370 #endif
00371 }
00372 
00373 /**
00374  * Get an element from a specific pool.
00375  *
00376  * @param type the pool to get an element from
00377  *
00378  * @return a pointer to the allocated memory or a NULL pointer on error
00379  */
00380 void *
00381 #if !MEMP_OVERFLOW_CHECK
00382 memp_malloc(memp_t type)
00383 #else
00384 memp_malloc_fn(memp_t type, const char* file, const int line)
00385 #endif
00386 {
00387   void *memp;
00388   LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
00389 
00390 #if MEMP_OVERFLOW_CHECK >= 2
00391   memp_overflow_check_all();
00392 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00393 
00394 #if !MEMP_OVERFLOW_CHECK
00395   memp = do_memp_malloc_pool(memp_pools[type]);
00396 #else
00397   memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
00398 #endif
00399 
00400   return memp;
00401 }
00402 
00403 static void
00404 do_memp_free_pool(const struct memp_desc* desc, void *mem)
00405 {
00406   struct memp *memp;
00407   SYS_ARCH_DECL_PROTECT(old_level);
00408 
00409   LWIP_ASSERT("memp_free: mem properly aligned",
00410                 ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
00411 
00412   /* cast through void* to get rid of alignment warnings */
00413   memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
00414 
00415   SYS_ARCH_PROTECT(old_level);
00416 
00417 #if MEMP_OVERFLOW_CHECK == 1
00418   memp_overflow_check_element_overflow(memp, desc);
00419   memp_overflow_check_element_underflow(memp, desc);
00420 #endif /* MEMP_OVERFLOW_CHECK */
00421 
00422 #if MEMP_STATS
00423   desc->stats->used--;
00424 #endif
00425 
00426 #if MEMP_MEM_MALLOC
00427   LWIP_UNUSED_ARG(desc);
00428   SYS_ARCH_UNPROTECT(old_level);
00429   mem_free(memp);
00430 #else /* MEMP_MEM_MALLOC */
00431   memp->next = *desc->tab;
00432   *desc->tab = memp;
00433 
00434 #if MEMP_SANITY_CHECK
00435   LWIP_ASSERT("memp sanity", memp_sanity(desc));
00436 #endif /* MEMP_SANITY_CHECK */
00437 
00438   SYS_ARCH_UNPROTECT(old_level);
00439 #endif /* !MEMP_MEM_MALLOC */
00440 }
00441 
00442 /**
00443  * Put a custom pool element back into its pool.
00444  *
00445  * @param desc the pool where to put mem
00446  * @param mem the memp element to free
00447  */
00448 void
00449 memp_free_pool(const struct memp_desc* desc, void *mem)
00450 {
00451   LWIP_ASSERT("invalid pool desc", desc != NULL);
00452   if ((desc == NULL) || (mem == NULL)) {
00453     return;
00454   }
00455 
00456   do_memp_free_pool(desc, mem);
00457 }
00458 
00459 /**
00460  * Put an element back into its pool.
00461  *
00462  * @param type the pool where to put mem
00463  * @param mem the memp element to free
00464  */
00465 void
00466 memp_free(memp_t type, void *mem)
00467 {
00468 #ifdef LWIP_HOOK_MEMP_AVAILABLE
00469   struct memp *old_first;
00470 #endif
00471 
00472   LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
00473 
00474   if (mem == NULL) {
00475     return;
00476   }
00477 
00478 #if MEMP_OVERFLOW_CHECK >= 2
00479   memp_overflow_check_all();
00480 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00481 
00482 #ifdef LWIP_HOOK_MEMP_AVAILABLE
00483   old_first = *memp_pools[type]->tab;
00484 #endif
00485 
00486   do_memp_free_pool(memp_pools[type], mem);
00487 
00488 #ifdef LWIP_HOOK_MEMP_AVAILABLE
00489   if (old_first == NULL) {
00490     LWIP_HOOK_MEMP_AVAILABLE(type);
00491   }
00492 #endif
00493 }