pbuf.c

来自「Keil下移植好的lwip基于c166」· C语言 代码 · 共 732 行 · 第 1/2 页

C
732
字号
#ifdef PBUF_STATS
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */
#define DEC_PBUF_STATS
#endif /* PBUF_STATS */

#define PBUF_POOL_FAST_FREE(p)  do {                                    \
                                  p->next = pbuf_pool_free_cache;       \
                                  pbuf_pool_free_cache = p;             \
                                  DEC_PBUF_STATS;                       \
                                } while (0)

#if SYS_LIGHTWEIGHT_PROT
#define PBUF_POOL_FREE(p)  do {                                         \
                                SYS_ARCH_DECL_PROTECT(old_level);       \
                                SYS_ARCH_PROTECT(old_level);            \
                                PBUF_POOL_FAST_FREE(p);                 \
                                SYS_ARCH_UNPROTECT(old_level);          \
                               } while(0)
#else /* SYS_LIGHTWEIGHT_PROT */
#define PBUF_POOL_FREE(p)  do {                                         \
                             sys_sem_wait(pbuf_pool_free_sem);          \
                             PBUF_POOL_FAST_FREE(p);                    \
                             sys_sem_signal(pbuf_pool_free_sem);        \
                           } while(0)
#endif /* SYS_LIGHTWEIGHT_PROT */
/*-----------------------------------------------------------------------------------*/
/* pbuf_realloc:
 *
 * Reallocates the memory for a pbuf. If the pbuf is in ROM, this as
 * simple as to adjust the ->tot_len and ->len fields. If the pbuf is
 * a pbuf chain, as it might be with both pbufs in dynamically
 * allocated RAM and for pbufs from the pbuf pool, we have to step
 * through the chain until we find the new endpoint in the pbuf chain.
 * Then the pbuf that is right on the endpoint is resized and any
 * further pbufs on the chain are deallocated.
 */
/*-----------------------------------------------------------------------------------*/
void
pbuf_realloc(struct pbuf *p, u16_t size)
{
  struct pbuf *q, *r;
  u16_t rsize;

  LWIP_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);
      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, (u8_t *)q->payload - (u8_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();
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_header():
 *
 * Adjusts the ->payload pointer so that space for a header appears in
 * the pbuf. Also, the ->tot_len and ->len fields are adjusted.
 *
 * Decreases the header size by the given amount.
 * Using a negative value increases the header size.
 */
/*-----------------------------------------------------------------------------------*/
u8_t
pbuf_header(struct pbuf *p, s16_t header_size)
{
  void *payload;

  if(p->flags & PBUF_FLAG_ROM) {
    return 1;
  }
  
  payload = p->payload;
  p->payload = (u8_t *)p->payload - header_size;

  DEBUGF(PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size));
  
  if((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
    DEBUGF(PBUF_DEBUG, ("pbuf_header: failed %p %p\n",
			(u8_t *)p->payload,
			(u8_t *)p + sizeof(struct pbuf)));
    p->payload = payload;
    return 1;
  }
  p->len += header_size;
  p->tot_len += header_size;
  
  return 0;
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_free():
 *
 * Decrements the reference count and deallocates the pbuf if the
 * reference count is zero. If the pbuf is a chain all pbufs in the
 * chain are deallocated.
 */ 
/*-----------------------------------------------------------------------------------*/
u8_t
pbuf_free(struct pbuf *p)
{
  struct pbuf *q;
  u8_t count = 0;
  SYS_ARCH_DECL_PROTECT(old_level);
  
  if(p == NULL) {
    return 0;
  }

  PERF_START;
 
/* *** CS *** TODO: re-enable this macro
 
  LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||
         p->flags == PBUF_FLAG_ROM ||
         p->flags == PBUF_FLAG_RAM);
  
  LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
*/
  /* Since decrementing ref cannot be guarranteed to be a single machine operation
     we must protect it. Also, the later test of ref must be protected.
  */
  SYS_ARCH_PROTECT(old_level);
  /* Decrement reference count. */  
  p->ref--;

  /*q = NULL;           DJH: Unnecessary statement*/
  /* If reference count == 0, actually deallocate pbuf. */
  if(p->ref == 0) {
      SYS_ARCH_UNPROTECT(old_level);
      
      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 *)((u8_t *)p + sizeof(struct pbuf));
              q = p->next;
              PBUF_POOL_FREE(p);
          } 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();
  }
  else
      SYS_ARCH_UNPROTECT(old_level);

  PERF_STOP("pbuf_free");
  
  return count;
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_clen():
 *
 * Returns the length of the pbuf chain.
 */
/*-----------------------------------------------------------------------------------*/
u8_t
pbuf_clen(struct pbuf *p)
{
  u8_t len;

  if(p == NULL) {
    return 0;
  }
  
  for(len = 0; p != NULL; p = p->next) {
    ++len;
  }
  return len;
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_ref():
 *
 * Increments the reference count of the pbuf.
 */
/*-----------------------------------------------------------------------------------*/
void
pbuf_ref(struct pbuf *p)
{
    SYS_ARCH_DECL_PROTECT(old_level);
    
  if(p == NULL) {
    return;
  }

  SYS_ARCH_PROTECT(old_level);
  ++(p->ref);
  SYS_ARCH_UNPROTECT(old_level);
}

/*------------------------------------------------------------------------------*/
/* pbuf_ref_chain():
 *
 * Increments the reference count of all pbufs in a chain.
 */
void
pbuf_ref_chain(struct pbuf *p)
{
    SYS_ARCH_DECL_PROTECT(old_level);
    SYS_ARCH_PROTECT(old_level);
    
    while (p != NULL) {
        p->ref++;
        p=p->next;
    }

    SYS_ARCH_UNPROTECT(old_level);
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_chain():
 *
 * Chains the two pbufs h and t together. The ->tot_len field of the
 * first pbuf (h) is adjusted.
 */
/*-----------------------------------------------------------------------------------*/
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
{
  struct pbuf *p;

  if(t == NULL) {
    return;
  }
  for(p = h; p->next != NULL; p = p->next);
  p->next = t;
  h->tot_len += t->tot_len;  
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_dechain():
 *
 * Adjusts the ->tot_len field of the pbuf and returns the tail (if
 * any) of the pbuf chain.
 */
/*-----------------------------------------------------------------------------------*/
struct pbuf *
pbuf_dechain(struct pbuf *p)
{
  struct pbuf *q;
  
  q = p->next;
  if (q != NULL) {
    q->tot_len = p->tot_len - p->len;
  }
  p->tot_len = p->len;
  p->next = NULL;
  return q;
}
/*-----------------------------------------------------------------------------------*/


struct pbuf *
pbuf_unref(struct pbuf *f)
{
  struct pbuf *p, *q;
  DEBUGF(PBUF_DEBUG, ("pbuf_unref: %p \n", (void*)f));
  /* first pbuf is of type PBUF_REF? */
  if (f->flags == PBUF_FLAG_REF)
  {
    /* allocate a pbuf (w/ payload) fully in RAM */
    p = pbuf_alloc(PBUF_RAW, f->len, PBUF_RAM);
    if (p != 0)
    {  
      int i;
      unsigned char *src, *dst;
      /* copy pbuf struct */
      p->next = f->next;
      src = f->payload;
      dst = p->payload;
      i = 0;
      /* copy payload to RAM pbuf */
      while(i < p->len)
      {
        *dst = *src;
        dst++;
        src++;
      }
      f->next = NULL;
      /* de-allocate PBUF_REF */
      pbuf_free(f);
      f = p;
      DEBUGF(PBUF_DEBUG, ("pbuf_unref: succesful %p \n", (void *)f));
    }
    else
    {
      /* deallocate chain */
      pbuf_free(f);
      f = NULL;
      DEBUGF(PBUF_DEBUG, ("pbuf_unref: failed\n"));
      return NULL;
    }
  }
  /* p = previous pbuf == first pbuf  */
  p = f;
  /* q = current pbuf */
  q = f->next;
  while (q != NULL)
  {
    q = q->next;
  }
  return f;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?