Warning, cross-references for /kernel/lwip/core/mem.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 #include "lwip/opt.h"
0057
0058 #if !MEM_LIBC_MALLOC
0059
0060 #include "lwip/def.h"
0061 #include "lwip/mem.h"
0062 #include "lwip/sys.h"
0063 #include "lwip/stats.h"
0064
0065 #include <string.h>
0066
0067 #if MEM_USE_POOLS
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 void *
0078 mem_malloc(mem_size_t size)
0079 {
0080 struct memp_malloc_helper *element;
0081 memp_t poolnr;
0082 mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
0083
0084 for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
0085 #if MEM_USE_POOLS_TRY_BIGGER_POOL
0086 again:
0087 #endif
0088
0089
0090 if (required_size <= memp_sizes[poolnr]) {
0091 break;
0092 }
0093 }
0094 if (poolnr > MEMP_POOL_LAST) {
0095 LWIP_ASSERT("mem_malloc(): no pool is that big!", 0);
0096 return NULL;
0097 }
0098 element = (struct memp_malloc_helper*)memp_malloc(poolnr);
0099 if (element == NULL) {
0100
0101
0102 #if MEM_USE_POOLS_TRY_BIGGER_POOL
0103
0104 if (poolnr < MEMP_POOL_LAST) {
0105 poolnr++;
0106 goto again;
0107 }
0108 #endif
0109 return NULL;
0110 }
0111
0112
0113 element->poolnr = poolnr;
0114
0115 element++;
0116
0117 return element;
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127 void
0128 mem_free(void *rmem)
0129 {
0130 struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
0131
0132 LWIP_ASSERT("rmem != NULL", (rmem != NULL));
0133 LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
0134
0135
0136 hmem--;
0137
0138 LWIP_ASSERT("hmem != NULL", (hmem != NULL));
0139 LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
0140 LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX));
0141
0142
0143 memp_free(hmem->poolnr, hmem);
0144 }
0145
0146 #else
0147
0148
0149
0150
0151
0152
0153
0154 struct mem {
0155
0156 mem_size_t next;
0157
0158 mem_size_t prev;
0159
0160 u8_t used;
0161 };
0162
0163
0164
0165
0166 #ifndef MIN_SIZE
0167 #define MIN_SIZE 12
0168 #endif
0169
0170 #define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE)
0171 #define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
0172 #define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
0173
0174
0175 static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
0176
0177 static u8_t *ram;
0178
0179 static struct mem *ram_end;
0180
0181 static struct mem *lfree;
0182
0183
0184 static sys_sem_t mem_sem;
0185
0186 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0187
0188 static volatile u8_t mem_free_count;
0189
0190
0191 #define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free)
0192 #define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free)
0193 #define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free)
0194 #define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc)
0195 #define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc)
0196 #define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc)
0197
0198 #else
0199
0200
0201 #define LWIP_MEM_FREE_DECL_PROTECT()
0202 #define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0)
0203 #define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem)
0204
0205 #define LWIP_MEM_ALLOC_DECL_PROTECT()
0206 #define LWIP_MEM_ALLOC_PROTECT()
0207 #define LWIP_MEM_ALLOC_UNPROTECT()
0208
0209 #endif
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 static void
0224 plug_holes(struct mem *mem)
0225 {
0226 struct mem *nmem;
0227 struct mem *pmem;
0228
0229 LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
0230 LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
0231 LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
0232
0233
0234 LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
0235
0236 nmem = (struct mem *)&ram[mem->next];
0237 if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
0238
0239 if (lfree == nmem) {
0240 lfree = mem;
0241 }
0242 mem->next = nmem->next;
0243 ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
0244 }
0245
0246
0247 pmem = (struct mem *)&ram[mem->prev];
0248 if (pmem != mem && pmem->used == 0) {
0249
0250 if (lfree == mem) {
0251 lfree = pmem;
0252 }
0253 pmem->next = mem->next;
0254 ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
0255 }
0256 }
0257
0258
0259
0260
0261 void
0262 mem_init(void)
0263 {
0264 struct mem *mem;
0265
0266 LWIP_ASSERT("Sanity check alignment",
0267 (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
0268
0269
0270 ram = LWIP_MEM_ALIGN(ram_heap);
0271
0272 mem = (struct mem *)ram;
0273 mem->next = MEM_SIZE_ALIGNED;
0274 mem->prev = 0;
0275 mem->used = 0;
0276
0277 ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];
0278 ram_end->used = 1;
0279 ram_end->next = MEM_SIZE_ALIGNED;
0280 ram_end->prev = MEM_SIZE_ALIGNED;
0281
0282 mem_sem = sys_sem_new(1);
0283
0284
0285 lfree = (struct mem *)ram;
0286
0287 MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
0288 }
0289
0290
0291
0292
0293
0294
0295
0296 void
0297 mem_free(void *rmem)
0298 {
0299 struct mem *mem;
0300 LWIP_MEM_FREE_DECL_PROTECT();
0301
0302 if (rmem == NULL) {
0303 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
0304 return;
0305 }
0306 LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);
0307
0308 LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
0309 (u8_t *)rmem < (u8_t *)ram_end);
0310
0311 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
0312 SYS_ARCH_DECL_PROTECT(lev);
0313 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
0314
0315 SYS_ARCH_PROTECT(lev);
0316 MEM_STATS_INC(illegal);
0317 SYS_ARCH_UNPROTECT(lev);
0318 return;
0319 }
0320
0321 LWIP_MEM_FREE_PROTECT();
0322
0323 mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
0324
0325 LWIP_ASSERT("mem_free: mem->used", mem->used);
0326
0327 mem->used = 0;
0328
0329 if (mem < lfree) {
0330
0331 lfree = mem;
0332 }
0333
0334 MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
0335
0336
0337 plug_holes(mem);
0338 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0339 mem_free_count = 1;
0340 #endif
0341 LWIP_MEM_FREE_UNPROTECT();
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 void *
0357 mem_realloc(void *rmem, mem_size_t newsize)
0358 {
0359 mem_size_t size;
0360 mem_size_t ptr, ptr2;
0361 struct mem *mem, *mem2;
0362
0363 LWIP_MEM_FREE_DECL_PROTECT();
0364
0365
0366
0367 newsize = LWIP_MEM_ALIGN_SIZE(newsize);
0368
0369 if(newsize < MIN_SIZE_ALIGNED) {
0370
0371 newsize = MIN_SIZE_ALIGNED;
0372 }
0373
0374 if (newsize > MEM_SIZE_ALIGNED) {
0375 return NULL;
0376 }
0377
0378 LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
0379 (u8_t *)rmem < (u8_t *)ram_end);
0380
0381 if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
0382 SYS_ARCH_DECL_PROTECT(lev);
0383 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n"));
0384
0385 SYS_ARCH_PROTECT(lev);
0386 MEM_STATS_INC(illegal);
0387 SYS_ARCH_UNPROTECT(lev);
0388 return rmem;
0389 }
0390
0391 mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
0392
0393 ptr = (u8_t *)mem - ram;
0394
0395 size = mem->next - ptr - SIZEOF_STRUCT_MEM;
0396 LWIP_ASSERT("mem_realloc can only shrink memory", newsize <= size);
0397 if (newsize > size) {
0398
0399 return NULL;
0400 }
0401 if (newsize == size) {
0402
0403 return rmem;
0404 }
0405
0406
0407 LWIP_MEM_FREE_PROTECT();
0408
0409 MEM_STATS_DEC_USED(used, (size - newsize));
0410
0411 mem2 = (struct mem *)&ram[mem->next];
0412 if(mem2->used == 0) {
0413
0414 mem_size_t next;
0415
0416 next = mem2->next;
0417
0418 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
0419 if (lfree == mem2) {
0420 lfree = (struct mem *)&ram[ptr2];
0421 }
0422 mem2 = (struct mem *)&ram[ptr2];
0423 mem2->used = 0;
0424
0425 mem2->next = next;
0426
0427 mem2->prev = ptr;
0428
0429 mem->next = ptr2;
0430
0431
0432
0433 if (mem2->next != MEM_SIZE_ALIGNED) {
0434 ((struct mem *)&ram[mem2->next])->prev = ptr2;
0435 }
0436
0437 } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
0438
0439
0440
0441
0442
0443
0444
0445 ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
0446 mem2 = (struct mem *)&ram[ptr2];
0447 if (mem2 < lfree) {
0448 lfree = mem2;
0449 }
0450 mem2->used = 0;
0451 mem2->next = mem->next;
0452 mem2->prev = ptr;
0453 mem->next = ptr2;
0454 if (mem2->next != MEM_SIZE_ALIGNED) {
0455 ((struct mem *)&ram[mem2->next])->prev = ptr2;
0456 }
0457
0458 }
0459
0460
0461
0462
0463
0464
0465 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0466 mem_free_count = 1;
0467 #endif
0468 LWIP_MEM_FREE_UNPROTECT();
0469 return rmem;
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481 void *
0482 mem_malloc(mem_size_t size)
0483 {
0484 mem_size_t ptr, ptr2;
0485 struct mem *mem, *mem2;
0486 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0487 u8_t local_mem_free_count = 0;
0488 #endif
0489 LWIP_MEM_ALLOC_DECL_PROTECT();
0490
0491 if (size == 0) {
0492 return NULL;
0493 }
0494
0495
0496
0497 size = LWIP_MEM_ALIGN_SIZE(size);
0498
0499 if(size < MIN_SIZE_ALIGNED) {
0500
0501 size = MIN_SIZE_ALIGNED;
0502 }
0503
0504 if (size > MEM_SIZE_ALIGNED) {
0505 return NULL;
0506 }
0507
0508
0509 sys_arch_sem_wait(mem_sem, 0);
0510 LWIP_MEM_ALLOC_PROTECT();
0511 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0512
0513 do {
0514 local_mem_free_count = 0;
0515 #endif
0516
0517
0518
0519
0520 for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
0521 ptr = ((struct mem *)&ram[ptr])->next) {
0522 mem = (struct mem *)&ram[ptr];
0523 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0524 mem_free_count = 0;
0525 LWIP_MEM_ALLOC_UNPROTECT();
0526
0527 LWIP_MEM_ALLOC_PROTECT();
0528 if (mem_free_count != 0) {
0529 local_mem_free_count = mem_free_count;
0530 }
0531 mem_free_count = 0;
0532 #endif
0533
0534 if ((!mem->used) &&
0535 (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {
0536
0537
0538
0539 if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550 ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
0551
0552 mem2 = (struct mem *)&ram[ptr2];
0553 mem2->used = 0;
0554 mem2->next = mem->next;
0555 mem2->prev = ptr;
0556
0557 mem->next = ptr2;
0558 mem->used = 1;
0559
0560 if (mem2->next != MEM_SIZE_ALIGNED) {
0561 ((struct mem *)&ram[mem2->next])->prev = ptr2;
0562 }
0563 MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
0564 } else {
0565
0566
0567
0568
0569
0570
0571
0572 mem->used = 1;
0573 MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
0574 }
0575
0576 if (mem == lfree) {
0577
0578 while (lfree->used && lfree != ram_end) {
0579 LWIP_MEM_ALLOC_UNPROTECT();
0580
0581 LWIP_MEM_ALLOC_PROTECT();
0582 lfree = (struct mem *)&ram[lfree->next];
0583 }
0584 LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
0585 }
0586 LWIP_MEM_ALLOC_UNPROTECT();
0587 sys_sem_signal(mem_sem);
0588 LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
0589 (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
0590 LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
0591 ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
0592 LWIP_ASSERT("mem_malloc: sanity check alignment",
0593 (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
0594
0595 return (u8_t *)mem + SIZEOF_STRUCT_MEM;
0596 }
0597 }
0598 #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
0599
0600 } while(local_mem_free_count != 0);
0601 #endif
0602 LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
0603 MEM_STATS_INC(err);
0604 LWIP_MEM_ALLOC_UNPROTECT();
0605 sys_sem_signal(mem_sem);
0606 return NULL;
0607 }
0608
0609 #endif
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620 void *mem_calloc(mem_size_t count, mem_size_t size)
0621 {
0622 void *p;
0623
0624
0625 p = mem_malloc(count * size);
0626 if (p) {
0627
0628 memset(p, 0, count * size);
0629 }
0630 return p;
0631 }
0632
0633 #endif