⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pbuf.c

📁 网络服务器上实现操作系统和嵌入式协议栈的 结合
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef PBUF_STATS
        ++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
        /* bail out unsuccesfully */
        pbuf_pool_free(p);
        return NULL;
      }
      //q->next = NULL;
      /* make previous pbuf point to this pbuf */
      r->next = q;
      /* set length of this pbuf */
      q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
      q->flags = PBUF_FLAG_POOL;
      q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
      LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
	      ((u32_t)q->payload % MEM_ALIGNMENT) == 0);
      q->ref = 1;
      /* calculate remaining length to be allocated */
      rem_len -= q->len;
      /* remember this pbuf for linkage in next iteration */
      r = q;
    }
    /* end of chain */
    r->next = NULL;

    break;
  case PBUF_RAM:
    /* If pbuf is to be allocated in RAM, allocate memory for it. */
    p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + length + offset));
    if (p == NULL) {
      return NULL;
    }
    /* Set up internal structure of the pbuf. */
    p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
    p->len = p->tot_len = length;
    p->next = NULL;
    p->flags = PBUF_FLAG_RAM;

    LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
	   ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
    break;
  /* pbuf references existing (static constant) ROM payload? */
  case PBUF_ROM:
  /* pbuf references existing (externally allocated) RAM payload? */
  case PBUF_REF:
    /* only allocate memory for the pbuf structure */
    p = memp_mallocp(MEMP_PBUF);
    if (p == NULL) {
      DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_REF.\n"));
      return NULL;
    }
    /* caller must set this field properly, afterwards */
    p->payload = NULL;
    p->len = p->tot_len = length;
    p->next = NULL;
    p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
    break;
  default:
    LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
    return NULL;
  }
  p->ref = 1;
  return p;
}


/**
 *
 * Moves free buffers from the pbuf_pool_free_cache to the pbuf_pool
 * list (if possible).
 *
 */
void
pbuf_refresh(void)
{
  struct pbuf *p;
//丁一修改
#if SYS_LIGHTWEIGHT_PROT
  SYS_ARCH_DECL_PROTECT(old_level);
  SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */  
  sys_sem_wait(pbuf_pool_free_sem);
#endif /* SYS_LIGHTWEIGHT_PROT */  
//原本
//  SYS_ARCH_DECL_PROTECT(old_level);
//  SYS_ARCH_PROTECT(old_level);
//#if !SYS_LIGHTWEIGHT_PROT
//  sys_sem_wait(pbuf_pool_free_sem);
//#endif /* else SYS_LIGHTWEIGHT_PROT */
  
  if(pbuf_pool_free_cache != NULL) {
#if !SYS_LIGHTWEIGHT_PROT      
    pbuf_pool_free_lock = 1;
    if(!pbuf_pool_alloc_lock) {
#endif /* SYS_LIGHTWEIGHT_PROT */
      if(pbuf_pool == NULL) {
	pbuf_pool = pbuf_pool_free_cache;	
      } else {  
	for(p = pbuf_pool; p->next != NULL; p = p->next);
	p->next = pbuf_pool_free_cache;   
      }
      pbuf_pool_free_cache = NULL;
#if !SYS_LIGHTWEIGHT_PROT      
#ifdef PBUF_STATS
    } else {
      ++lwip_stats.pbuf.refresh_locked;
#endif /* PBUF_STATS */
    }
    
    pbuf_pool_free_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */    
  }


  //丁一修改  
#if SYS_LIGHTWEIGHT_PROT
  SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
  sys_sem_signal(pbuf_pool_free_sem);
#endif /* SYS_LIGHTWEIGHT_PROT */  
//原本  
//  SYS_ARCH_UNPROTECT(old_level);  
//#if !SYS_LIGHTWEIGHT_PROT      
//  sys_sem_signal(pbuf_pool_free_sem);
//#endif /* SYS_LIGHTWEIGHT_PROT */  
}

#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 */

/**
 * Shrink a pbuf chain to a desired length.
 *
 * @param p pbuf to shrink.
 * @param new_len desired new length of pbuf chain
 *
 * Depending on the desired length, the first few pbufs in a chain might
 * be skipped and left unchanged. The new last pbuf in the chain will be
 * resized, and any remaining pbufs will be freed.
 * 
 * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
 *
 * @bug Cannot grow the size of a pbuf (chain) (yet).
 */
void
pbuf_realloc(struct pbuf *p, u16_t new_len)
{
  struct pbuf *q;
  u16_t rem_len; /* remaining length */
  s16_t grow;

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

  /* desired length larger than current length? */
  if (new_len >= p->tot_len) {
    /* enlarging not yet supported */
    return;
  }
  
  /* the pbuf chain grows by (new_len - p->tot_len) bytes
   * (which may be negative in case of shrinking) */
  grow = new_len - p->tot_len;
  
  /* first, step over any pbufs that should remain in the chain */
  rem_len = new_len;
  q = p;  
  /* this pbuf should be kept? */
  while (rem_len > q->len) {
    /* decrease remaining length by pbuf length */
    rem_len -= q->len;
    /* decrease total length indicator */
    q->tot_len += grow;
    /* proceed to next pbuf in chain */
    q = q->next;
  }
  /* we have now reached the new last pbuf (in q) */
  /* rem_len == desired length for pbuf q */  

  /* shrink allocated memory for PBUF_RAM */
  /* (other types merely adjust their length fields */
  if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) {
    /* reallocate and adjust the length of the pbuf that will be split */
    mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
  }
  /* adjust length fields for new last pbuf */
  q->len = rem_len;
  q->tot_len = q->len;

  /* any remaining pbufs in chain? */
  if (q->next != NULL) {
    /* free remaining pbufs in chain */
    pbuf_free(q->next);
  }
  /* q is last packet in chain */
  q->next = NULL;

  pbuf_refresh();
}

/**
 * Adjusts the payload pointer to hide or reveal headers in the payload.
 * 
 * Adjusts the ->payload pointer so that space for a header
 * (dis)appears in the pbuf payload.
 *
 * The ->payload, ->tot_len and ->len fields are adjusted.
 *
 * @param hdr_size Number of bytes to increment header size which
 * increases the size of the pbuf. New space is on the front.
 * (Using a negative value decreases the header size.)
 *
 * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
 * the call will fail. A check is made that the increase in header size does
 * not move the payload pointer in front of the start of the buffer. 
 * @return 1 on failure, 0 on success.
 */
u8_t
pbuf_header(struct pbuf *p, s16_t header_size)
{
  void *payload;

  /* remember current payload pointer */
  payload = p->payload;

  /* pbuf types containing payloads? */
  if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
    /* set new payload pointer */
    p->payload = (u8_t *)p->payload - header_size;
    /* boundary check fails? */
    if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
      DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p\n",
        (u8_t *)p->payload,
        (u8_t *)p + sizeof(struct pbuf)) );\
      /* restore old payload pointer */
      p->payload = payload;
      /* bail out unsuccesfully */
      return 1;
    }
  /* pbuf types refering to payloads? */
  } else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
    /* hide a header in the payload? */
    if ((header_size < 0) && (header_size - p->len <= 0)) {
      /* increase payload pointer */
      p->payload = (u8_t *)p->payload - header_size;
    } else {
      /* cannot expand payload to front (yet!)
       * bail out unsuccesfully */
      return 1;
    }
  }
  DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size) );
  /* modify pbuf length fields */
  p->len += header_size;
  p->tot_len += header_size;

  return 0;
}

/**
 * Free a pbuf (chain) from usage, de-allocate non-used head of chain.
 *
 * 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, until
 * a non-zero reference count is encountered, or the end of the chain is
 * reached. 
 *
 * @param pbuf pbuf (chain) to be freed from one user.
 *
 * @return the number of unreferenced pbufs that were de-allocated 
 * from the head of the chain.
 *
 * @note the reference counter of a pbuf equals the number of pointers
 * that refer to the pbuf (or into the pbuf).
 *
 * @internal examples:
 *
 * 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;
//丁一修改
#if SYS_LIGHTWEIGHT_PROT
  SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */  
//原本
//  SYS_ARCH_DECL_PROTECT(old_level);

  if (p == NULL) {
    DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
    return 0;
  }

  PERF_START;

  LWIP_ASSERT("pbuf_free: sane flags",
    p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||

⌨️ 快捷键说明

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