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