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 lwip by
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 #if defined(TARGET_LPC1768) 00170 # define ETHMEM_SECTION __attribute((section("AHBSRAM1"))) 00171 #else 00172 # define ETHMEM_SECTION 00173 #endif 00174 00175 /** This is the actual memory used by the pools (all pools in one big block). */ 00176 static u8_t memp_memory[MEM_ALIGNMENT - 1 00177 #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) 00178 #include "lwip/memp_std.h" 00179 ] ETHMEM_SECTION; 00180 00181 #endif /* MEMP_SEPARATE_POOLS */ 00182 00183 #if MEMP_SANITY_CHECK 00184 /** 00185 * Check that memp-lists don't form a circle 00186 */ 00187 static int 00188 memp_sanity(void) 00189 { 00190 s16_t i, c; 00191 struct memp *m, *n; 00192 00193 for (i = 0; i < MEMP_MAX; i++) { 00194 for (m = memp_tab[i]; m != NULL; m = m->next) { 00195 c = 1; 00196 for (n = memp_tab[i]; n != NULL; n = n->next) { 00197 if (n == m && --c < 0) { 00198 return 0; 00199 } 00200 } 00201 } 00202 } 00203 return 1; 00204 } 00205 #endif /* MEMP_SANITY_CHECK*/ 00206 #if MEMP_OVERFLOW_CHECK 00207 #if defined(LWIP_DEBUG) && MEMP_STATS 00208 static const char * memp_overflow_names[] = { 00209 #define LWIP_MEMPOOL(name,num,size,desc) "/"desc, 00210 #include "lwip/memp_std.h" 00211 }; 00212 #endif 00213 00214 /** 00215 * Check if a memp element was victim of an overflow 00216 * (e.g. the restricted area after it has been altered) 00217 * 00218 * @param p the memp element to check 00219 * @param memp_type the pool p comes from 00220 */ 00221 static void 00222 memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) 00223 { 00224 u16_t k; 00225 u8_t *m; 00226 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 00227 m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; 00228 for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { 00229 if (m[k] != 0xcd) { 00230 char errstr[128] = "detected memp overflow in pool "; 00231 char digit[] = "0"; 00232 if(memp_type >= 10) { 00233 digit[0] = '0' + (memp_type/10); 00234 strcat(errstr, digit); 00235 } 00236 digit[0] = '0' + (memp_type%10); 00237 strcat(errstr, digit); 00238 #if defined(LWIP_DEBUG) && MEMP_STATS 00239 strcat(errstr, memp_overflow_names[memp_type]); 00240 #endif 00241 LWIP_ASSERT(errstr, 0); 00242 } 00243 } 00244 #endif 00245 } 00246 00247 /** 00248 * Check if a memp element was victim of an underflow 00249 * (e.g. the restricted area before it has been altered) 00250 * 00251 * @param p the memp element to check 00252 * @param memp_type the pool p comes from 00253 */ 00254 static void 00255 memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) 00256 { 00257 u16_t k; 00258 u8_t *m; 00259 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 00260 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; 00261 for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { 00262 if (m[k] != 0xcd) { 00263 char errstr[128] = "detected memp underflow in pool "; 00264 char digit[] = "0"; 00265 if(memp_type >= 10) { 00266 digit[0] = '0' + (memp_type/10); 00267 strcat(errstr, digit); 00268 } 00269 digit[0] = '0' + (memp_type%10); 00270 strcat(errstr, digit); 00271 #if defined(LWIP_DEBUG) && MEMP_STATS 00272 strcat(errstr, memp_overflow_names[memp_type]); 00273 #endif 00274 LWIP_ASSERT(errstr, 0); 00275 } 00276 } 00277 #endif 00278 } 00279 00280 /** 00281 * Do an overflow check for all elements in every pool. 00282 * 00283 * @see memp_overflow_check_element for a description of the check 00284 */ 00285 static void 00286 memp_overflow_check_all(void) 00287 { 00288 u16_t i, j; 00289 struct memp *p; 00290 00291 p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00292 for (i = 0; i < MEMP_MAX; ++i) { 00293 p = p; 00294 for (j = 0; j < memp_num[i]; ++j) { 00295 memp_overflow_check_element_overflow(p, i); 00296 p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); 00297 } 00298 } 00299 p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00300 for (i = 0; i < MEMP_MAX; ++i) { 00301 p = p; 00302 for (j = 0; j < memp_num[i]; ++j) { 00303 memp_overflow_check_element_underflow(p, i); 00304 p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); 00305 } 00306 } 00307 } 00308 00309 /** 00310 * Initialize the restricted areas of all memp elements in every pool. 00311 */ 00312 static void 00313 memp_overflow_init(void) 00314 { 00315 u16_t i, j; 00316 struct memp *p; 00317 u8_t *m; 00318 00319 p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00320 for (i = 0; i < MEMP_MAX; ++i) { 00321 p = p; 00322 for (j = 0; j < memp_num[i]; ++j) { 00323 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 00324 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; 00325 memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); 00326 #endif 00327 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 00328 m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; 00329 memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); 00330 #endif 00331 p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); 00332 } 00333 } 00334 } 00335 #endif /* MEMP_OVERFLOW_CHECK */ 00336 00337 /** 00338 * Initialize this module. 00339 * 00340 * Carves out memp_memory into linked lists for each pool-type. 00341 */ 00342 void 00343 memp_init(void) 00344 { 00345 struct memp *memp; 00346 u16_t i, j; 00347 00348 for (i = 0; i < MEMP_MAX; ++i) { 00349 MEMP_STATS_AVAIL(used, i, 0); 00350 MEMP_STATS_AVAIL(max, i, 0); 00351 MEMP_STATS_AVAIL(err, i, 0); 00352 MEMP_STATS_AVAIL(avail, i, memp_num[i]); 00353 } 00354 00355 #if !MEMP_SEPARATE_POOLS 00356 memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); 00357 #endif /* !MEMP_SEPARATE_POOLS */ 00358 /* for every pool: */ 00359 for (i = 0; i < MEMP_MAX; ++i) { 00360 memp_tab[i] = NULL; 00361 #if MEMP_SEPARATE_POOLS 00362 memp = (struct memp*)memp_bases[i]; 00363 #endif /* MEMP_SEPARATE_POOLS */ 00364 /* create a linked list of memp elements */ 00365 for (j = 0; j < memp_num[i]; ++j) { 00366 memp->next = memp_tab[i]; 00367 memp_tab[i] = memp; 00368 memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] 00369 #if MEMP_OVERFLOW_CHECK 00370 + MEMP_SANITY_REGION_AFTER_ALIGNED 00371 #endif 00372 ); 00373 } 00374 } 00375 #if MEMP_OVERFLOW_CHECK 00376 memp_overflow_init(); 00377 /* check everything a first time to see if it worked */ 00378 memp_overflow_check_all(); 00379 #endif /* MEMP_OVERFLOW_CHECK */ 00380 } 00381 00382 /** 00383 * Get an element from a specific pool. 00384 * 00385 * @param type the pool to get an element from 00386 * 00387 * the debug version has two more parameters: 00388 * @param file file name calling this function 00389 * @param line number of line where this function is called 00390 * 00391 * @return a pointer to the allocated memory or a NULL pointer on error 00392 */ 00393 void * 00394 #if !MEMP_OVERFLOW_CHECK 00395 memp_malloc(memp_t type) 00396 #else 00397 memp_malloc_fn(memp_t type, const char* file, const int line) 00398 #endif 00399 { 00400 struct memp *memp; 00401 SYS_ARCH_DECL_PROTECT(old_level); 00402 00403 LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); 00404 00405 SYS_ARCH_PROTECT(old_level); 00406 #if MEMP_OVERFLOW_CHECK >= 2 00407 memp_overflow_check_all(); 00408 #endif /* MEMP_OVERFLOW_CHECK >= 2 */ 00409 00410 memp = memp_tab[type]; 00411 00412 if (memp != NULL) { 00413 memp_tab[type] = memp->next; 00414 #if MEMP_OVERFLOW_CHECK 00415 memp->next = NULL; 00416 memp->file = file; 00417 memp->line = line; 00418 #endif /* MEMP_OVERFLOW_CHECK */ 00419 MEMP_STATS_INC_USED(used, type); 00420 LWIP_ASSERT("memp_malloc: memp properly aligned", 00421 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); 00422 memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); 00423 } else { 00424 LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); 00425 MEMP_STATS_INC(err, type); 00426 } 00427 00428 SYS_ARCH_UNPROTECT(old_level); 00429 00430 return memp; 00431 } 00432 00433 /** 00434 * Put an element back into its pool. 00435 * 00436 * @param type the pool where to put mem 00437 * @param mem the memp element to free 00438 */ 00439 void 00440 memp_free(memp_t type, void *mem) 00441 { 00442 struct memp *memp; 00443 SYS_ARCH_DECL_PROTECT(old_level); 00444 00445 if (mem == NULL) { 00446 return; 00447 } 00448 LWIP_ASSERT("memp_free: mem properly aligned", 00449 ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); 00450 00451 memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); 00452 00453 SYS_ARCH_PROTECT(old_level); 00454 #if MEMP_OVERFLOW_CHECK 00455 #if MEMP_OVERFLOW_CHECK >= 2 00456 memp_overflow_check_all(); 00457 #else 00458 memp_overflow_check_element_overflow(memp, type); 00459 memp_overflow_check_element_underflow(memp, type); 00460 #endif /* MEMP_OVERFLOW_CHECK >= 2 */ 00461 #endif /* MEMP_OVERFLOW_CHECK */ 00462 00463 MEMP_STATS_DEC(used, type); 00464 00465 memp->next = memp_tab[type]; 00466 memp_tab[type] = memp; 00467 00468 #if MEMP_SANITY_CHECK 00469 LWIP_ASSERT("memp sanity", memp_sanity()); 00470 #endif /* MEMP_SANITY_CHECK */ 00471 00472 SYS_ARCH_UNPROTECT(old_level); 00473 } 00474 00475 #endif /* MEMP_MEM_MALLOC */
Generated on Tue Jul 12 2022 13:44:41 by
