200 |
* * PBUF_ROM: no buffer memory is allocated for the pbuf, even for |
* * PBUF_ROM: no buffer memory is allocated for the pbuf, even for |
201 |
* protocol headers. Additional headers must be prepended |
* protocol headers. Additional headers must be prepended |
202 |
* by allocating another pbuf and chain in to the front of |
* by allocating another pbuf and chain in to the front of |
203 |
* the ROM pbuf. |
* the ROM pbuf. It is assumed that the memory used is really |
204 |
|
* similar to ROM in that it is immutable and will not be |
205 |
|
* changed. Memory which is dynamic should generally not |
206 |
|
* be attached to PBUF_ROM pbufs. Use PBUF_REF instead. |
207 |
|
* * PBUF_REF: no buffer memory is allocated for the pbuf, even for |
208 |
|
* protocol headers. It is assumed that the pbuf is only |
209 |
|
* being used in a single thread. If the pbuf gets queued, |
210 |
|
* then pbuf_unref should be called to copy the buffer. |
211 |
* * PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from |
* * PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from |
212 |
* the pbuf pool that is allocated during pbuf_init(). |
* the pbuf pool that is allocated during pbuf_init(). |
213 |
*/ |
*/ |
304 |
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", |
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", |
305 |
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
306 |
break; |
break; |
307 |
case PBUF_ROM: |
case PBUF_ROM: |
308 |
|
case PBUF_REF: |
309 |
/* If the pbuf should point to ROM, we only need to allocate |
/* If the pbuf should point to ROM, we only need to allocate |
310 |
memory for the pbuf structure. */ |
memory for the pbuf structure. */ |
311 |
p = memp_mallocp(MEMP_PBUF); |
p = memp_mallocp(MEMP_PBUF); |
315 |
p->payload = NULL; |
p->payload = NULL; |
316 |
p->len = p->tot_len = size; |
p->len = p->tot_len = size; |
317 |
p->next = NULL; |
p->next = NULL; |
318 |
p->flags = PBUF_FLAG_ROM; |
if (flag == PBUF_ROM) |
319 |
|
p->flags = PBUF_FLAG_ROM; |
320 |
|
else |
321 |
|
p->flags = PBUF_FLAG_REF; |
322 |
break; |
break; |
323 |
default: |
default: |
324 |
LWIP_ASSERT("pbuf_alloc: erroneous flag", 0); |
LWIP_ASSERT("pbuf_alloc: erroneous flag", 0); |
419 |
u16_t rsize; |
u16_t rsize; |
420 |
|
|
421 |
LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL || |
LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL || |
422 |
p->flags == PBUF_FLAG_ROM || |
p->flags == PBUF_FLAG_ROM || |
423 |
p->flags == PBUF_FLAG_RAM); |
p->flags == PBUF_FLAG_RAM || |
424 |
|
p->flags == PBUF_FLAG_REF); |
425 |
|
|
426 |
|
|
427 |
if(p->tot_len <= size) { |
if(p->tot_len <= size) { |
450 |
q = r; |
q = r; |
451 |
} |
} |
452 |
break; |
break; |
453 |
case PBUF_FLAG_ROM: |
case PBUF_FLAG_ROM: |
454 |
|
case PBUF_FLAG_REF: |
455 |
p->len = size; |
p->len = size; |
456 |
break; |
break; |
457 |
case PBUF_FLAG_RAM: |
case PBUF_FLAG_RAM: |
499 |
{ |
{ |
500 |
void *payload; |
void *payload; |
501 |
|
|
502 |
if(p->flags & PBUF_FLAG_ROM) { |
if(p->flags == PBUF_FLAG_ROM || |
503 |
|
p->flags == PBUF_FLAG_REF) { |
504 |
return 1; |
return 1; |
505 |
} |
} |
506 |
|
|
544 |
|
|
545 |
LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL || |
LWIP_ASSERT("pbuf_free: sane flags", p->flags == PBUF_FLAG_POOL || |
546 |
p->flags == PBUF_FLAG_ROM || |
p->flags == PBUF_FLAG_ROM || |
547 |
p->flags == PBUF_FLAG_RAM); |
p->flags == PBUF_FLAG_RAM || |
548 |
|
p->flags == PBUF_FLAG_REF ); |
549 |
|
|
550 |
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); |
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); |
551 |
|
|
569 |
q = p->next; |
q = p->next; |
570 |
PBUF_POOL_FREE(p); |
PBUF_POOL_FREE(p); |
571 |
} else { |
} else { |
572 |
if(p->flags == PBUF_FLAG_ROM) { |
if(p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) { |
573 |
q = p->next; |
q = p->next; |
574 |
memp_freep(MEMP_PBUF, p); |
memp_freep(MEMP_PBUF, p); |
575 |
} else { |
} else { |
579 |
} |
} |
580 |
|
|
581 |
p = q; |
p = q; |
582 |
|
/* Only free the next one in a chain if it's reference count is 0. |
583 |
|
This allows buffer chains to have multiple headers pointing to them. */ |
584 |
|
if (p) |
585 |
|
{ |
586 |
|
p->ref--; |
587 |
|
if (p->ref > 0) |
588 |
|
break; |
589 |
|
} |
590 |
|
|
591 |
++count; |
++count; |
592 |
} |
} |
593 |
pbuf_refresh(); |
pbuf_refresh(); |
697 |
return q; |
return q; |
698 |
} |
} |
699 |
/*-----------------------------------------------------------------------------------*/ |
/*-----------------------------------------------------------------------------------*/ |
700 |
|
/** Replace any pbufs of type PBUF_FLAG_REF with PBUF_POOL buffers. |
701 |
|
|
702 |
|
Go through pbuf chain and replace any PBUF_REF buffers with PBUF_POOL |
703 |
|
buffers. This is generally done for buffer chains which need to be queued |
704 |
|
in some way (either on an output queue or on the arp queue). All pbufs |
705 |
|
replaced will be freed immediately. |
706 |
|
|
707 |
|
@param f Head of pbuf chain to process |
708 |
|
|
709 |
|
@return Pointer to new head of pbuf chain. |
710 |
|
*/ |
711 |
struct pbuf * |
struct pbuf * |
712 |
pbuf_unref(struct pbuf *f) |
pbuf_unref(struct pbuf *f) |
713 |
{ |
{ |
714 |
struct pbuf *p, *q; |
struct pbuf *p, *prev, *q, *top; |
715 |
DEBUGF(PBUF_DEBUG, ("pbuf_unref: %p \n", (void*)f)); |
DEBUGF(PBUF_DEBUG, ("pbuf_unref: %p \n", (void*)f)); |
716 |
/* first pbuf is of type PBUF_REF? */ |
|
717 |
if (f->flags == PBUF_FLAG_REF) |
prev = 0; |
718 |
|
p = f; |
719 |
|
top = f; |
720 |
|
do |
721 |
{ |
{ |
722 |
/* allocate a pbuf (w/ payload) fully in RAM */ |
/* pbuf is of type PBUF_REF? */ |
723 |
p = pbuf_alloc(PBUF_RAW, f->len, PBUF_RAM); |
if (p->flags == PBUF_FLAG_REF) |
724 |
if (p != 0) |
{ |
725 |
{ |
/* allocate a pbuf (w/ payload) fully in RAM */ |
726 |
int i; |
/* PBUF_POOL buffers are faster if we can use them */ |
727 |
unsigned char *src, *dst; |
if (p->len <= PBUF_POOL_BUFSIZE) |
728 |
/* copy pbuf struct */ |
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL); |
729 |
p->next = f->next; |
else |
730 |
src = f->payload; |
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM); |
731 |
dst = p->payload; |
if (q != 0) |
732 |
i = 0; |
{ |
733 |
/* copy payload to RAM pbuf */ |
/* copy pbuf struct */ |
734 |
while(i < p->len) |
q->next = p->next; |
735 |
|
if (prev) |
736 |
|
/* Break chain and insert new pbuf instead */ |
737 |
|
prev->next = q; |
738 |
|
else |
739 |
|
top = q; |
740 |
|
p->next = NULL; |
741 |
|
|
742 |
|
memcpy(q->payload, p->payload, p->len); |
743 |
|
q->tot_len = p->tot_len; |
744 |
|
q->len = p->len; |
745 |
|
|
746 |
|
/* Don't copy ref, since someone else might be using the old buffer */ |
747 |
|
|
748 |
|
/* de-allocate PBUF_REF */ |
749 |
|
/* pbuf is not freed because it is assumed that some upper level |
750 |
|
program has a direct pointer to this pbuf and will free it. */ |
751 |
|
p = q; |
752 |
|
DEBUGF(PBUF_DEBUG, ("pbuf_unref: succesful %p \n", (void *)p)); |
753 |
|
} |
754 |
|
else |
755 |
{ |
{ |
756 |
*dst = *src; |
/* deallocate chain */ |
757 |
dst++; |
pbuf_free(top); |
758 |
src++; |
DEBUGF(PBUF_DEBUG, ("pbuf_unref: failed\n")); |
759 |
|
return NULL; |
760 |
} |
} |
|
f->next = NULL; |
|
|
/* de-allocate PBUF_REF */ |
|
|
pbuf_free(f); |
|
|
f = p; |
|
|
DEBUGF(PBUF_DEBUG, ("pbuf_unref: succesful %p \n", (void *)f)); |
|
761 |
} |
} |
762 |
else |
prev = p; |
763 |
{ |
p = p->next; |
764 |
/* deallocate chain */ |
} while (p); |
765 |
pbuf_free(f); |
|
766 |
f = NULL; |
return top; |
|
DEBUGF(PBUF_DEBUG, ("pbuf_unref: failed\n")); |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
/* p = previous pbuf == first pbuf */ |
|
|
p = f; |
|
|
/* q = current pbuf */ |
|
|
q = f->next; |
|
|
while (q != NULL) |
|
|
{ |
|
|
q = q->next; |
|
|
} |
|
|
return f; |
|
767 |
} |
} |