Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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/altcp.h"
00061 #include "lwip/ip4_frag.h"
00062 #include "lwip/netbuf.h"
00063 #include "lwip/api.h"
00064 #include "lwip/priv/tcpip_priv.h"
00065 #include "lwip/priv/api_msg.h"
00066 #include "lwip/priv/sockets_priv.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 "lwip/netdb.h"
00072 #include "lwip/dns.h"
00073 #include "lwip/priv/nd6_priv.h"
00074 #include "lwip/ip6_frag.h"
00075 #include "lwip/mld6.h"
00076 
00077 #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
00078 #include "lwip/priv/memp_std.h"
00079 
00080 const struct memp_desc *const memp_pools[MEMP_MAX] = {
00081 #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
00082 #include "lwip/priv/memp_std.h"
00083 };
00084 
00085 #ifdef LWIP_HOOK_FILENAME
00086 #include LWIP_HOOK_FILENAME
00087 #endif
00088 
00089 #if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
00090 #undef MEMP_OVERFLOW_CHECK
00091 /* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
00092 #define MEMP_OVERFLOW_CHECK 1
00093 #endif
00094 
00095 #if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC
00096 /**
00097  * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
00098  */
00099 static int
00100 memp_sanity(const struct memp_desc *desc)
00101 {
00102   struct memp *t, *h;
00103 
00104   t = *desc->tab;
00105   if (t != NULL) {
00106     for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
00107          h = ((h->next != NULL) ? h->next->next : NULL)) {
00108       if (t == h) {
00109         return 0;
00110       }
00111     }
00112   }
00113 
00114   return 1;
00115 }
00116 #endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */
00117 
00118 #if MEMP_OVERFLOW_CHECK
00119 /**
00120  * Check if a memp element was victim of an overflow or underflow
00121  * (e.g. the restricted area after/before it has been altered)
00122  *
00123  * @param p the memp element to check
00124  * @param desc the pool p comes from
00125  */
00126 static void
00127 memp_overflow_check_element(struct memp *p, const struct memp_desc *desc)
00128 {
00129   mem_overflow_check_raw((u8_t *)p + MEMP_SIZE, desc->size, "pool ", desc->desc);
00130 }
00131 
00132 /**
00133  * Initialize the restricted area of on memp element.
00134  */
00135 static void
00136 memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
00137 {
00138   mem_overflow_init_raw((u8_t *)p + MEMP_SIZE, desc->size);
00139 }
00140 
00141 #if MEMP_OVERFLOW_CHECK >= 2
00142 /**
00143  * Do an overflow check for all elements in every pool.
00144  *
00145  * @see memp_overflow_check_element for a description of the check
00146  */
00147 static void
00148 memp_overflow_check_all(void)
00149 {
00150   u16_t i, j;
00151   struct memp *p;
00152   SYS_ARCH_DECL_PROTECT(old_level);
00153   SYS_ARCH_PROTECT(old_level);
00154 
00155   for (i = 0; i < MEMP_MAX; ++i) {
00156     p = (struct memp *)LWIP_MEM_ALIGN(memp_pools[i]->base);
00157     for (j = 0; j < memp_pools[i]->num; ++j) {
00158       memp_overflow_check_element(p, memp_pools[i]);
00159       p = LWIP_ALIGNMENT_CAST(struct memp *, ((u8_t *)p + MEMP_SIZE + memp_pools[i]->size + MEM_SANITY_REGION_AFTER_ALIGNED));
00160     }
00161   }
00162   SYS_ARCH_UNPROTECT(old_level);
00163 }
00164 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00165 #endif /* MEMP_OVERFLOW_CHECK */
00166 
00167 /**
00168  * Initialize custom memory pool.
00169  * Related functions: memp_malloc_pool, memp_free_pool
00170  *
00171  * @param desc pool to initialize
00172  */
00173 void
00174 memp_init_pool(const struct memp_desc *desc)
00175 {
00176 #if MEMP_MEM_MALLOC
00177   LWIP_UNUSED_ARG(desc);
00178 #else
00179   int i;
00180   struct memp *memp;
00181 
00182   *desc->tab = NULL;
00183   memp = (struct memp *)LWIP_MEM_ALIGN(desc->base);
00184 #if MEMP_MEM_INIT
00185   /* force memset on pool memory */
00186   memset(memp, 0, (size_t)desc->num * (MEMP_SIZE + desc->size
00187 #if MEMP_OVERFLOW_CHECK
00188                                        + MEM_SANITY_REGION_AFTER_ALIGNED
00189 #endif
00190                                       ));
00191 #endif
00192   /* create a linked list of memp elements */
00193   for (i = 0; i < desc->num; ++i) {
00194     memp->next = *desc->tab;
00195     *desc->tab = memp;
00196 #if MEMP_OVERFLOW_CHECK
00197     memp_overflow_init_element(memp, desc);
00198 #endif /* MEMP_OVERFLOW_CHECK */
00199     /* cast through void* to get rid of alignment warnings */
00200     memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
00201 #if MEMP_OVERFLOW_CHECK
00202                                    + MEM_SANITY_REGION_AFTER_ALIGNED
00203 #endif
00204                                   );
00205   }
00206 #if MEMP_STATS
00207   desc->stats->avail = desc->num;
00208 #endif /* MEMP_STATS */
00209 #endif /* !MEMP_MEM_MALLOC */
00210 
00211 #if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
00212   desc->stats->name  = desc->desc;
00213 #endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
00214 }
00215 
00216 /**
00217  * Initializes lwIP built-in pools.
00218  * Related functions: memp_malloc, memp_free
00219  *
00220  * Carves out memp_memory into linked lists for each pool-type.
00221  */
00222 void
00223 memp_init(void)
00224 {
00225   u16_t i;
00226 
00227   /* for every pool: */
00228   for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
00229     memp_init_pool(memp_pools[i]);
00230 
00231 #if LWIP_STATS && MEMP_STATS
00232     lwip_stats.memp[i] = memp_pools[i]->stats;
00233 #endif
00234   }
00235 
00236 #if MEMP_OVERFLOW_CHECK >= 2
00237   /* check everything a first time to see if it worked */
00238   memp_overflow_check_all();
00239 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00240 }
00241 
00242 static void *
00243 #if !MEMP_OVERFLOW_CHECK
00244 do_memp_malloc_pool(const struct memp_desc *desc)
00245 #else
00246 do_memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
00247 #endif
00248 {
00249   struct memp *memp;
00250   SYS_ARCH_DECL_PROTECT(old_level);
00251 
00252 #if MEMP_MEM_MALLOC
00253   memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
00254   SYS_ARCH_PROTECT(old_level);
00255 #else /* MEMP_MEM_MALLOC */
00256   SYS_ARCH_PROTECT(old_level);
00257 
00258   memp = *desc->tab;
00259 #endif /* MEMP_MEM_MALLOC */
00260 
00261   if (memp != NULL) {
00262 #if !MEMP_MEM_MALLOC
00263 #if MEMP_OVERFLOW_CHECK == 1
00264     memp_overflow_check_element(memp, desc);
00265 #endif /* MEMP_OVERFLOW_CHECK */
00266 
00267     *desc->tab = memp->next;
00268 #if MEMP_OVERFLOW_CHECK
00269     memp->next = NULL;
00270 #endif /* MEMP_OVERFLOW_CHECK */
00271 #endif /* !MEMP_MEM_MALLOC */
00272 #if MEMP_OVERFLOW_CHECK
00273     memp->file = file;
00274     memp->line = line;
00275 #if MEMP_MEM_MALLOC
00276     memp_overflow_init_element(memp, desc);
00277 #endif /* MEMP_MEM_MALLOC */
00278 #endif /* MEMP_OVERFLOW_CHECK */
00279     LWIP_ASSERT("memp_malloc: memp properly aligned",
00280                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
00281 #if MEMP_STATS
00282     desc->stats->used++;
00283     if (desc->stats->used > desc->stats->max) {
00284       desc->stats->max = desc->stats->used;
00285     }
00286 #endif
00287     SYS_ARCH_UNPROTECT(old_level);
00288     /* cast through u8_t* to get rid of alignment warnings */
00289     return ((u8_t *)memp + MEMP_SIZE);
00290   } else {
00291 #if MEMP_STATS
00292     desc->stats->err++;
00293 #endif
00294     SYS_ARCH_UNPROTECT(old_level);
00295     LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
00296   }
00297 
00298   return NULL;
00299 }
00300 
00301 /**
00302  * Get an element from a custom pool.
00303  *
00304  * @param desc the pool to get an element from
00305  *
00306  * @return a pointer to the allocated memory or a NULL pointer on error
00307  */
00308 void *
00309 #if !MEMP_OVERFLOW_CHECK
00310 memp_malloc_pool(const struct memp_desc *desc)
00311 #else
00312 memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
00313 #endif
00314 {
00315   LWIP_ASSERT("invalid pool desc", desc != NULL);
00316   if (desc == NULL) {
00317     return NULL;
00318   }
00319 
00320 #if !MEMP_OVERFLOW_CHECK
00321   return do_memp_malloc_pool(desc);
00322 #else
00323   return do_memp_malloc_pool_fn(desc, file, line);
00324 #endif
00325 }
00326 
00327 /**
00328  * Get an element from a specific pool.
00329  *
00330  * @param type the pool to get an element from
00331  *
00332  * @return a pointer to the allocated memory or a NULL pointer on error
00333  */
00334 void *
00335 #if !MEMP_OVERFLOW_CHECK
00336 memp_malloc(memp_t type)
00337 #else
00338 memp_malloc_fn(memp_t type, const char *file, const int line)
00339 #endif
00340 {
00341   void *memp;
00342   LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
00343 
00344 #if MEMP_OVERFLOW_CHECK >= 2
00345   memp_overflow_check_all();
00346 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00347 
00348 #if !MEMP_OVERFLOW_CHECK
00349   memp = do_memp_malloc_pool(memp_pools[type]);
00350 #else
00351   memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
00352 #endif
00353 
00354   return memp;
00355 }
00356 
00357 static void
00358 do_memp_free_pool(const struct memp_desc *desc, void *mem)
00359 {
00360   struct memp *memp;
00361   SYS_ARCH_DECL_PROTECT(old_level);
00362 
00363   LWIP_ASSERT("memp_free: mem properly aligned",
00364               ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
00365 
00366   /* cast through void* to get rid of alignment warnings */
00367   memp = (struct memp *)(void *)((u8_t *)mem - MEMP_SIZE);
00368 
00369   SYS_ARCH_PROTECT(old_level);
00370 
00371 #if MEMP_OVERFLOW_CHECK == 1
00372   memp_overflow_check_element(memp, desc);
00373 #endif /* MEMP_OVERFLOW_CHECK */
00374 
00375 #if MEMP_STATS
00376   desc->stats->used--;
00377 #endif
00378 
00379 #if MEMP_MEM_MALLOC
00380   LWIP_UNUSED_ARG(desc);
00381   SYS_ARCH_UNPROTECT(old_level);
00382   mem_free(memp);
00383 #else /* MEMP_MEM_MALLOC */
00384   memp->next = *desc->tab;
00385   *desc->tab = memp;
00386 
00387 #if MEMP_SANITY_CHECK
00388   LWIP_ASSERT("memp sanity", memp_sanity(desc));
00389 #endif /* MEMP_SANITY_CHECK */
00390 
00391   SYS_ARCH_UNPROTECT(old_level);
00392 #endif /* !MEMP_MEM_MALLOC */
00393 }
00394 
00395 /**
00396  * Put a custom pool element back into its pool.
00397  *
00398  * @param desc the pool where to put mem
00399  * @param mem the memp element to free
00400  */
00401 void
00402 memp_free_pool(const struct memp_desc *desc, void *mem)
00403 {
00404   LWIP_ASSERT("invalid pool desc", desc != NULL);
00405   if ((desc == NULL) || (mem == NULL)) {
00406     return;
00407   }
00408 
00409   do_memp_free_pool(desc, mem);
00410 }
00411 
00412 /**
00413  * Put an element back into its pool.
00414  *
00415  * @param type the pool where to put mem
00416  * @param mem the memp element to free
00417  */
00418 void
00419 memp_free(memp_t type, void *mem)
00420 {
00421 #ifdef LWIP_HOOK_MEMP_AVAILABLE
00422   struct memp *old_first;
00423 #endif
00424 
00425   LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
00426 
00427   if (mem == NULL) {
00428     return;
00429   }
00430 
00431 #if MEMP_OVERFLOW_CHECK >= 2
00432   memp_overflow_check_all();
00433 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
00434 
00435 #ifdef LWIP_HOOK_MEMP_AVAILABLE
00436   old_first = *memp_pools[type]->tab;
00437 #endif
00438 
00439   do_memp_free_pool(memp_pools[type], mem);
00440 
00441 #ifdef LWIP_HOOK_MEMP_AVAILABLE
00442   if (old_first == NULL) {
00443     LWIP_HOOK_MEMP_AVAILABLE(type);
00444   }
00445 #endif
00446 }