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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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/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 }
Generated on Tue Jul 12 2022 13:54:29 by
