// File: /workspace/github_c_makefile_star2_O2/FH0[P]tun_direct/lwip-2.1.2/src/core/pbuf.c
// Function: pbuf_free
u8_t
pbuf_free(struct pbuf *p)
{
  u8_t alloc_src;
  struct pbuf *q;
  u8_t count;

  if (p == NULL) {
    LWIP_ASSERT("p != NULL", p != NULL);
    /* if assertions are disabled, proceed with debug output */
    LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                ("pbuf_free(p == NULL) was called.\n"));
    return 0;
  }
  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));

  PERF_START;

  count = 0;
  /* de-allocate all consecutive pbufs from the head of the chain that
   * obtain a zero reference count after decrementing*/
  while (p != NULL) {
    LWIP_PBUF_REF_T ref;
    SYS_ARCH_DECL_PROTECT(old_level);
    /* Since decrementing ref cannot be guaranteed to be a single machine operation
     * we must protect it. We put the new ref into a local variable to prevent
     * further protection. */
    SYS_ARCH_PROTECT(old_level);
    /* all pbufs in a chain are referenced at least once */
    LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
    /* decrease reference count (number of pointers to pbuf) */
    ref = --(p->ref);
    SYS_ARCH_UNPROTECT(old_level);
    /* this pbuf is no longer referenced to? */
    if (ref == 0) {
      /* remember next pbuf in chain for next iteration */
      q = p->next;
      LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
      alloc_src = pbuf_get_allocsrc(p);
#if LWIP_SUPPORT_CUSTOM_PBUF
      /* is this a custom pbuf? */
      if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
        struct pbuf_custom *pc = (struct pbuf_custom *)p;
        LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
        pc->custom_free_function(p);
      } else
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
      {
        /* is this a pbuf from the pool? */
        if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) {
          memp_free(MEMP_PBUF_POOL, p);
          /* is this a ROM or RAM referencing pbuf? */
        } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) {
          memp_free(MEMP_PBUF, p);
          /* type == PBUF_RAM */
        } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) {
          mem_free(p);
        } else {
          /* @todo: support freeing other types */
          LWIP_ASSERT("invalid pbuf type", 0);
        }
      }
      count++;
      /* proceed to next pbuf */
      p = q;
      /* p->ref > 0, this pbuf is still referenced to */
      /* (and so the remaining pbufs in chain as well) */
    } else {
      LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)ref));
      /* stop walking through the chain */
      p = NULL;
    }
  }
  PERF_STOP("pbuf_free");
  /* return number of de-allocated pbufs */
  return count;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x4ed3
movq %rdi, %r15
xorl %ebx, %ebx
pushq $0xa
popq %rbp
pushq $0xb
popq %r14
testq %r15, %r15
je 0x4e99
movq %r15, %rsi
movb 0x16(%r15), %al
testb %al, %al
je 0x4ea6
movl $0x0, %r15d
decb %al
movb %al, 0x16(%rsi)
jne 0x4e32
movq (%rsi), %r15
testb $0x2, 0x15(%rsi)
jne 0x4e74
movzbl 0x14(%rsi), %eax
andl $0xf, %eax
je 0x4e8d
cmpl $0x1, %eax
je 0x4e84
cmpl $0x2, %eax
jne 0x4f0b
movl %r14d, %edi
jmp 0x4e86
movq 0x18(%rsi), %rax
testq %rax, %rax
je 0x4eef
movq %rsi, %rdi
callq *%rax
jmp 0x4e95
movl %ebp, %edi
callq 0x3bcd
jmp 0x4e95
movq %rsi, %rdi
callq 0x3ace
incb %bl
jmp 0x4e32
movl %ebx, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0xf41f(%rip), %rdi      # 0x142cc
leaq 0xfa5b(%rip), %rsi      # 0x1490f
leaq 0xf96e(%rip), %rcx      # 0x14829
movl $0x2f1, %edx            # imm = 0x2F1
xorl %eax, %eax
callq 0x20d0
xorl %edi, %edi
callq 0x21b0
callq 0x2050
leaq 0xf3f2(%rip), %rdi      # 0x142cc
leaq 0xf9d2(%rip), %rsi      # 0x148b3
leaq 0xf941(%rip), %rcx      # 0x14829
movl $0x2dc, %edx            # imm = 0x2DC
jmp 0x4ec0
leaq 0xf3d6(%rip), %rdi      # 0x142cc
leaq 0xfa28(%rip), %rsi      # 0x14925
leaq 0xf925(%rip), %rcx      # 0x14829
movl $0x2ff, %edx            # imm = 0x2FF
jmp 0x4ec0
leaq 0xf3ba(%rip), %rdi      # 0x142cc
leaq 0xfa2d(%rip), %rsi      # 0x14946
leaq 0xf909(%rip), %rcx      # 0x14829
movl $0x30f, %edx            # imm = 0x30F
jmp 0x4ec0