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