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