Exemplo n.º 1
0
/*-----------------------------------------------------------------------------------*/
uint8_t
pbuf_free(struct pbuf *p)
{
  struct pbuf *q;
  uint8_t count = 0;

  if(p == NULL) {
    return 0;
  }

  ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||
         p->flags == PBUF_FLAG_ROM ||
         p->flags == PBUF_FLAG_RAM);

  ASSERT("pbuf_free: p->ref > 0", p->ref > 0);

  /* Decrement reference count. */
  p->ref--;

  q = NULL;
  /* If reference count == 0, actually deallocate pbuf. */
  if(p->ref == 0) {

    while(p != NULL) {
      /* Check if this is a pbuf from the pool. */
      if(p->flags == PBUF_FLAG_POOL) {
	p->len = p->tot_len = PBUF_POOL_BUFSIZE;
	p->payload = (void *)((uint8_t *)p + sizeof(struct pbuf));
	q = p->next;
	PBUF_POOL_FREE(p);
#ifdef PBUF_STATS
	--stats.pbuf.used;
#endif /* PBUF_STATS */
      } else if(p->flags == PBUF_FLAG_ROM) {
	q = p->next;
	memp_freep(MEMP_PBUF, p);
      } else {
	q = p->next;
	mem_free(p);
      }
      p = q;
      count++;
    }
    pbuf_refresh();
  }

  return count;
}
Exemplo n.º 2
0
/**
 * 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 counts are one, the whole
 * chain is free'd.
 *
 * @param pbuf The pbuf (chain) to be dereferenced.
 *
 * @return the number of pbufs that were de-allocated
 * from the head of the chain.
 *
 * @note MUST NOT be called on a packet queue (Not verified to work yet).
 * @note the reference counter of a pbuf equals the number of pointers
 * that refer to the pbuf (or into the pbuf).
 *
 * @internal examples:
 *
 * Assuming existing chains a->b->c with the following reference
 * counts, calling pbuf_free(a) results in:
 * 
 * 1->2->3 becomes ...1->3
 * 3->3->3 becomes 2->3->3
 * 1->1->2 becomes ......1
 * 2->1->1 becomes 1->1->1
 * 1->1->1 becomes .......
 *
 */
u8_t
pbuf_free(struct pbuf *p)
{
  struct pbuf *q;
  u8_t count;
  SYS_ARCH_DECL_PROTECT(old_level);

  LWIP_ASSERT("p != NULL", p != NULL);
  /* if assertions are disabled, proceed with debug output */
  if (p == NULL) {
    LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
    return 0;
  }
  LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));

  PERF_START;

  LWIP_ASSERT("pbuf_free: sane flags",
    p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||
    p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);

  count = 0;
  /* Since decrementing ref cannot be guaranteed to be a single machine operation
   * we must protect it. Also, the later test of ref must be protected.
   */
  SYS_ARCH_PROTECT(old_level);
  /* de-allocate all consecutive pbufs from the head of the chain that
   * obtain a zero reference count after decrementing*/
  while (p != NULL) {
    /* 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) */
    p->ref--;
    /* this pbuf is no longer referenced to? */
    if (p->ref == 0) {
      /* remember next pbuf in chain for next iteration */
      q = p->next;
      LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
      /* is this a pbuf from the pool? */
      if (p->flags == PBUF_FLAG_POOL) {
        p->len = p->tot_len = PBUF_POOL_BUFSIZE;
        p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
        PBUF_POOL_FREE(p);
      /* is this a ROM or RAM referencing pbuf? */
      } else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
        memp_free(MEMP_PBUF, p);
      /* p->flags == PBUF_FLAG_RAM */
      } else {
        mem_free(p);
      }
      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 | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
      /* stop walking through the chain */
      p = NULL;
    }
  }
  SYS_ARCH_UNPROTECT(old_level);
  PERF_STOP("pbuf_free");
  /* return number of de-allocated pbufs */
  return count;
}
Exemplo n.º 3
0
/*-----------------------------------------------------------------------------------*/
void
pbuf_realloc(struct pbuf *p, uint16_t size)
{
  struct pbuf *q, *r;
  uint16_t rsize;

  ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
         p->flags == PBUF_FLAG_ROM ||
         p->flags == PBUF_FLAG_RAM);


  if(p->tot_len <= size) {
    return;
  }

  switch(p->flags) {
  case PBUF_FLAG_POOL:
    /* First, step over any pbufs that should still be in the chain. */
    rsize = size;
    q = p;
    while(rsize > q->len) {
      rsize -= q->len;
      q = q->next;
    }
    /* Adjust the length of the pbuf that will be halved. */
    q->len = rsize;

    /* And deallocate any left over pbufs. */
    r = q->next;
    q->next = NULL;
    q = r;
    while(q != NULL) {
      r = q->next;
      PBUF_POOL_FREE(q);
#ifdef PBUF_STATS
      --stats.pbuf.used;
#endif /* PBUF_STATS */
      q = r;
    }
    break;
  case PBUF_FLAG_ROM:
    p->len = size;
    break;
  case PBUF_FLAG_RAM:
    /* First, step over the pbufs that should still be in the chain. */
    rsize = size;
    q = p;
    while(rsize > q->len) {
      rsize -= q->len;
      q = q->next;
    }
    if(q->flags == PBUF_FLAG_RAM) {
    /* Reallocate and adjust the length of the pbuf that will be halved. */
      mem_realloc(q, (uint8_t *)q->payload - (uint8_t *)q + rsize);
    }

    q->len = rsize;

    /* And deallocate any left over pbufs. */
    r = q->next;
    q->next = NULL;
    q = r;
    while(q != NULL) {
      r = q->next;
      pbuf_free(q);
      q = r;
    }
    break;
  }
  p->tot_len = size;

  pbuf_refresh();
}