* @ingroup pbuf * Dereference a pbuf chain or queue and deallocate any no-longer-used * pbufs at the head of this chain or queue. * * Decrements the pbuf reference count. If it reaches zero, the pbuf is * deallocated. * * For a pbuf chain, this is repeated for each pbuf in the chain, * up to the first pbuf which has a non-zero reference count after * decrementing. So, when all reference c
| 722 | * |
| 723 | */ |
| 724 | u8_t |
| 725 | pbuf_free(struct pbuf *p) |
| 726 | { |
| 727 | u8_t alloc_src; |
| 728 | struct pbuf *q; |
| 729 | u8_t count; |
| 730 | |
| 731 | if (p == NULL) { |
| 732 | LWIP_ASSERT("p != NULL", p != NULL); |
| 733 | /* if assertions are disabled, proceed with debug output */ |
| 734 | LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, |
| 735 | ("pbuf_free(p == NULL) was called.\n")); |
| 736 | return 0; |
| 737 | } |
| 738 | LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); |
| 739 | |
| 740 | PERF_START; |
| 741 | |
| 742 | count = 0; |
| 743 | /* de-allocate all consecutive pbufs from the head of the chain that |
| 744 | * obtain a zero reference count after decrementing*/ |
| 745 | while (p != NULL) { |
| 746 | LWIP_PBUF_REF_T ref; |
| 747 | SYS_ARCH_DECL_PROTECT(old_level); |
| 748 | /* Since decrementing ref cannot be guaranteed to be a single machine operation |
| 749 | * we must protect it. We put the new ref into a local variable to prevent |
| 750 | * further protection. */ |
| 751 | SYS_ARCH_PROTECT(old_level); |
| 752 | /* all pbufs in a chain are referenced at least once */ |
| 753 | LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); |
| 754 | /* decrease reference count (number of pointers to pbuf) */ |
| 755 | ref = --(p->ref); |
| 756 | SYS_ARCH_UNPROTECT(old_level); |
| 757 | /* this pbuf is no longer referenced to? */ |
| 758 | if (ref == 0) { |
| 759 | /* remember next pbuf in chain for next iteration */ |
| 760 | q = p->next; |
| 761 | LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); |
| 762 | alloc_src = pbuf_get_allocsrc(p); |
| 763 | #if LWIP_SUPPORT_CUSTOM_PBUF |
| 764 | /* is this a custom pbuf? */ |
| 765 | if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { |
| 766 | struct pbuf_custom *pc = (struct pbuf_custom *)p; |
| 767 | LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); |
| 768 | pc->custom_free_function(p); |
| 769 | } else |
| 770 | #endif /* LWIP_SUPPORT_CUSTOM_PBUF */ |
| 771 | { |
| 772 | /* is this a pbuf from the pool? */ |
| 773 | if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) { |
| 774 | memp_free(MEMP_PBUF_POOL, p); |
| 775 | /* is this a ROM or RAM referencing pbuf? */ |
| 776 | } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) { |
| 777 | memp_free(MEMP_PBUF, p); |
| 778 | /* type == PBUF_RAM */ |
| 779 | } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) { |
| 780 | mem_free(p); |
| 781 | } else { |