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

📄 pbuf.c

📁 LwIP adaptation for Fujitsu MB90f497 and CS8900A Ethernet driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2001, Swedish Institute of Computer Science.
 * All rights reserved. 
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the distribution. 
 * 3. Neither the name of the Institute nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software 
 *    without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE. 
 *
 * This file is part of the lwIP TCP/IP stack.
 * 
 * Author: Adam Dunkels <adam@sics.se>
 *
 * $Id: pbuf.c,v 1.9 2002/05/07 12:45:25 adam Exp $
 */

/*-----------------------------------------------------------------------------------*/
/* pbuf.c
 *
 * Functions for the manipulation of pbufs. The pbufs holds all packets in the
 * system.
 *
 */
/*-----------------------------------------------------------------------------------*/
#include "lwip/debug.h"

#include "lwip/stats.h"

#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"

#include "lwip/sys.h"
#include "lwip/lcd.h"
#include "lwip/perf.h"

static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
static sys_sem_t pbuf_pool_free_sem;
static struct pbuf *pbuf_pool = NULL;
static struct pbuf *pbuf_pool_alloc_cache = NULL;
static struct pbuf *pbuf_pool_free_cache = NULL;

/*-----------------------------------------------------------------------------------*/
/* pbuf_init():
 *
 * Initializes the pbuf module. A large part of memory is allocated
 * for holding the pool of pbufs. The size of the individual pbufs in
 * the pool is given by the size parameter, and the number of pbufs in
 * the pool by the num parameter.
 *
 * After the memory has been allocated, the pbufs are set up. The
 * ->next pointer in each pbuf is set up to point to the next pbuf in
 * the pool.
 */
/*-----------------------------------------------------------------------------------*/
void
pbuf_init(void)
{
  struct pbuf *p, *q;
  u16_t i;

  pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
  ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
   
#ifdef PBUF_STATS
  stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */
  
  /* Set up ->next pointers to link the pbufs of the pool together. */
  p = pbuf_pool;
  
  for(i = 0; i < PBUF_POOL_SIZE; ++i) {
    p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
    p->len = p->tot_len = PBUF_POOL_BUFSIZE;
    p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
    q = p;
    p = p->next;
  }
  
  /* The ->next pointer of last pbuf is NULL to indicate that there
     are no more pbufs in the pool. */
  q->next = NULL;

  pbuf_pool_alloc_lock = 0;
  pbuf_pool_free_lock = 0;
  pbuf_pool_free_sem = sys_sem_new(1);
  
}
/*-----------------------------------------------------------------------------------*/
/* The following two functions are only called from pbuf_alloc(). */
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
pbuf_pool_alloc(void)
{
  struct pbuf *p = NULL;

  /* First, see if there are pbufs in the cache. */
  if(pbuf_pool_alloc_cache) {
    p = pbuf_pool_alloc_cache;
    if(p) {
      pbuf_pool_alloc_cache = p->next; 
    }
  } else {
    /* Next, check the actual pbuf pool, but if the pool is locked, we
       pretend to be out of buffers and return NULL. */
    if(pbuf_pool_free_lock) {
#ifdef PBUF_STATS
      ++stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
      return NULL;
    }
    pbuf_pool_alloc_lock = 1;
    if(!pbuf_pool_free_lock) {
      p = pbuf_pool;
      if(p) {
	pbuf_pool = p->next; 
      }
#ifdef PBUF_STATS
    } else {
      ++stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
    }
    pbuf_pool_alloc_lock = 0;
  }

#ifdef PBUF_STATS
  if(p != NULL) {
   
    ++stats.pbuf.used;
    if(stats.pbuf.used > stats.pbuf.max) {
      stats.pbuf.max = stats.pbuf.used;
    }
  }
#endif /* PBUF_STATS */

  return p;   
}
/*-----------------------------------------------------------------------------------*/
static void
pbuf_pool_free(struct pbuf *p)
{
  struct pbuf *q;

#ifdef PBUF_STATS
    for(q = p; q != NULL; q = q->next) {
      --stats.pbuf.used;
    }
#endif /* PBUF_STATS */
  
  if(pbuf_pool_alloc_cache == NULL) {
    pbuf_pool_alloc_cache = p;
  } else {  
    for(q = pbuf_pool_alloc_cache; q->next != NULL; q = q->next);
    q->next = p;    
  }
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_alloc():
 *
 * Allocates a pbuf at protocol layer l. The actual memory allocated
 * for the pbuf is determined by the layer at which the pbuf is
 * allocated and the requested size (from the size parameter). The
 * flag parameter decides how and where the pbuf should be allocated
 * as follows:
 * 
 * * PBUF_RAM: buffer memory for pbuf is allocated as one large
 *             chunk. This includes protocol headers as well. 
 * * RBUF_ROM: no buffer memory is allocated for the pbuf, even for
 *             protocol headers. Additional headers must be prepended
 *             by allocating another pbuf and chain in to the front of
 *             the ROM pbuf.	       
 * * PBUF_ROOL: the pbuf is allocated as a pbuf chain, with pbufs from
 *              the pbuf pool that is allocated during pbuf_init().
 */
/*-----------------------------------------------------------------------------------*/
struct pbuf *
pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag)
{
  struct pbuf *p, *q, *r;
  u16_t offset;
  s32_t rsize;

  offset = 0;
  switch(l) {
  case PBUF_TRANSPORT:
    offset += PBUF_TRANSPORT_HLEN;
    /* FALLTHROUGH */
  case PBUF_IP:
    offset += PBUF_IP_HLEN;
    offset += PBUF_LINK_HLEN;
    /* FALLTHROUGH */
  case PBUF_LINK:
    break;
  case PBUF_RAW:
    break;
  default:
    ASSERT("pbuf_alloc: bad pbuf layer", 0);
    return NULL;
  }

  switch(flag) {
  case PBUF_POOL:
    /* Allocate head of pbuf chain into p. */
    p = pbuf_pool_alloc();
    if(p == NULL) {
#ifdef PBUF_STATS
      ++stats.pbuf.err;
#endif /* PBUF_STATS */
      return NULL;
    }
    p->next = NULL;
    
    /* Set the payload pointer so that it points offset bytes into
       pbuf data memory. */
    p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));

    /* The total length of the pbuf is the requested size. */
    p->tot_len = size;

    /* Set the length of the first pbuf is the chain. */
    p->len = size > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: size;

    p->flags = PBUF_FLAG_POOL;
    
    /* Allocate the tail of the pbuf chain. */
    r = p;
    rsize = size - p->len;
    while(rsize > 0) {      
      q = pbuf_pool_alloc();
      if(q == NULL) {
	DEBUGF(PBUF_DEBUG, ("pbuf_alloc: Out of pbufs in pool,\n"));
#ifdef PBUF_STATS
        ++stats.pbuf.err;
#endif /* PBUF_STATS */
        pbuf_pool_free(p);
        return NULL;
      }
      q->next = NULL;
      r->next = q;
      q->len = rsize > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rsize;
      q->flags = PBUF_FLAG_POOL;
      q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
      r = q;
      q->ref = 1;
      q = q->next;
      rsize -= PBUF_POOL_BUFSIZE;
    }
    r->next = NULL;

    ASSERT("pbuf_alloc: pbuf->payload properly aligned",
	   ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
    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) + size + 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 = size;
    p->next = NULL;
    p->flags = PBUF_FLAG_RAM;
#ifdef PBUF_STATS 
	stats.varstats++;
#endif  	

    ASSERT("pbuf_alloc: pbuf->payload properly aligned",
	   ((u32_t)p->payload % MEM_ALIGNMENT) == 0);
    break;
  case PBUF_ROM:
    /* If the pbuf should point to ROM, we only need to allocate
       memory for the pbuf structure. */
    p = memp_mallocp(MEMP_PBUF);
    if(p == NULL) {
      return NULL;
    }
    p->payload = NULL;
    p->len = p->tot_len = size;
    p->next = NULL;
    p->flags = PBUF_FLAG_ROM;
    break;
  default:
    ASSERT("pbuf_alloc: erroneous flag", 0);
    return NULL;
  }
  p->ref = 1;
  return p;

⌨️ 快捷键说明

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