00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
00065
00066 struct memp {
00067 struct memp *next;
00068 #if MEMP_OVERFLOW_CHECK
00069 const char *file;
00070 int line;
00071 #endif
00072 };
00073
00074 #if MEMP_OVERFLOW_CHECK
00075
00076
00077
00078
00079
00080
00081
00082
00083 #ifndef MEMP_SANITY_REGION_BEFORE
00084 #define MEMP_SANITY_REGION_BEFORE 16
00085 #endif
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
00091 #ifndef MEMP_SANITY_REGION_AFTER
00092 #define MEMP_SANITY_REGION_AFTER 16
00093 #endif
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
00099
00100
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
00105
00106
00107
00108
00109
00110 #define MEMP_SIZE 0
00111 #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
00112
00113 #endif
00114
00115
00116
00117 static struct memp *memp_tab[MEMP_MAX];
00118
00119 #else
00120
00121 #define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x))
00122
00123 #endif
00124
00125
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
00135
00136
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
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
00149
00150 #if MEMP_SEPARATE_POOLS
00151
00152
00153
00154
00155
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
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
00168
00169
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
00176
00177 #if MEMP_SANITY_CHECK
00178
00179
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
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
00211
00212
00213
00214
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
00244
00245
00246
00247
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
00277
00278
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
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
00331
00332
00333
00334
00335
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
00353
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
00359
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
00373 memp_overflow_check_all();
00374 #endif
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
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
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
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
00430
00431
00432
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
00456 #endif
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
00466
00467 SYS_ARCH_UNPROTECT(old_level);
00468 }
00469
00470 #endif