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