📄 pbuf.c
字号:
/* * 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.1 2003/05/21 10:37:40 chenyu 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 "arch/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. *//*-----------------------------------------------------------------------------------*/voidpbuf_init(void){ struct pbuf *p, *q; u8_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; 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; }#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 voidpbuf_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; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -