Go to the documentation of this file.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
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include "lwip/opt.h"
00057
00058 #if !MEM_LIBC_MALLOC
00059
00060 #include "lwip/def.h"
00061 #include "lwip/mem.h"
00062 #include "lwip/sys.h"
00063 #include "lwip/stats.h"
00064
00065 #include <string.h>
00066
00067 #if MEM_USE_POOLS
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 void *
00078 mem_malloc(mem_size_t size)
00079 {
00080 struct memp_malloc_helper *element;
00081 memp_t poolnr;
00082 mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
00083
00084 for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
00085 #if MEM_USE_POOLS_TRY_BIGGER_POOL
00086 again:
00087 #endif
00088
00089
00090 if (required_size <= memp_sizes[poolnr]) {
00091 break;
00092 }
00093 }
00094 if (poolnr > MEMP_POOL_LAST) {
00095 LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
00096 return NULL;
00097 }
00098 element = (struct memp_malloc_helper*)memp_malloc(poolnr);
00099 if (element == NULL) {
00100
00101
00102 #if MEM_USE_POOLS_TRY_BIGGER_POOL
00103
00104 if (poolnr < MEMP_POOL_LAST) {
00105 poolnr++;
00106 goto again;
00107 }
00108 #endif
00109 return NULL;
00110 }
00111
00112
00113 element->poolnr = poolnr;
00114
00115 element++;
00116
00117 return element;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127 void
00128 mem_free(void *rmem)
00129 {
00130 struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
00131
00132 LWIP_ASSERT("rmem != NULL", (rmem != NULL));
00133 LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
00134
00135
00136 hmem--;
00137
00138 LWIP_ASSERT("hmem != NULL", (hmem != NULL));
00139 LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
00140 LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
00141
00142
00143 memp_free(hmem->poolnr, hmem);
00144 }
00145
00146 #else
00147
00148
00149
00150
00151
00152
00153
00154 struct mem {
00155
00156 mem_size_t next;
00157
00158 mem_size_t prev;
00159
00160 u8_t used;
00161 };
00162
00163
00164
00165
00166 #ifndef MIN_SIZE
00167 #define MIN_SIZE 12
00168 #endif
00169
00170 #define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
00171 #define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
00172 #define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
00173
00174
00175 static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
00176
00177 static u8_t *ram;
00178
00179 static struct mem *ram_end;
00180
00181 static struct mem *lfree;
00182
00183
00184 static sys_sem_t mem_sem;
00185
00186 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00187
00188 static volatile u8_t mem_free_count;
00189
00190
00191 #define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free)
00192 #define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free)
00193 #define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free)
00194 #define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
00195 #define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc)
00196 #define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc)
00197
00198 #else
00199
00200
00201 #define LWIP_MEM_FREE_DECL_PROTECT()
00202 #define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0)
00203 #define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem)
00204
00205 #define LWIP_MEM_ALLOC_DECL_PROTECT()
00206 #define LWIP_MEM_ALLOC_PROTECT()
00207 #define LWIP_MEM_ALLOC_UNPROTECT()
00208
00209 #endif
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 static void
00224 plug_holes(struct mem *mem)
00225 {
00226 struct mem *nmem;
00227 struct mem *pmem;
00228
00229 LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
00230 LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
00231 LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
00232
00233
00234 LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
00235
00236 nmem = (struct mem *)&ram[mem->next];
00237 if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
00238
00239 if (lfree == nmem) {
00240 lfree = mem;
00241 }
00242 mem->next = nmem->next;
00243 ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
00244 }
00245
00246
00247 pmem = (struct mem *)&ram[mem->prev];
00248 if (pmem != mem && pmem->used == 0) {
00249
00250 if (lfree == mem) {
00251 lfree = pmem;
00252 }
00253 pmem->next = mem->next;
00254 ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
00255 }
00256 }
00257
00258
00259
00260
00261 void
00262 mem_init(void)
00263 {
00264 struct mem *mem;
00265
00266 LWIP_ASSERT("Sanity check alignment",
00267 (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
00268
00269
00270 ram = LWIP_MEM_ALIGN(ram_heap);
00271
00272 mem = (struct mem *)ram;
00273 mem->next = MEM_SIZE_ALIGNED;
00274 mem->prev = 0;
00275 mem->used = 0;
00276
00277 ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];
00278 ram_end->used = 1;
00279 ram_end->next = MEM_SIZE_ALIGNED;
00280 ram_end->prev = MEM_SIZE_ALIGNED;
00281
00282 mem_sem = sys_sem_new(1);
00283
00284
00285 lfree = (struct mem *)ram;
00286
00287 MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 void
00297 mem_free(void *rmem)
00298 {
00299 struct mem *mem;
00300 LWIP_MEM_FREE_DECL_PROTECT();
00301
00302 if (rmem == NULL) {
00303 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
00304 return;
00305 }
00306 LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
00307
00308 LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
00309 (u8_t *)rmem < (u8_t *)ram_end);
00310
00311 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
00312 SYS_ARCH_DECL_PROTECT(lev);
00313 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
00314
00315 SYS_ARCH_PROTECT(lev);
00316 MEM_STATS_INC(illegal);
00317 SYS_ARCH_UNPROTECT(lev);
00318 return;
00319 }
00320
00321 LWIP_MEM_FREE_PROTECT();
00322
00323 mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
00324
00325 LWIP_ASSERT("mem_free: mem->used", mem->used);
00326
00327 mem->used = 0;
00328
00329 if (mem < lfree) {
00330
00331 lfree = mem;
00332 }
00333
00334 MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
00335
00336
00337 plug_holes(mem);
00338 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00339 mem_free_count = 1;
00340 #endif
00341 LWIP_MEM_FREE_UNPROTECT();
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 void *
00357 mem_realloc(void *rmem, mem_size_t newsize)
00358 {
00359 mem_size_t size;
00360 mem_size_t ptr, ptr2;
00361 struct mem *mem, *mem2;
00362
00363 LWIP_MEM_FREE_DECL_PROTECT();
00364
00365
00366
00367 newsize = LWIP_MEM_ALIGN_SIZE(newsize);
00368
00369 if(newsize < MIN_SIZE_ALIGNED) {
00370
00371 newsize = MIN_SIZE_ALIGNED;
00372 }
00373
00374 if (newsize > MEM_SIZE_ALIGNED) {
00375 return NULL;
00376 }
00377
00378 LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
00379 (u8_t *)rmem < (u8_t *)ram_end);
00380
00381 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
00382 SYS_ARCH_DECL_PROTECT(lev);
00383 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n"));
00384
00385 SYS_ARCH_PROTECT(lev);
00386 MEM_STATS_INC(illegal);
00387 SYS_ARCH_UNPROTECT(lev);
00388 return rmem;
00389 }
00390
00391 mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
00392
00393 ptr = (u8_t *)mem - ram;
00394
00395 size = mem->next - ptr - SIZEOF_STRUCT_MEM;
00396 LWIP_ASSERT("mem_realloc can only shrink memory", newsize <= size);
00397 if (newsize > size) {
00398
00399 return NULL;
00400 }
00401 if (newsize == size) {
00402
00403 return rmem;
00404 }
00405
00406
00407 LWIP_MEM_FREE_PROTECT();
00408
00409 MEM_STATS_DEC_USED(used, (size - newsize));
00410
00411 mem2 = (struct mem *)&ram[mem->next];
00412 if(mem2->used == 0) {
00413
00414 mem_size_t next;
00415
00416 next = mem2->next;
00417
00418 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
00419 if (lfree == mem2) {
00420 lfree = (struct mem *)&ram[ptr2];
00421 }
00422 mem2 = (struct mem *)&ram[ptr2];
00423 mem2->used = 0;
00424
00425 mem2->next = next;
00426
00427 mem2->prev = ptr;
00428
00429 mem->next = ptr2;
00430
00431
00432
00433 if (mem2->next != MEM_SIZE_ALIGNED) {
00434 ((struct mem *)&ram[mem2->next])->prev = ptr2;
00435 }
00436
00437 } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
00438
00439
00440
00441
00442
00443
00444
00445 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
00446 mem2 = (struct mem *)&ram[ptr2];
00447 if (mem2 < lfree) {
00448 lfree = mem2;
00449 }
00450 mem2->used = 0;
00451 mem2->next = mem->next;
00452 mem2->prev = ptr;
00453 mem->next = ptr2;
00454 if (mem2->next != MEM_SIZE_ALIGNED) {
00455 ((struct mem *)&ram[mem2->next])->prev = ptr2;
00456 }
00457
00458 }
00459
00460
00461
00462
00463
00464
00465 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00466 mem_free_count = 1;
00467 #endif
00468 LWIP_MEM_FREE_UNPROTECT();
00469 return rmem;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 void *
00482 mem_malloc(mem_size_t size)
00483 {
00484 mem_size_t ptr, ptr2;
00485 struct mem *mem, *mem2;
00486 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00487 u8_t local_mem_free_count = 0;
00488 #endif
00489 LWIP_MEM_ALLOC_DECL_PROTECT();
00490
00491 if (size == 0) {
00492 return NULL;
00493 }
00494
00495
00496
00497 size = LWIP_MEM_ALIGN_SIZE(size);
00498
00499 if(size < MIN_SIZE_ALIGNED) {
00500
00501 size = MIN_SIZE_ALIGNED;
00502 }
00503
00504 if (size > MEM_SIZE_ALIGNED) {
00505 return NULL;
00506 }
00507
00508
00509 sys_arch_sem_wait(mem_sem, 0);
00510 LWIP_MEM_ALLOC_PROTECT();
00511 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00512
00513 do {
00514 local_mem_free_count = 0;
00515 #endif
00516
00517
00518
00519
00520 for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
00521 ptr = ((struct mem *)&ram[ptr])->next) {
00522 mem = (struct mem *)&ram[ptr];
00523 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00524 mem_free_count = 0;
00525 LWIP_MEM_ALLOC_UNPROTECT();
00526
00527 LWIP_MEM_ALLOC_PROTECT();
00528 if (mem_free_count != 0) {
00529 local_mem_free_count = mem_free_count;
00530 }
00531 mem_free_count = 0;
00532 #endif
00533
00534 if ((!mem->used) &&
00535 (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
00536
00537
00538
00539 if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
00551
00552 mem2 = (struct mem *)&ram[ptr2];
00553 mem2->used = 0;
00554 mem2->next = mem->next;
00555 mem2->prev = ptr;
00556
00557 mem->next = ptr2;
00558 mem->used = 1;
00559
00560 if (mem2->next != MEM_SIZE_ALIGNED) {
00561 ((struct mem *)&ram[mem2->next])->prev = ptr2;
00562 }
00563 MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
00564 } else {
00565
00566
00567
00568
00569
00570
00571
00572 mem->used = 1;
00573 MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
00574 }
00575
00576 if (mem == lfree) {
00577
00578 while (lfree->used && lfree != ram_end) {
00579 LWIP_MEM_ALLOC_UNPROTECT();
00580
00581 LWIP_MEM_ALLOC_PROTECT();
00582 lfree = (struct mem *)&ram[lfree->next];
00583 }
00584 LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
00585 }
00586 LWIP_MEM_ALLOC_UNPROTECT();
00587 sys_sem_signal(mem_sem);
00588 LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
00589 (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
00590 LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
00591 ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
00592 LWIP_ASSERT("mem_malloc: sanity check alignment",
00593 (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
00594
00595 return (u8_t *)mem + SIZEOF_STRUCT_MEM;
00596 }
00597 }
00598 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
00599
00600 } while(local_mem_free_count != 0);
00601 #endif
00602 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
00603 MEM_STATS_INC(err);
00604 LWIP_MEM_ALLOC_UNPROTECT();
00605 sys_sem_signal(mem_sem);
00606 return NULL;
00607 }
00608
00609 #endif
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 void *mem_calloc(mem_size_t count, mem_size_t size)
00621 {
00622 void *p;
00623
00624
00625 p = mem_malloc(count * size);
00626 if (p) {
00627
00628 memset(p, 0, count * size);
00629 }
00630 return p;
00631 }
00632
00633 #endif