Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
memp.c
Go to the documentation of this file.
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 15:37:04 by 1.7.2