Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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 #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 Sun Jul 17 2022 08:25:24 by 1.7.2