• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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