29 |
|
|
30 |
/* |
/* |
31 |
* Copyright (c) 2001-2003 Swedish Institute of Computer Science. |
* Copyright (c) 2001-2003 Swedish Institute of Computer Science. |
32 |
* All rights reserved. |
* All rights reserved. |
33 |
* |
* |
34 |
* Redistribution and use in source and binary forms, with or without modification, |
* Redistribution and use in source and binary forms, with or without modification, |
35 |
* are permitted provided that the following conditions are met: |
* are permitted provided that the following conditions are met: |
36 |
* |
* |
37 |
* 1. Redistributions of source code must retain the above copyright notice, |
* 1. Redistributions of source code must retain the above copyright notice, |
40 |
* this list of conditions and the following disclaimer in the documentation |
* this list of conditions and the following disclaimer in the documentation |
41 |
* and/or other materials provided with the distribution. |
* and/or other materials provided with the distribution. |
42 |
* 3. The name of the author may not be used to endorse or promote products |
* 3. The name of the author may not be used to endorse or promote products |
43 |
* derived from this software without specific prior written permission. |
* derived from this software without specific prior written permission. |
44 |
* |
* |
45 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
46 |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
47 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
48 |
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
49 |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
50 |
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
51 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
52 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
53 |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
54 |
* OF SUCH DAMAGE. |
* OF SUCH DAMAGE. |
55 |
* |
* |
56 |
* This file is part of the lwIP TCP/IP stack. |
* This file is part of the lwIP TCP/IP stack. |
57 |
* |
* |
58 |
* Author: Adam Dunkels <adam@sics.se> |
* Author: Adam Dunkels <adam@sics.se> |
59 |
* |
* |
60 |
*/ |
*/ |
101 |
|
|
102 |
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0]; |
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0]; |
103 |
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0); |
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0); |
104 |
|
|
105 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
106 |
lwip_stats.pbuf.avail = PBUF_POOL_SIZE; |
lwip_stats.pbuf.avail = PBUF_POOL_SIZE; |
107 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
108 |
|
|
109 |
/* Set up ->next pointers to link the pbufs of the pool together */ |
/* Set up ->next pointers to link the pbufs of the pool together */ |
110 |
p = pbuf_pool; |
p = pbuf_pool; |
111 |
|
|
112 |
for(i = 0; i < PBUF_POOL_SIZE; ++i) { |
for(i = 0; i < PBUF_POOL_SIZE; ++i) { |
113 |
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf)); |
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf)); |
114 |
p->len = p->tot_len = PBUF_POOL_BUFSIZE; |
p->len = p->tot_len = PBUF_POOL_BUFSIZE; |
116 |
q = p; |
q = p; |
117 |
p = p->next; |
p = p->next; |
118 |
} |
} |
119 |
|
|
120 |
/* The ->next pointer of last pbuf is NULL to indicate that there |
/* The ->next pointer of last pbuf is NULL to indicate that there |
121 |
are no more pbufs in the pool */ |
are no more pbufs in the pool */ |
122 |
q->next = NULL; |
q->next = NULL; |
123 |
|
|
124 |
#if !SYS_LIGHTWEIGHT_PROT |
#if !SYS_LIGHTWEIGHT_PROT |
125 |
pbuf_pool_alloc_lock = 0; |
pbuf_pool_alloc_lock = 0; |
126 |
pbuf_pool_free_lock = 0; |
pbuf_pool_free_lock = 0; |
127 |
pbuf_pool_free_sem = sys_sem_new(1); |
pbuf_pool_free_sem = sys_sem_new(1); |
128 |
#endif |
#endif |
129 |
} |
} |
130 |
|
|
131 |
/** |
/** |
138 |
|
|
139 |
SYS_ARCH_DECL_PROTECT(old_level); |
SYS_ARCH_DECL_PROTECT(old_level); |
140 |
SYS_ARCH_PROTECT(old_level); |
SYS_ARCH_PROTECT(old_level); |
141 |
|
|
142 |
#if !SYS_LIGHTWEIGHT_PROT |
#if !SYS_LIGHTWEIGHT_PROT |
143 |
/* Next, check the actual pbuf pool, but if the pool is locked, we |
/* Next, check the actual pbuf pool, but if the pool is locked, we |
144 |
pretend to be out of buffers and return NULL. */ |
pretend to be out of buffers and return NULL. */ |
145 |
if (pbuf_pool_free_lock) { |
if (pbuf_pool_free_lock) { |
150 |
} |
} |
151 |
pbuf_pool_alloc_lock = 1; |
pbuf_pool_alloc_lock = 1; |
152 |
if (!pbuf_pool_free_lock) { |
if (!pbuf_pool_free_lock) { |
153 |
#endif /* SYS_LIGHTWEIGHT_PROT */ |
#endif /* SYS_LIGHTWEIGHT_PROT */ |
154 |
p = pbuf_pool; |
p = pbuf_pool; |
155 |
if (p) { |
if (p) { |
156 |
pbuf_pool = p->next; |
pbuf_pool = p->next; |
157 |
} |
} |
158 |
#if !SYS_LIGHTWEIGHT_PROT |
#if !SYS_LIGHTWEIGHT_PROT |
159 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
160 |
} else { |
} else { |
161 |
++lwip_stats.pbuf.alloc_locked; |
++lwip_stats.pbuf.alloc_locked; |
162 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
163 |
} |
} |
164 |
pbuf_pool_alloc_lock = 0; |
pbuf_pool_alloc_lock = 0; |
165 |
#endif /* SYS_LIGHTWEIGHT_PROT */ |
#endif /* SYS_LIGHTWEIGHT_PROT */ |
166 |
|
|
167 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
168 |
if (p != NULL) { |
if (p != NULL) { |
169 |
++lwip_stats.pbuf.used; |
++lwip_stats.pbuf.used; |
170 |
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) { |
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) { |
171 |
lwip_stats.pbuf.max = lwip_stats.pbuf.used; |
lwip_stats.pbuf.max = lwip_stats.pbuf.used; |
174 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
175 |
|
|
176 |
SYS_ARCH_UNPROTECT(old_level); |
SYS_ARCH_UNPROTECT(old_level); |
177 |
return p; |
return p; |
178 |
} |
} |
179 |
|
|
180 |
|
|
187 |
* |
* |
188 |
* @param flag this parameter decides how and where the pbuf |
* @param flag this parameter decides how and where the pbuf |
189 |
* should be allocated as follows: |
* should be allocated as follows: |
190 |
* |
* |
191 |
* - PBUF_RAM: buffer memory for pbuf is allocated as one large |
* - PBUF_RAM: buffer memory for pbuf is allocated as one large |
192 |
* chunk. This includes protocol headers as well. |
* chunk. This includes protocol headers as well. |
193 |
* - PBUF_ROM: no buffer memory is allocated for the pbuf, even for |
* - PBUF_ROM: no buffer memory is allocated for the pbuf, even for |
194 |
* protocol headers. Additional headers must be prepended |
* protocol headers. Additional headers must be prepended |
195 |
* by allocating another pbuf and chain in to the front of |
* by allocating another pbuf and chain in to the front of |
205 |
* the pbuf pool that is allocated during pbuf_init(). |
* the pbuf pool that is allocated during pbuf_init(). |
206 |
* |
* |
207 |
* @return the allocated pbuf. If multiple pbufs where allocated, this |
* @return the allocated pbuf. If multiple pbufs where allocated, this |
208 |
* is the first pbuf of a pbuf chain. |
* is the first pbuf of a pbuf chain. |
209 |
*/ |
*/ |
210 |
struct pbuf * |
struct pbuf * |
211 |
pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag) |
pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag) |
241 |
case PBUF_POOL: |
case PBUF_POOL: |
242 |
/* allocate head of pbuf chain into p */ |
/* allocate head of pbuf chain into p */ |
243 |
p = pbuf_pool_alloc(); |
p = pbuf_pool_alloc(); |
244 |
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", p)); |
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); |
245 |
if (p == NULL) { |
if (p == NULL) { |
246 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
247 |
++lwip_stats.pbuf.err; |
++lwip_stats.pbuf.err; |
249 |
return NULL; |
return NULL; |
250 |
} |
} |
251 |
p->next = NULL; |
p->next = NULL; |
252 |
|
|
253 |
/* make the payload pointer point 'offset' bytes into pbuf data memory */ |
/* make the payload pointer point 'offset' bytes into pbuf data memory */ |
254 |
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); |
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); |
255 |
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", |
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", |
262 |
p->flags = PBUF_FLAG_POOL; |
p->flags = PBUF_FLAG_POOL; |
263 |
/* set reference count (needed here in case we fail) */ |
/* set reference count (needed here in case we fail) */ |
264 |
p->ref = 1; |
p->ref = 1; |
265 |
|
|
266 |
/* now allocate the tail of the pbuf chain */ |
/* now allocate the tail of the pbuf chain */ |
267 |
|
|
268 |
/* remember first pbuf for linkage in next iteration */ |
/* remember first pbuf for linkage in next iteration */ |
269 |
r = p; |
r = p; |
270 |
/* remaining length to be allocated */ |
/* remaining length to be allocated */ |
271 |
rem_len = length - p->len; |
rem_len = length - p->len; |
272 |
/* any remaining pbufs to be allocated? */ |
/* any remaining pbufs to be allocated? */ |
273 |
while (rem_len > 0) { |
while (rem_len > 0) { |
274 |
q = pbuf_pool_alloc(); |
q = pbuf_pool_alloc(); |
275 |
if (q == NULL) { |
if (q == NULL) { |
276 |
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n")); |
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n")); |
381 |
* Depending on the desired length, the first few pbufs in a chain might |
* Depending on the desired length, the first few pbufs in a chain might |
382 |
* be skipped and left unchanged. The new last pbuf in the chain will be |
* be skipped and left unchanged. The new last pbuf in the chain will be |
383 |
* resized, and any remaining pbufs will be freed. |
* resized, and any remaining pbufs will be freed. |
384 |
* |
* |
385 |
* @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. |
* @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. |
386 |
* @note May not be called on a packet queue. |
* @note May not be called on a packet queue. |
387 |
* |
* |
404 |
/* enlarging not yet supported */ |
/* enlarging not yet supported */ |
405 |
return; |
return; |
406 |
} |
} |
407 |
|
|
408 |
/* the pbuf chain grows by (new_len - p->tot_len) bytes |
/* the pbuf chain grows by (new_len - p->tot_len) bytes |
409 |
* (which may be negative in case of shrinking) */ |
* (which may be negative in case of shrinking) */ |
410 |
grow = new_len - p->tot_len; |
grow = new_len - p->tot_len; |
411 |
|
|
412 |
/* first, step over any pbufs that should remain in the chain */ |
/* first, step over any pbufs that should remain in the chain */ |
413 |
rem_len = new_len; |
rem_len = new_len; |
414 |
q = p; |
q = p; |
415 |
/* this pbuf should be kept? */ |
/* this pbuf should be kept? */ |
416 |
while (rem_len > q->len) { |
while (rem_len > q->len) { |
417 |
/* decrease remaining length by pbuf length */ |
/* decrease remaining length by pbuf length */ |
422 |
q = q->next; |
q = q->next; |
423 |
} |
} |
424 |
/* we have now reached the new last pbuf (in q) */ |
/* we have now reached the new last pbuf (in q) */ |
425 |
/* rem_len == desired length for pbuf q */ |
/* rem_len == desired length for pbuf q */ |
426 |
|
|
427 |
/* shrink allocated memory for PBUF_RAM */ |
/* shrink allocated memory for PBUF_RAM */ |
428 |
/* (other types merely adjust their length fields */ |
/* (other types merely adjust their length fields */ |
446 |
|
|
447 |
/** |
/** |
448 |
* Adjusts the payload pointer to hide or reveal headers in the payload. |
* Adjusts the payload pointer to hide or reveal headers in the payload. |
449 |
* |
* |
450 |
* Adjusts the ->payload pointer so that space for a header |
* Adjusts the ->payload pointer so that space for a header |
451 |
* (dis)appears in the pbuf payload. |
* (dis)appears in the pbuf payload. |
452 |
* |
* |
458 |
* |
* |
459 |
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so |
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so |
460 |
* the call will fail. A check is made that the increase in header size does |
* the call will fail. A check is made that the increase in header size does |
461 |
* not move the payload pointer in front of the start of the buffer. |
* not move the payload pointer in front of the start of the buffer. |
462 |
* @return 1 on failure, 0 on success. |
* @return 1 on failure, 0 on success. |
463 |
* |
* |
464 |
* @note May not be called on a packet queue. |
* @note May not be called on a packet queue. |
497 |
return 1; |
return 1; |
498 |
} |
} |
499 |
} |
} |
500 |
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", payload, p->payload, header_size) ); |
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n", (void *)payload, (void *)p->payload, header_size) ); |
501 |
/* modify pbuf length fields */ |
/* modify pbuf length fields */ |
502 |
p->len += header_size; |
p->len += header_size; |
503 |
p->tot_len += header_size; |
p->tot_len += header_size; |
513 |
* |
* |
514 |
* For a pbuf chain, this is repeated for each pbuf in the chain, until |
* For a pbuf chain, this is repeated for each pbuf in the chain, until |
515 |
* a non-zero reference count is encountered, or the end of the chain is |
* a non-zero reference count is encountered, or the end of the chain is |
516 |
* reached. |
* reached. |
517 |
* |
* |
518 |
* @param pbuf pbuf (chain) to be freed from one user. |
* @param pbuf pbuf (chain) to be freed from one user. |
519 |
* |
* |
520 |
* @return the number of unreferenced pbufs that were de-allocated |
* @return the number of unreferenced pbufs that were de-allocated |
521 |
* from the head of the chain. |
* from the head of the chain. |
522 |
* |
* |
523 |
* @note May not be called on a packet queue. |
* @note May not be called on a packet queue. |
531 |
* 1->1->2 becomes ....->1 |
* 1->1->2 becomes ....->1 |
532 |
* 2->1->1 becomes 1->1->1 |
* 2->1->1 becomes 1->1->1 |
533 |
* 1->1->1 becomes ....... |
* 1->1->1 becomes ....... |
534 |
* |
* |
535 |
*/ |
*/ |
536 |
u8_t |
u8_t |
537 |
pbuf_free(struct pbuf *p) |
pbuf_free(struct pbuf *p) |
538 |
{ |
{ |
587 |
/* p->ref > 0, this pbuf is still referenced to */ |
/* p->ref > 0, this pbuf is still referenced to */ |
588 |
/* (and so the remaining pbufs in chain as well) */ |
/* (and so the remaining pbufs in chain as well) */ |
589 |
} else { |
} else { |
590 |
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, p->ref)); |
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref)); |
591 |
/* stop walking through chain */ |
/* stop walking through chain */ |
592 |
p = NULL; |
p = NULL; |
593 |
} |
} |
610 |
{ |
{ |
611 |
u8_t len; |
u8_t len; |
612 |
|
|
613 |
len = 0; |
len = 0; |
614 |
while (p != NULL) { |
while (p != NULL) { |
615 |
++len; |
++len; |
616 |
p = p->next; |
p = p->next; |
629 |
pbuf_ref(struct pbuf *p) |
pbuf_ref(struct pbuf *p) |
630 |
{ |
{ |
631 |
SYS_ARCH_DECL_PROTECT(old_level); |
SYS_ARCH_DECL_PROTECT(old_level); |
632 |
/* pbuf given? */ |
/* pbuf given? */ |
633 |
if (p != NULL) { |
if (p != NULL) { |
634 |
SYS_ARCH_PROTECT(old_level); |
SYS_ARCH_PROTECT(old_level); |
635 |
++(p->ref); |
++(p->ref); |
644 |
* @param h head pbuf (chain) |
* @param h head pbuf (chain) |
645 |
* @param t tail pbuf (chain) |
* @param t tail pbuf (chain) |
646 |
* @note May not be called on a packet queue. |
* @note May not be called on a packet queue. |
647 |
* |
* |
648 |
* The ->tot_len fields of all pbufs of the head chain are adjusted. |
* The ->tot_len fields of all pbufs of the head chain are adjusted. |
649 |
* The ->next field of the last pbuf of the head chain is adjusted. |
* The ->next field of the last pbuf of the head chain is adjusted. |
650 |
* The ->ref field of the first pbuf of the tail chain is adjusted. |
* The ->ref field of the first pbuf of the tail chain is adjusted. |
651 |
* |
* |
652 |
*/ |
*/ |
653 |
void |
void |
654 |
pbuf_chain(struct pbuf *h, struct pbuf *t) |
pbuf_chain(struct pbuf *h, struct pbuf *t) |
660 |
|
|
661 |
if (t == NULL) |
if (t == NULL) |
662 |
return; |
return; |
663 |
|
|
664 |
/* proceed to last pbuf of chain */ |
/* proceed to last pbuf of chain */ |
665 |
for (p = h; p->next != NULL; p = p->next) { |
for (p = h; p->next != NULL; p = p->next) { |
666 |
/* add total length of second chain to all totals of first chain */ |
/* add total length of second chain to all totals of first chain */ |
685 |
* |
* |
686 |
* @param q pointer to first packet on the queue |
* @param q pointer to first packet on the queue |
687 |
* @param n packet to be queued |
* @param n packet to be queued |
688 |
* |
* |
689 |
*/ |
*/ |
690 |
void |
void |
691 |
pbuf_queue(struct pbuf *p, struct pbuf *n) |
pbuf_queue(struct pbuf *p, struct pbuf *n) |
710 |
/* now p->tot_len == p->len */ |
/* now p->tot_len == p->len */ |
711 |
/* proceed to next packet on queue */ |
/* proceed to next packet on queue */ |
712 |
p = p->next; |
p = p->next; |
713 |
} |
} |
714 |
/* chain last pbuf of h chain (p) with first of tail (t) */ |
/* chain last pbuf of h chain (p) with first of tail (t) */ |
715 |
p->next = n; |
p->next = n; |
716 |
/* t is now referenced to one more time */ |
/* t is now referenced to one more time */ |
723 |
* |
* |
724 |
* @param p pointer to first packet on the queue which will be dequeued. |
* @param p pointer to first packet on the queue which will be dequeued. |
725 |
* @return first packet on the remaining queue (NULL if no further packets). |
* @return first packet on the remaining queue (NULL if no further packets). |
726 |
* |
* |
727 |
*/ |
*/ |
728 |
struct pbuf * |
struct pbuf * |
729 |
pbuf_dequeue(struct pbuf *p) |
pbuf_dequeue(struct pbuf *p) |
768 |
* |
* |
769 |
* @param p Head of pbuf chain to process |
* @param p Head of pbuf chain to process |
770 |
* |
* |
771 |
* @return Pointer to head of pbuf chain |
* @return Pointer to head of pbuf chain |
772 |
*/ |
*/ |
773 |
struct pbuf * |
struct pbuf * |
774 |
pbuf_take(struct pbuf *p) |
pbuf_take(struct pbuf *p) |
803 |
/* replacement pbuf could be allocated? */ |
/* replacement pbuf could be allocated? */ |
804 |
if (q != NULL) |
if (q != NULL) |
805 |
{ |
{ |
806 |
/* copy p to q */ |
/* copy p to q */ |
807 |
/* copy successor */ |
/* copy successor */ |
808 |
q->next = p->next; |
q->next = p->next; |
809 |
/* remove linkage from original pbuf */ |
/* remove linkage from original pbuf */ |
849 |
p = p->next; |
p = p->next; |
850 |
} while (p); |
} while (p); |
851 |
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n")); |
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n")); |
852 |
|
|
853 |
return head; |
return head; |
854 |
} |
} |
855 |
|
|
867 |
{ |
{ |
868 |
struct pbuf *q; |
struct pbuf *q; |
869 |
u8_t tail_gone = 1; |
u8_t tail_gone = 1; |
870 |
/* tail */ |
/* tail */ |
871 |
q = p->next; |
q = p->next; |
872 |
/* pbuf has successor in chain? */ |
/* pbuf has successor in chain? */ |
873 |
if (q != NULL) { |
if (q != NULL) { |
880 |
/* total length of pbuf p is its own length only */ |
/* total length of pbuf p is its own length only */ |
881 |
p->tot_len = p->len; |
p->tot_len = p->len; |
882 |
/* q is no longer referenced by p, free it */ |
/* q is no longer referenced by p, free it */ |
883 |
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *) q)); |
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); |
884 |
tail_gone = pbuf_free(q); |
tail_gone = pbuf_free(q); |
885 |
if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *) q)); |
if (tail_gone > 0) LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, |
886 |
|
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); |
887 |
/* return remaining tail or NULL if deallocated */ |
/* return remaining tail or NULL if deallocated */ |
888 |
} |
} |
889 |
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ |
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ |
894 |
|
|
895 |
/* TODO: This function is unused in the lwIP stack and will be deprecated. This is due |
/* TODO: This function is unused in the lwIP stack and will be deprecated. This is due |
896 |
* to the new way chains are built. */ |
* to the new way chains are built. */ |
897 |
#if 0 |
#if 0 |
898 |
/** |
/** |
899 |
* |
* |
900 |
* Increment the reference count of all pbufs in a chain. |
* Increment the reference count of all pbufs in a chain. |
907 |
{ |
{ |
908 |
SYS_ARCH_DECL_PROTECT(old_level); |
SYS_ARCH_DECL_PROTECT(old_level); |
909 |
SYS_ARCH_PROTECT(old_level); |
SYS_ARCH_PROTECT(old_level); |
910 |
|
|
911 |
while (p != NULL) { |
while (p != NULL) { |
912 |
++p->ref; |
++p->ref; |
913 |
p = p->next; |
p = p->next; |