1 /**
2 * @file
3 * Dynamic pool memory manager
4 *
5 * lwIP has dedicated pools for many structures (netconn, protocol control blocks,
6 * packet buffers, ...). All these pools are managed here.
7 *
8 * @defgroup mempool Memory pools
9 * @ingroup infrastructure
10 * Custom memory pools
11
12 */
13
14 /*
15 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without modification,
19 * are permitted provided that the following conditions are met:
20 *
21 * 1. Redistributions of source code must retain the above copyright notice,
22 * this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright notice,
24 * this list of conditions and the following disclaimer in the documentation
25 * and/or other materials provided with the distribution.
26 * 3. The name of the author may not be used to endorse or promote products
27 * derived from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
32 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
34 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
38 * OF SUCH DAMAGE.
39 *
40 * This file is part of the lwIP TCP/IP stack.
41 *
42 * Author: Adam Dunkels <adam@sics.se>
43 *
44 */
45
46 #include "lwip/opt.h"
47
48 #include "lwip/memp.h"
49 #include "lwip/sys.h"
50 #include "lwip/stats.h"
51
52 #include <string.h>
53
54 /* Make sure we include everything we need for size calculation required by memp_std.h */
55 #include "lwip/pbuf.h"
56 #include "lwip/raw.h"
57 #include "lwip/udp.h"
58 #include "lwip/tcp.h"
59 #include "lwip/priv/tcp_priv.h"
60 #include "lwip/ip4_frag.h"
61 #include "lwip/netbuf.h"
62 #include "lwip/api.h"
63 #include "lwip/priv/tcpip_priv.h"
64 #include "lwip/priv/api_msg.h"
65 #include "lwip/priv/sockets_priv.h"
66 #include "lwip/etharp.h"
67 #include "lwip/igmp.h"
68 #include "lwip/timeouts.h"
69 /* needed by default MEMP_NUM_SYS_TIMEOUT */
70 #include "lwip/netdb.h"
71 #include "lwip/dns.h"
72 #include "lwip/priv/nd6_priv.h"
73 #include "lwip/ip6_frag.h"
74 #include "lwip/mld6.h"
75
76 #if LWIP_ALLOW_SOCKET_CONFIG
77 struct memp_desc *memp_pools[MEMP_MAX] = {0};
78 #else
79 #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
80 #include "lwip/priv/memp_std.h"
81
82 const struct memp_desc *const memp_pools[MEMP_MAX] = {
83 #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
84 #include "lwip/priv/memp_std.h"
85 };
86 #endif
87
88 #ifdef LWIP_HOOK_FILENAME
89 #include LWIP_HOOK_FILENAME
90 #endif
91
92 #if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2
93 #undef MEMP_OVERFLOW_CHECK
94 /* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */
95 #define MEMP_OVERFLOW_CHECK 1
96 #endif
97
98 #if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC
99 /**
100 * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
101 */
102 static int
memp_sanity(const struct memp_desc * desc)103 memp_sanity(const struct memp_desc *desc)
104 {
105 struct memp *t, *h;
106
107 t = *desc->tab;
108 if (t != NULL) {
109 for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
110 h = ((h->next != NULL) ? h->next->next : NULL)) {
111 if (t == h) {
112 return 0;
113 }
114 }
115 }
116
117 return 1;
118 }
119 #endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */
120
121 #if MEMP_OVERFLOW_CHECK
122 /**
123 * Check if a memp element was victim of an overflow or underflow
124 * (e.g. the restricted area after/before it has been altered)
125 *
126 * @param p the memp element to check
127 * @param desc the pool p comes from
128 */
129 static void
memp_overflow_check_element(struct memp * p,const struct memp_desc * desc)130 memp_overflow_check_element(struct memp *p, const struct memp_desc *desc)
131 {
132 mem_overflow_check_raw((u8_t *)p + MEMP_SIZE, desc->size, "pool ", desc->desc);
133 }
134
135 /**
136 * Initialize the restricted area of on memp element.
137 */
138 static void
memp_overflow_init_element(struct memp * p,const struct memp_desc * desc)139 memp_overflow_init_element(struct memp *p, const struct memp_desc *desc)
140 {
141 mem_overflow_init_raw((u8_t *)p + MEMP_SIZE, desc->size);
142 }
143
144 #if MEMP_OVERFLOW_CHECK >= 2
145 /**
146 * Do an overflow check for all elements in every pool.
147 *
148 * @see memp_overflow_check_element for a description of the check
149 */
150 static void
memp_overflow_check_all(void)151 memp_overflow_check_all(void)
152 {
153 u16_t i, j;
154 struct memp *p;
155 SYS_ARCH_DECL_PROTECT(old_level);
156 SYS_ARCH_PROTECT(old_level);
157
158 for (i = 0; i < MEMP_MAX; ++i) {
159 p = (struct memp *)LWIP_MEM_ALIGN(memp_pools[i]->base);
160 for (j = 0; j < memp_pools[i]->num; ++j) {
161 memp_overflow_check_element(p, memp_pools[i]);
162 p = LWIP_ALIGNMENT_CAST(struct memp *, ((u8_t *)p + MEMP_SIZE + memp_pools[i]->size + MEM_SANITY_REGION_AFTER_ALIGNED));
163 }
164 }
165 SYS_ARCH_UNPROTECT(old_level);
166 }
167 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
168 #endif /* MEMP_OVERFLOW_CHECK */
169
170 #if LWIP_ALLOW_SOCKET_CONFIG
171 /**
172 * Initialize custom memory pool.
173 * Related functions: memp_malloc_pool, memp_free_pool
174 *
175 * @param desc pool to initialize
176 */
177 void
memp_init_pool(const char * szdesc,u32_t num,u16_t size,u8_t type)178 memp_init_pool(const char *szdesc, u32_t num, u16_t size, u8_t type)
179 {
180 #if MEMP_MEM_MALLOC
181 LWIP_UNUSED_ARG(szdesc);
182 LWIP_UNUSED_ARG(num);
183 LWIP_UNUSED_ARG(size);
184 LWIP_UNUSED_ARG(type);
185 #else
186 u32_t i;
187 struct memp *memp = NULL;
188 struct memp_desc *desc = NULL;
189 u32_t pool_size = ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)));
190 desc = mem_malloc(sizeof(struct memp_desc));
191 if (desc == NULL) {
192 return;
193 }
194 (void)memset_s(desc, sizeof(struct memp_desc), 0, sizeof(struct memp_desc));
195 desc->base = mem_malloc(pool_size);
196 if (desc->base == NULL) {
197 mem_free(desc);
198 return;
199 }
200 #if MEMP_STATS
201 desc->stats = mem_malloc(sizeof(struct stats_mem));
202 if (desc->stats == NULL) {
203 mem_free(desc->base);
204 mem_free(desc);
205 return;
206 }
207 (void)memset(desc->stats, 0, sizeof(struct stats_mem));
208 #if LWIP_STATS
209 lwip_stats.memp[type] = desc->stats;
210 desc->stats->max = num;
211 #endif /* LWIP_STATS */
212 #endif /* MEMP_STATS */
213 (void)memset_s(desc->base, pool_size, 0, pool_size);
214 memp_pools[type] = desc;
215 desc->desc = szdesc;
216 desc->size = (u16_t)LWIP_MEM_ALIGN_SIZE((u32_t)size);
217 desc->num = (u16_t)num;
218 desc->tab = &desc->tab_tail;
219 *desc->tab = NULL;
220
221 memp = (struct memp*)(desc->base);
222 /* create a linked list of memp elements */
223 for (i = 0; i < desc->num; ++i) {
224 memp->next = *desc->tab;
225 *desc->tab = memp;
226 #if MEMP_OVERFLOW_CHECK
227 memp_overflow_init_element(memp, desc);
228 #endif /* MEMP_OVERFLOW_CHECK */
229 /* cast through void* to get rid of alignment warnings */
230 memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
231 #if MEMP_OVERFLOW_CHECK
232 + MEM_SANITY_REGION_AFTER_ALIGNED
233 #endif /* MEMP_OVERFLOW_CHECK */
234 );
235 }
236 #if MEMP_STATS
237 desc->stats->avail = desc->num;
238 #endif /* MEMP_STATS */
239 #endif /* MEMP_MEM_MALLOC */
240
241 #if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
242 desc->stats->name = desc->desc;
243 #endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
244 }
245
246 unsigned int g_lwip_num_sockets = DEFAULT_LWIP_NUM_SOCKETS;
lwip_set_socket_num(unsigned int socketnum)247 int lwip_set_socket_num(unsigned int socketnum)
248 {
249 extern volatile int tcpip_init_finish;
250 SYS_ARCH_DECL_PROTECT(old_level);
251 if (tcpip_init_finish) {
252 return -1;
253 }
254 if ((socketnum == 0) || (socketnum > LWIP_NUM_SOCKETS_MAX)) {
255 return -1;
256 }
257 SYS_ARCH_PROTECT(old_level);
258 g_lwip_num_sockets = socketnum;
259 SYS_ARCH_UNPROTECT(old_level);
260 return 0;
261 }
262
lwip_get_socket_num(void)263 unsigned int lwip_get_socket_num(void)
264 {
265 unsigned int ret;
266 SYS_ARCH_DECL_PROTECT(old_level);
267 SYS_ARCH_PROTECT(old_level);
268 ret = g_lwip_num_sockets;
269 SYS_ARCH_UNPROTECT(old_level);
270 return ret;
271 }
272 #else
273 /**
274 * Initialize custom memory pool.
275 * Related functions: memp_malloc_pool, memp_free_pool
276 *
277 * @param desc pool to initialize
278 */
279 void
memp_init_pool(const struct memp_desc * desc)280 memp_init_pool(const struct memp_desc *desc)
281 {
282 #if MEMP_MEM_MALLOC
283 LWIP_UNUSED_ARG(desc);
284 #else
285 int i;
286 struct memp *memp;
287
288 *desc->tab = NULL;
289 memp = (struct memp *)LWIP_MEM_ALIGN(desc->base);
290 #if MEMP_MEM_INIT
291 /* force memset on pool memory */
292 memset(memp, 0, (size_t)desc->num * (MEMP_SIZE + desc->size
293 #if MEMP_OVERFLOW_CHECK
294 + MEM_SANITY_REGION_AFTER_ALIGNED
295 #endif
296 ));
297 #endif
298 /* create a linked list of memp elements */
299 for (i = 0; i < desc->num; ++i) {
300 memp->next = *desc->tab;
301 *desc->tab = memp;
302 #if MEMP_OVERFLOW_CHECK
303 memp_overflow_init_element(memp, desc);
304 #endif /* MEMP_OVERFLOW_CHECK */
305 /* cast through void* to get rid of alignment warnings */
306 memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
307 #if MEMP_OVERFLOW_CHECK
308 + MEM_SANITY_REGION_AFTER_ALIGNED
309 #endif
310 );
311 }
312 #if MEMP_STATS
313 desc->stats->avail = desc->num;
314 #endif /* MEMP_STATS */
315 #endif /* !MEMP_MEM_MALLOC */
316
317 #if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
318 desc->stats->name = desc->desc;
319 #endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
320 }
321 #endif
322
323 /**
324 * Initializes lwIP built-in pools.
325 * Related functions: memp_malloc, memp_free
326 *
327 * Carves out memp_memory into linked lists for each pool-type.
328 */
329 void
memp_init(void)330 memp_init(void)
331 {
332 u16_t i = 0;
333 #if LWIP_ALLOW_SOCKET_CONFIG
334 static u8_t memp_init_flag = 0;
335
336 if (memp_init_flag == 1) {
337 return;
338 }
339
340 #define LWIP_MEMPOOL(name, num, size, desc) memp_init_pool(desc, num, (u16_t)size, (u8_t)i++);
341 #include "lwip/priv/memp_std.h"
342
343 memp_init_flag = 1;
344 #else /* LWIP_ALLOW_SOCKET_CONFIG */
345 /* for every pool: */
346 for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
347 memp_init_pool(memp_pools[i]);
348
349 #if LWIP_STATS && MEMP_STATS
350 lwip_stats.memp[i] = memp_pools[i]->stats;
351 #endif
352 }
353 #endif /* LWIP_ALLOW_SOCKET_CONFIG */
354
355 #if MEMP_OVERFLOW_CHECK >= 2
356 /* check everything a first time to see if it worked */
357 memp_overflow_check_all();
358 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
359 }
360
361 static void *
362 #if !MEMP_OVERFLOW_CHECK
do_memp_malloc_pool(const struct memp_desc * desc)363 do_memp_malloc_pool(const struct memp_desc *desc)
364 #else
365 do_memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
366 #endif
367 {
368 struct memp *memp;
369 SYS_ARCH_DECL_PROTECT(old_level);
370
371 #if MEMP_MEM_MALLOC
372 memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));
373 SYS_ARCH_PROTECT(old_level);
374 #else /* MEMP_MEM_MALLOC */
375 SYS_ARCH_PROTECT(old_level);
376
377 memp = *desc->tab;
378 #endif /* MEMP_MEM_MALLOC */
379
380 if (memp != NULL) {
381 #if MEMP_DOUBLE_FREE_CHECK
382 memp->is_used = 1;
383 #endif
384
385 #if !MEMP_MEM_MALLOC
386 #if MEMP_OVERFLOW_CHECK == 1
387 memp_overflow_check_element(memp, desc);
388 #endif /* MEMP_OVERFLOW_CHECK */
389
390 *desc->tab = memp->next;
391 #if MEMP_OVERFLOW_CHECK
392 memp->next = NULL;
393 #endif /* MEMP_OVERFLOW_CHECK */
394 #endif /* !MEMP_MEM_MALLOC */
395 #if MEMP_OVERFLOW_CHECK
396 memp->file = file;
397 memp->line = line;
398 #if MEMP_MEM_MALLOC
399 memp_overflow_init_element(memp, desc);
400 #endif /* MEMP_MEM_MALLOC */
401 #endif /* MEMP_OVERFLOW_CHECK */
402 LWIP_ASSERT("memp_malloc: memp properly aligned",
403 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
404 #if MEMP_STATS
405 desc->stats->used++;
406 if (desc->stats->used > desc->stats->max) {
407 desc->stats->max = desc->stats->used;
408 }
409 #endif
410 SYS_ARCH_UNPROTECT(old_level);
411 /* cast through u8_t* to get rid of alignment warnings */
412 return ((u8_t *)memp + MEMP_SIZE);
413 } else {
414 #if MEMP_STATS
415 desc->stats->err++;
416 #endif
417 LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc));
418 }
419
420 SYS_ARCH_UNPROTECT(old_level);
421 return NULL;
422 }
423
424 /**
425 * Get an element from a custom pool.
426 *
427 * @param desc the pool to get an element from
428 *
429 * @return a pointer to the allocated memory or a NULL pointer on error
430 */
431 void *
432 #if !MEMP_OVERFLOW_CHECK
memp_malloc_pool(const struct memp_desc * desc)433 memp_malloc_pool(const struct memp_desc *desc)
434 #else
435 memp_malloc_pool_fn(const struct memp_desc *desc, const char *file, const int line)
436 #endif
437 {
438 LWIP_ASSERT("invalid pool desc", desc != NULL);
439 if (desc == NULL) {
440 return NULL;
441 }
442
443 #if !MEMP_OVERFLOW_CHECK
444 return do_memp_malloc_pool(desc);
445 #else
446 return do_memp_malloc_pool_fn(desc, file, line);
447 #endif
448 }
449
450 /**
451 * Get an element from a specific pool.
452 *
453 * @param type the pool to get an element from
454 *
455 * @return a pointer to the allocated memory or a NULL pointer on error
456 */
457 void *
458 #if !MEMP_OVERFLOW_CHECK
memp_malloc(memp_t type)459 memp_malloc(memp_t type)
460 #else
461 memp_malloc_fn(memp_t type, const char *file, const int line)
462 #endif
463 {
464 void *memp;
465 LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);
466
467 #if MEMP_OVERFLOW_CHECK >= 2
468 memp_overflow_check_all();
469 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
470
471 #if !MEMP_OVERFLOW_CHECK
472 memp = do_memp_malloc_pool(memp_pools[type]);
473 #else
474 memp = do_memp_malloc_pool_fn(memp_pools[type], file, line);
475 #endif
476
477 return memp;
478 }
479
480 static void
do_memp_free_pool(const struct memp_desc * desc,void * mem)481 do_memp_free_pool(const struct memp_desc *desc, void *mem)
482 {
483 struct memp *memp;
484 SYS_ARCH_DECL_PROTECT(old_level);
485
486 LWIP_ASSERT("memp_free: mem properly aligned",
487 ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
488
489 /* cast through void* to get rid of alignment warnings */
490 memp = (struct memp *)(void *)((u8_t *)mem - MEMP_SIZE);
491
492 SYS_ARCH_PROTECT(old_level);
493 #if MEMP_DOUBLE_FREE_CHECK
494 if (!memp->is_used) {
495 LWIP_DEBUGF(MEMP_DEBUG, ("memp_free: double free memp\n"));
496 SYS_ARCH_UNPROTECT(old_level);
497 return;
498 }
499 #endif
500
501 #if MEMP_OVERFLOW_CHECK == 1
502 memp_overflow_check_element(memp, desc);
503 #endif /* MEMP_OVERFLOW_CHECK */
504
505 #if MEMP_STATS
506 desc->stats->used--;
507 #endif
508
509 #if MEMP_DOUBLE_FREE_CHECK
510 memp->is_used = 0;
511 #endif
512 #if MEMP_MEM_MALLOC
513 LWIP_UNUSED_ARG(desc);
514 SYS_ARCH_UNPROTECT(old_level);
515 mem_free(memp);
516 #else /* MEMP_MEM_MALLOC */
517 memp->next = *desc->tab;
518 *desc->tab = memp;
519
520 #if MEMP_SANITY_CHECK
521 LWIP_ASSERT("memp sanity", memp_sanity(desc));
522 #endif /* MEMP_SANITY_CHECK */
523
524 SYS_ARCH_UNPROTECT(old_level);
525 #endif /* !MEMP_MEM_MALLOC */
526 }
527
528 /**
529 * Put a custom pool element back into its pool.
530 *
531 * @param desc the pool where to put mem
532 * @param mem the memp element to free
533 */
534 void
memp_free_pool(const struct memp_desc * desc,void * mem)535 memp_free_pool(const struct memp_desc *desc, void *mem)
536 {
537 LWIP_ASSERT("invalid pool desc", desc != NULL);
538 if ((desc == NULL) || (mem == NULL)) {
539 return;
540 }
541
542 do_memp_free_pool(desc, mem);
543 }
544
545 #if !MEMP_MEM_MALLOC
546 u32_t
memp_check(memp_t type,void * mem)547 memp_check(memp_t type, void *mem)
548 {
549 u8_t *memp_start = NULL;
550 u8_t *memp_end = NULL;
551
552 memp_start = (u8_t *)LWIP_MEM_ALIGN((void *)memp_pools[type]->base) + MEMP_SIZE;
553 memp_end = (u8_t *)memp_start
554 + (memp_pools[type]->num - 1U) * (MEMP_SIZE + memp_pools[type]->size
555 #if MEMP_OVERFLOW_CHECK
556 + MEM_SANITY_REGION_AFTER_ALIGNED
557 #endif
558 );
559
560 if ((mem >= (void*)memp_start) && (mem <= (void*)memp_end)) {
561 return 1;
562 } else {
563 return 0;
564 }
565 }
566 #endif
567
568 /**
569 * Put an element back into its pool.
570 *
571 * @param type the pool where to put mem
572 * @param mem the memp element to free
573 */
574 void
memp_free(memp_t type,void * mem)575 memp_free(memp_t type, void *mem)
576 {
577 #ifdef LWIP_HOOK_MEMP_AVAILABLE
578 struct memp *old_first;
579 #endif
580
581 LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);
582
583 if (mem == NULL) {
584 return;
585 }
586
587 #if MEMP_OVERFLOW_CHECK >= 2
588 memp_overflow_check_all();
589 #endif /* MEMP_OVERFLOW_CHECK >= 2 */
590
591 #ifdef LWIP_HOOK_MEMP_AVAILABLE
592 old_first = *memp_pools[type]->tab;
593 #endif
594
595 do_memp_free_pool(memp_pools[type], mem);
596
597 #ifdef LWIP_HOOK_MEMP_AVAILABLE
598 if (old_first == NULL) {
599 LWIP_HOOK_MEMP_AVAILABLE(type);
600 }
601 #endif
602 }
603 #if !MEMP_MEM_MALLOC
604 #ifdef LWIP_DEBUG_INFO
debug_memp_info(void)605 void debug_memp_info(void)
606 {
607 memp_t type;
608 u32_t memp_used;
609 u32_t memp_aval;
610 struct memp *memp = NULL;
611 #if LWIP_ALLOW_SOCKET_CONFIG
612 struct memp_desc *desc = NULL;
613 #else
614 const struct memp_desc *desc = NULL;
615 #endif
616 SYS_ARCH_DECL_PROTECT(old_level);
617
618 LWIP_PLATFORM_PRINT("[MEMP]%-4s %-8s %-8s %-8s\n",
619 "TYPE", "NUM", "USED", "AVAILABLE");
620
621 for (type = (memp_t)(0); type < (memp_t)(MEMP_MAX); type++) {
622 SYS_ARCH_PROTECT(old_level);
623 desc = memp_pools[type];
624 memp_aval = 0;
625 memp = *desc->tab;
626 while (memp != NULL) {
627 memp_aval++;
628 memp = memp->next;
629 }
630 memp_used = desc->num - memp_aval;
631
632 SYS_ARCH_UNPROTECT(old_level);
633 LWIP_PLATFORM_PRINT("[MEMP]%-4d ", type);
634 LWIP_PLATFORM_PRINT("%-8u ", desc->num);
635 LWIP_PLATFORM_PRINT("%-8u ", memp_used);
636 LWIP_PLATFORM_PRINT("%-8u\n", memp_aval);
637 }
638 }
639
debug_memp_detail(int type)640 void debug_memp_detail(int type)
641 {
642 u32_t idx;
643 #if LWIP_ALLOW_SOCKET_CONFIG
644 struct memp_desc *desc = NULL;
645 #else
646 const struct memp_desc *desc = NULL;
647 #endif
648
649 if ((type >= MEMP_MAX) || (type < 0)) {
650 LWIP_PLATFORM_PRINT("[MEMP]memp type %u is more than MEMP_MAX or < 0\n", type);
651 return;
652 }
653
654 desc = memp_pools[type];
655
656 LWIP_PLATFORM_PRINT("[MEMP]%-4s %-8s\n", "TYPE", "INDEX");
657 for (idx = 0; idx < desc->num; idx++) {
658 LWIP_PLATFORM_PRINT("[MEMP]%-4d ", type);
659 LWIP_PLATFORM_PRINT("%-8u\n", idx);
660 }
661 }
662
debug_memp_type_info(int type)663 void debug_memp_type_info(int type)
664 {
665 #if LWIP_ALLOW_SOCKET_CONFIG
666 struct memp_desc *desc = NULL;
667 #else
668 const struct memp_desc *desc = NULL;
669 #endif
670 struct memp *memp = NULL;
671 struct memp *memp_free_list = NULL;
672 u32_t idx;
673 u8_t found_in_free_list;
674 SYS_ARCH_DECL_PROTECT(old_level);
675
676 if ((type != MEMP_TCP_PCB) &&
677 #if LWIP_RAW
678 (type != MEMP_RAW_PCB) &&
679 #endif /* LWIP_RAW */
680 (type != MEMP_UDP_PCB) && (type != MEMP_NETCONN)) {
681 LWIP_PLATFORM_PRINT("memp type error!\n");
682 return;
683 }
684
685 desc = memp_pools[type];
686
687 for (idx = 0; idx < desc->num; idx++) {
688 SYS_ARCH_PROTECT(old_level);
689 memp = (struct memp *)(void *)((u8_t *)(LWIP_MEM_ALIGN(desc->base)) + idx * (MEMP_SIZE + desc->size
690 #if MEMP_OVERFLOW_CHECK
691 + MEM_SANITY_REGION_AFTER_ALIGNED
692 #endif
693 ));
694
695 /* Check whether the current memp element is present in the free list */
696 memp_free_list = *desc->tab;
697
698 found_in_free_list = 0;
699 while (memp_free_list != NULL) {
700 if (memp_free_list == memp) {
701 found_in_free_list = 1;
702 break;
703 }
704 memp_free_list = memp_free_list->next;
705 }
706 SYS_ARCH_UNPROTECT(old_level);
707 if (found_in_free_list != 0) {
708 /* If the memp element is found in the free list, then dont print its debug info */
709 continue;
710 }
711
712 switch (type) {
713 case MEMP_TCP_PCB:
714 (void)debug_tcppcb_info((struct tcp_pcb *)((u8_t*)memp + MEMP_SIZE));
715 break;
716 case MEMP_UDP_PCB:
717 (void)debug_udppcb_info((struct udp_pcb *)((u8_t*)memp + MEMP_SIZE));
718 break;
719 #if LWIP_RAW
720 case MEMP_RAW_PCB:
721 (void)debug_rawpcb_info((struct raw_pcb *)((u8_t*)memp + MEMP_SIZE));
722 break;
723 #endif
724 case MEMP_NETCONN:
725 (void)debug_netconn_info((struct netconn *)((u8_t*)memp + MEMP_SIZE), 0);
726 break;
727 default:
728 break;
729 }
730 }
731 }
732 #endif /* LWIP_DEBUG_INFO */
733 #endif /* !MEMP_MEM_MALLOC */
734