mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-07-02 19:08:57 +00:00
Fixed buf #19168 based on patch by Dmitry Potapov
This commit is contained in:
parent
1f544e087b
commit
9da7afb345
|
@ -42,6 +42,11 @@ HISTORY
|
||||||
|
|
||||||
++ Bug fixes:
|
++ Bug fixes:
|
||||||
|
|
||||||
|
2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov)
|
||||||
|
* pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if
|
||||||
|
SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available)
|
||||||
|
Also fixed cast warning in pbuf_alloc()
|
||||||
|
|
||||||
2007-03-04 Simon Goldschmidt
|
2007-03-04 Simon Goldschmidt
|
||||||
* etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt
|
* etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt
|
||||||
existing pbuf chain when enqueuing multiple pbufs to a pending ARP request
|
existing pbuf chain when enqueuing multiple pbufs to a pending ARP request
|
||||||
|
|
|
@ -216,7 +216,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||||
{
|
{
|
||||||
struct pbuf *p, *q, *r;
|
struct pbuf *p, *q, *r;
|
||||||
u16_t offset;
|
u16_t offset;
|
||||||
s32_t rem_len; /* remaining length */
|
u16_t rem_len; /* remaining length */
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
|
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||||
|
|
||||||
/* determine header offset */
|
/* determine header offset */
|
||||||
|
@ -270,6 +270,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||||
/* remember first pbuf for linkage in next iteration */
|
/* remember first pbuf for linkage in next iteration */
|
||||||
r = p;
|
r = p;
|
||||||
/* remaining length to be allocated */
|
/* remaining length to be allocated */
|
||||||
|
LWIP_ASSERT("length >= p->len", length >= p->len);
|
||||||
rem_len = length - p->len;
|
rem_len = length - p->len;
|
||||||
/* any remaining pbufs to be allocated? */
|
/* any remaining pbufs to be allocated? */
|
||||||
while (rem_len > 0) {
|
while (rem_len > 0) {
|
||||||
|
@ -296,7 +297,10 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||||
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
|
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
|
||||||
q->ref = 1;
|
q->ref = 1;
|
||||||
/* calculate remaining length to be allocated */
|
/* calculate remaining length to be allocated */
|
||||||
rem_len -= q->len;
|
if(q->len < rem_len)
|
||||||
|
rem_len -= q->len;
|
||||||
|
else
|
||||||
|
rem_len = 0;
|
||||||
/* remember this pbuf for linkage in next iteration */
|
/* remember this pbuf for linkage in next iteration */
|
||||||
r = q;
|
r = q;
|
||||||
}
|
}
|
||||||
|
@ -567,7 +571,6 @@ pbuf_free(struct pbuf *p)
|
||||||
u16_t flags;
|
u16_t flags;
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
u8_t count;
|
u8_t count;
|
||||||
SYS_ARCH_DECL_PROTECT(old_level);
|
|
||||||
|
|
||||||
LWIP_ASSERT("p != NULL", p != NULL);
|
LWIP_ASSERT("p != NULL", p != NULL);
|
||||||
/* if assertions are disabled, proceed with debug output */
|
/* if assertions are disabled, proceed with debug output */
|
||||||
|
@ -584,19 +587,22 @@ pbuf_free(struct pbuf *p)
|
||||||
p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);
|
p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
/* Since decrementing ref cannot be guaranteed to be a single machine operation
|
|
||||||
* we must protect it. Also, the later test of ref must be protected.
|
|
||||||
*/
|
|
||||||
SYS_ARCH_PROTECT(old_level);
|
|
||||||
/* de-allocate all consecutive pbufs from the head of the chain that
|
/* de-allocate all consecutive pbufs from the head of the chain that
|
||||||
* obtain a zero reference count after decrementing*/
|
* obtain a zero reference count after decrementing*/
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
|
u16_t ref;
|
||||||
|
SYS_ARCH_DECL_PROTECT(old_level);
|
||||||
|
/* Since decrementing ref cannot be guaranteed to be a single machine operation
|
||||||
|
* we must protect it. Also, the later test of ref must be protected.
|
||||||
|
*/
|
||||||
|
SYS_ARCH_PROTECT(old_level);
|
||||||
/* all pbufs in a chain are referenced at least once */
|
/* all pbufs in a chain are referenced at least once */
|
||||||
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
|
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
|
||||||
/* decrease reference count (number of pointers to pbuf) */
|
/* decrease reference count (number of pointers to pbuf) */
|
||||||
p->ref--;
|
ref = p->ref--;
|
||||||
|
SYS_ARCH_UNPROTECT(old_level);
|
||||||
/* this pbuf is no longer referenced to? */
|
/* this pbuf is no longer referenced to? */
|
||||||
if (p->ref == 0) {
|
if (ref == 0) {
|
||||||
/* remember next pbuf in chain for next iteration */
|
/* remember next pbuf in chain for next iteration */
|
||||||
q = p->next;
|
q = p->next;
|
||||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
|
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
|
||||||
|
@ -619,12 +625,11 @@ pbuf_free(struct pbuf *p)
|
||||||
/* p->ref > 0, this pbuf is still referenced to */
|
/* p->ref > 0, this pbuf is still referenced to */
|
||||||
/* (and so the remaining pbufs in chain as well) */
|
/* (and so the remaining pbufs in chain as well) */
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
|
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
|
||||||
/* stop walking through the chain */
|
/* stop walking through the chain */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SYS_ARCH_UNPROTECT(old_level);
|
|
||||||
PERF_STOP("pbuf_free");
|
PERF_STOP("pbuf_free");
|
||||||
/* return number of de-allocated pbufs */
|
/* return number of de-allocated pbufs */
|
||||||
return count;
|
return count;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user