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.
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 #include "lwip/opt.h" 00042 00043 #include "lwip/memp.h" 00044 #include "lwip/pbuf.h" 00045 #include "lwip/udp.h" 00046 #include "lwip/raw.h" 00047 #include "lwip/tcp_impl.h" 00048 #include "lwip/igmp.h" 00049 #include "lwip/api.h" 00050 #include "lwip/api_msg.h" 00051 #include "lwip/tcpip.h" 00052 #include "lwip/sys.h" 00053 #include "lwip/timers.h" 00054 #include "lwip/stats.h" 00055 #include "netif/etharp.h" 00056 #include "lwip/ip_frag.h" 00057 #include "lwip/snmp_structs.h" 00058 #include "lwip/snmp_msg.h" 00059 #include "lwip/dns.h" 00060 #include "netif/ppp_oe.h" 00061 00062 #include <string.h> 00063 00064 #if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ 00065 00066 struct memp { 00067 struct memp *next; 00068 #if MEMP_OVERFLOW_CHECK 00069 const char *file; 00070 int line; 00071 #endif /* MEMP_OVERFLOW_CHECK */ 00072 }; 00073 00074 #if MEMP_OVERFLOW_CHECK 00075 /* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning 00076 * and at the end of each element, initialize them as 0xcd and check 00077 * them later. */ 00078 /* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, 00079 * every single element in each pool is checked! 00080 * This is VERY SLOW but also very helpful. */ 00081 /* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in 00082 * lwipopts.h to change the amount reserved for checking. */ 00083 #ifndef MEMP_SANITY_REGION_BEFORE 00084 #define MEMP_SANITY_REGION_BEFORE 16 00085 #endif /* MEMP_SANITY_REGION_BEFORE*/ 00086 #if MEMP_SANITY_REGION_BEFORE > 0 00087 #define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) 00088 #else 00089 #define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 00090 #endif /* MEMP_SANITY_REGION_BEFORE*/ 00091 #ifndef MEMP_SANITY_REGION_AFTER 00092 #define MEMP_SANITY_REGION_AFTER 16 00093 #endif /* MEMP_SANITY_REGION_AFTER*/ 00094 #if MEMP_SANITY_REGION_AFTER > 0 00095 #define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) 00096 #else 00097 #define MEMP_SANITY_REGION_AFTER_ALIGNED 0 00098 #endif /* MEMP_SANITY_REGION_AFTER*/ 00099 00100 /* MEMP_SIZE: save space for struct memp and for sanity check */ 00101 #define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) 00102 #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) 00103 00104 #else /* MEMP_OVERFLOW_CHECK */ 00105 00106 /* No sanity checks 00107 * We don't need to preserve the struct memp while not allocated, so we 00108 * can save a little space and set MEMP_SIZE to 0. 00109 */ 00110 #define MEMP_SIZE 0 00111 #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) 00112 00113 #endif /* MEMP_OVERFLOW_CHECK */ 00114 00115 /** This array holds the first free element of each pool. 00116 * Elements form a linked list. */ 00117 static struct memp *memp_tab[MEMP_MAX]; 00118 00119 #else /* MEMP_MEM_MALLOC */ 00120 00121 #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) 00122 00123 #endif /* MEMP_MEM_MALLOC */ 00124 00125 /** This array holds the element sizes of each pool. */ 00126 #if !MEM_USE_POOLS && !MEMP_MEM_MALLOC 00127 static 00128 #endif 00129 const u16_t memp_sizes[MEMP_MAX] = { 00130 #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), 00131 #include "lwip/memp_std.h" 00132 }; 00133 00134 #if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ 00135 00136 /** This array holds the number of elements in each pool. */ 00137 static const u16_t memp_num[MEMP_MAX] = { 00138 #define LWIP_MEMPOOL(name,num,size,desc) (num), 00139 #include "lwip/memp_std.h" 00140 }; 00141 00142 /** This array holds a textual description of each pool. */ 00143 #ifdef LWIP_DEBUG 00144 static const char *memp_desc[MEMP_MAX] = { 00145 #define LWIP_MEMPOOL(name,num,size,desc) (desc), 00146 #include "lwip/memp_std.h" 00147 }; 00148 #endif /* LWIP_DEBUG */ 00149 00150 #if MEMP_SEPARATE_POOLS 00151 00152 /** This creates each memory pool. These are named memp_memory_XXX_base (where 00153 * XXX is the name of the pool defined in memp_std.h). 00154 * To relocate a pool, declare it as extern in cc.h. Example for GCC: 00155 * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; 00156 */ 00157 #define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ 00158 [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; 00159 #include "lwip/memp_std.h" 00160 00161 /** This array holds the base of each memory pool. */ 00162 static u8_t *const memp_bases[] = { 00163 #define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, 00164 #include "lwip/memp_std.h" 00165 }; 00166 00167 #else /* MEMP_SEPARATE_POOLS */ 00168 00169 /** This is the actual memory used by the pools (all pools in one big block). */ 00170 static u8_t memp_memory[MEM_ALIGNMENT - 1 00171 #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) 00172 #include "lwip/memp_std.h" 00173 ]; 00174 00175 #endif /* MEMP_SEPARATE_POOLS */ 00176 00177 #if MEMP_SANITY_CHECK 00178 /** 00179 * Check that memp-lists don't form a circle 00180 */ 00181 static int 00182 memp_sanity(void) 00183 { 00184 s16_t i, c; 00185 struct memp *m, *n; 00186 00187 for (i = 0; i < MEMP_MAX; i++) { 00188 for (m = memp_tab[i]; m != NULL; m = m->next) { 00189 c = 1; 00190 for (n = memp_tab[i]; n != NULL; n = n->next) { 00191 if (n == m && --c < 0) { 00192 return 0; 00193 } 00194 } 00195 } 00196 } 00197 return 1; 00198 } 00199 #endif /* MEMP_SANITY_CHECK*/ 00200 #if MEMP_OVERFLOW_CHECK 00201 #if defined(LWIP_DEBUG) && MEMP_STATS 00202 static const char * memp_overflow_names[] = { 00203 #define LWIP_MEMPOOL(name,num,size,desc) "/"desc, 00204 #include "lwip/memp_std.h" 00205 }; 00206 #endif 00207 00208 /** 00209 * Check if a memp element was victim of an overflow 00210 * (e.g. the restricted area after it has been altered) 00211 * 00212 * @param p the memp element to check 00213 * @param memp_type the pool p comes from 00214 */ 00215 static void 00216 memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) 00217 { 00218 u16_t k; 00219 u8_t *m; 00220 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 00221 m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; 00222 for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { 00223 if (m[k] != 0xcd) { 00224 char errstr[128] = "detected memp overflow in pool "; 00225 char digit[] = "0"; 00226 if(memp_type >= 10) { 00227 digit[0] = '0' + (memp_type/10); 00228 strcat(errstr, digit); 00229 } 00230 digit[0] = '0' + (memp_type%10); 00231 strcat(errstr, digit); 00232 #if defined(LWIP_DEBUG) && MEMP_STATS 00233 strcat(errstr, memp_overflow_names[memp_type]); 00234 #endif 00235 LWIP_ASSERT(errstr, 0); 00236 } 00237 } 00238 #endif 00239 } 00240 00241 /** 00242 * Check if a memp element was victim of an underflow 00243 * (e.g. the restricted area before it has been altered) 00244 * 00245 * @param p the memp element to check 00246 * @param memp_type the pool p comes from 00247 */ 00248 static void 00249 memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) 00250 { 00251 u16_t k; 00252 u8_t *m; 00253 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 00254 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; 00255 for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { 00256 if (m[k] != 0xcd) { 00257 char errstr[128] = "detected memp underflow in pool "; 00258 char digit[] = "0"; 00259 if(memp_type >= 10) { 00260 digit[0] = '0' + (memp_type/10); 00261 strcat(errstr, digit); 00262 } 00263 digit[0] = '0' + (memp_type%10); 00264 strcat(errstr, digit); 00265 #if defined(LWIP_DEBUG) && MEMP_STATS 00266 strcat(errstr, memp_overflow_names[memp_type]); 00267 #endif 00268 LWIP_ASSERT(errstr, 0); 00269 } 00270 } 00271 #endif 00272 } 00273 00274 /** 00275 * Do an overflow check for all elements in every pool. 00276 * 00277 * @see memp_overflow_check_element for a description of the check 00278 */ 00279 static void 00280 memp_overflow_check_all(void) 00281 { 00282 u16_t i, j; 00283 struct memp *p; 00284 00285 p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00286 for (i = 0; i < MEMP_MAX; ++i) { 00287 p = p; 00288 for (j = 0; j < memp_num[i]; ++j) { 00289 memp_overflow_check_element_overflow(p, i); 00290 p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); 00291 } 00292 } 00293 p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00294 for (i = 0; i < MEMP_MAX; ++i) { 00295 p = p; 00296 for (j = 0; j < memp_num[i]; ++j) { 00297 memp_overflow_check_element_underflow(p, i); 00298 p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); 00299 } 00300 } 00301 } 00302 00303 /** 00304 * Initialize the restricted areas of all memp elements in every pool. 00305 */ 00306 static void 00307 memp_overflow_init(void) 00308 { 00309 u16_t i, j; 00310 struct memp *p; 00311 u8_t *m; 00312 00313 p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00314 for (i = 0; i < MEMP_MAX; ++i) { 00315 p = p; 00316 for (j = 0; j < memp_num[i]; ++j) { 00317 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 00318 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; 00319 memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); 00320 #endif 00321 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 00322 m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; 00323 memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); 00324 #endif 00325 p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); 00326 } 00327 } 00328 } 00329 #endif /* MEMP_OVERFLOW_CHECK */ 00330 00331 /** 00332 * Initialize this module. 00333 * 00334 * Carves out memp_memory into linked lists for each pool-type. 00335 */ 00336 void 00337 memp_init(void) 00338 { 00339 struct memp *memp; 00340 u16_t i, j; 00341 00342 for (i = 0; i < MEMP_MAX; ++i) { 00343 MEMP_STATS_AVAIL(used, i, 0); 00344 MEMP_STATS_AVAIL(max, i, 0); 00345 MEMP_STATS_AVAIL(err, i, 0); 00346 MEMP_STATS_AVAIL(avail, i, memp_num[i]); 00347 } 00348 00349 #if !MEMP_SEPARATE_POOLS 00350 memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00351 #endif /* !MEMP_SEPARATE_POOLS */ 00352 /* for every pool: */ 00353 for (i = 0; i < MEMP_MAX; ++i) { 00354 memp_tab[i] = NULL; 00355 #if MEMP_SEPARATE_POOLS 00356 memp = (struct memp*)memp_bases[i]; 00357 #endif /* MEMP_SEPARATE_POOLS */ 00358 /* create a linked list of memp elements */ 00359 for (j = 0; j < memp_num[i]; ++j) { 00360 memp->next = memp_tab[i]; 00361 memp_tab[i] = memp; 00362 memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] 00363 #if MEMP_OVERFLOW_CHECK 00364 + MEMP_SANITY_REGION_AFTER_ALIGNED 00365 #endif 00366 ); 00367 } 00368 } 00369 #if MEMP_OVERFLOW_CHECK 00370 memp_overflow_init(); 00371 /* check everything a first time to see if it worked */ 00372 memp_overflow_check_all(); 00373 #endif /* MEMP_OVERFLOW_CHECK */ 00374 } 00375 00376 /** 00377 * Get an element from a specific pool. 00378 * 00379 * @param type the pool to get an element from 00380 * 00381 * the debug version has two more parameters: 00382 * @param file file name calling this function 00383 * @param line number of line where this function is called 00384 * 00385 * @return a pointer to the allocated memory or a NULL pointer on error 00386 */ 00387 void * 00388 #if !MEMP_OVERFLOW_CHECK 00389 memp_malloc(memp_t type) 00390 #else 00391 memp_malloc_fn(memp_t type, const char* file, const int line) 00392 #endif 00393 { 00394 struct memp *memp; 00395 SYS_ARCH_DECL_PROTECT(old_level); 00396 00397 LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); 00398 00399 SYS_ARCH_PROTECT(old_level); 00400 #if MEMP_OVERFLOW_CHECK >= 2 00401 memp_overflow_check_all(); 00402 #endif /* MEMP_OVERFLOW_CHECK >= 2 */ 00403 00404 memp = memp_tab[type]; 00405 00406 if (memp != NULL) { 00407 memp_tab[type] = memp->next; 00408 #if MEMP_OVERFLOW_CHECK 00409 memp->next = NULL; 00410 memp->file = file; 00411 memp->line = line; 00412 #endif /* MEMP_OVERFLOW_CHECK */ 00413 MEMP_STATS_INC_USED(used, type); 00414 LWIP_ASSERT("memp_malloc: memp properly aligned", 00415 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); 00416 memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); 00417 } else { 00418 LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); 00419 MEMP_STATS_INC(err, type); 00420 } 00421 00422 SYS_ARCH_UNPROTECT(old_level); 00423 00424 return memp; 00425 } 00426 00427 /** 00428 * Put an element back into its pool. 00429 * 00430 * @param type the pool where to put mem 00431 * @param mem the memp element to free 00432 */ 00433 void 00434 memp_free(memp_t type, void *mem) 00435 { 00436 struct memp *memp; 00437 SYS_ARCH_DECL_PROTECT(old_level); 00438 00439 if (mem == NULL) { 00440 return; 00441 } 00442 LWIP_ASSERT("memp_free: mem properly aligned", 00443 ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); 00444 00445 memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); 00446 00447 SYS_ARCH_PROTECT(old_level); 00448 #if MEMP_OVERFLOW_CHECK 00449 #if MEMP_OVERFLOW_CHECK >= 2 00450 memp_overflow_check_all(); 00451 #else 00452 memp_overflow_check_element_overflow(memp, type); 00453 memp_overflow_check_element_underflow(memp, type); 00454 #endif /* MEMP_OVERFLOW_CHECK >= 2 */ 00455 #endif /* MEMP_OVERFLOW_CHECK */ 00456 00457 MEMP_STATS_DEC(used, type); 00458 00459 memp->next = memp_tab[type]; 00460 memp_tab[type] = memp; 00461 00462 #if MEMP_SANITY_CHECK 00463 LWIP_ASSERT("memp sanity", memp_sanity()); 00464 #endif /* MEMP_SANITY_CHECK */ 00465 00466 SYS_ARCH_UNPROTECT(old_level); 00467 } 00468 00469 #endif /* MEMP_MEM_MALLOC */
Generated on Tue Jul 12 2022 15:26:15 by
