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

📄 pbuf.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 3 页
字号:
  case PBUF_REF:    /* only allocate memory for the pbuf structure */    p = memp_malloc(MEMP_PBUF);    if (p == NULL) {      LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));      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;  }  /* set reference count */  p->ref = 1;  LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));  return p;}#if 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;                  \                                  pbuf_pool = 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. * @note May not be called on a packet queue. * * @bug Cannot grow the size of a pbuf (chain) (yet). */voidpbuf_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;  /* should this pbuf 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;}/** * 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_inc 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.) * If hdr_size_inc is 0, this function does nothing and returns succesful. * * 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 non-zero on failure, zero on success. * */u8_tpbuf_header(struct pbuf *p, s16_t header_size_increment){  u16_t flags;  void *payload;  LWIP_ASSERT("p != NULL", p != NULL);  if ((header_size_increment == 0) || (p == NULL)) return 0;   flags = p->flags;  /* remember current payload pointer */  payload = p->payload;  /* pbuf types containing payloads? */  if (flags == PBUF_FLAG_RAM || flags == PBUF_FLAG_POOL) {    /* set new payload pointer */    p->payload = (u8_t *)p->payload - header_size_increment;    /* boundary check fails? */    if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {      LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",        (void *)p->payload,        (void *)(p + 1)));\      /* restore old payload pointer */      p->payload = payload;      /* bail out unsuccesfully */      return 1;    }  /* pbuf types refering to external payloads? */  } else if (flags == PBUF_FLAG_REF || flags == PBUF_FLAG_ROM) {    /* hide a header in the payload? */    if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {      /* increase payload pointer */      p->payload = (u8_t *)p->payload - header_size_increment;    } else {      /* cannot expand payload to front (yet!)       * bail out unsuccesfully */      return 1;    }  }  /* modify pbuf length fields */  p->len += header_size_increment;  p->tot_len += header_size_increment;  LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",    (void *)payload, (void *)p->payload, header_size_increment));  return 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_tpbuf_free(struct pbuf *p){  u16_t flags;  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));      flags = p->flags;      /* is this a pbuf from the pool? */      if (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 (flags == PBUF_FLAG_ROM || flags == PBUF_FLAG_REF) {        memp_free(MEMP_PBUF, 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 %"U16_F", ending here.\n", (void *)p, (u16_t)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;}/** * Count number of pbufs in a chain * * @param p first pbuf of chain * @return the number of pbufs in a chain */u8_tpbuf_clen(struct pbuf *p){  u8_t len;  len = 0;  while (p != NULL) {    ++len;    p = p->next;  }  return len;}/** * Increment the reference count of the pbuf. * * @param p pbuf to increase reference counter of * */voidpbuf_ref(struct pbuf *p)

⌨️ 快捷键说明

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