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