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