📄 pbuf.c
字号:
}
/*-----------------------------------------------------------------------------------*/
/* pbuf_refresh():
*
* Moves free buffers from the pbuf_pool_free_cache to the pbuf_pool
* list (if possible).
*
*/
/*-----------------------------------------------------------------------------------*/
void
pbuf_refresh(void)
{
struct pbuf *p;
sys_sem_wait(pbuf_pool_free_sem);
if(pbuf_pool_free_cache != NULL) {
pbuf_pool_free_lock = 1;
if(!pbuf_pool_alloc_lock) {
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;
#ifdef PBUF_STATS
} else {
++stats.pbuf.refresh_locked;
#endif /* PBUF_STATS */
}
pbuf_pool_free_lock = 0;
}
sys_sem_signal(pbuf_pool_free_sem);
}
#define PBUF_POOL_FREE(p) do { \
sys_sem_wait(pbuf_pool_free_sem); \
p->next = pbuf_pool_free_cache; \
pbuf_pool_free_cache = p; \
sys_sem_signal(pbuf_pool_free_sem); \
} while(0)
/*-----------------------------------------------------------------------------------*/
/* 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;
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);
#ifdef PBUF_STATS
--stats.pbuf.used;
#endif /* PBUF_STATS */
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.
*/
/*-----------------------------------------------------------------------------------*/
u8_t
pbuf_header(struct pbuf *p, s16_t header_size)
{
void *payload;
s16_t aux = -header_size;
payload = p->payload;
if(header_size>0)
p->payload = (u8_t *)p->payload - header_size/sizeof(u8_t);
else
p->payload = (u8_t *)p->payload + aux/sizeof(u8_t);
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;
}
if(header_size>0) {
p->len += header_size;
p->tot_len += header_size;
} else {
p->len -= aux;
p->tot_len -= aux;
}
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;
if(p == NULL) {
return 0;
}
// Put_String("\npbuf_free: ");
PERF_START;
ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL ||
p->flags == PBUF_FLAG_ROM ||
p->flags == PBUF_FLAG_RAM);
ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
/* Decrement reference count. */
p->ref--;
q = NULL;
/* If reference count == 0, actually deallocate pbuf. */
if(p->ref == 0) {
while(p != NULL) {
/* Check if this is a pbuf from the pool. */
if(p->flags == PBUF_FLAG_POOL) {
// Put_String("pbuf_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);
#ifdef PBUF_STATS
--stats.pbuf.used;
#endif /* PBUF_STATS */
} else if(p->flags == PBUF_FLAG_ROM) {
q = p->next;
memp_freep(MEMP_PBUF, p);
} else {
q = p->next;
mem_free(p);
#ifdef PBUF_STATS
stats.varstats--;
#endif
}
p = q;
++count;
}
pbuf_refresh();
}
PERF_STOP("pbuf_free");
// mprintf(count,4,0);
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)
{
if(p == NULL) {
return;
}
++(p->ref);
}
/*-----------------------------------------------------------------------------------*/
/* 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;
}
/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -