65 |
#endif |
#endif |
66 |
|
|
67 |
static struct pbuf *pbuf_pool = NULL; |
static struct pbuf *pbuf_pool = NULL; |
|
static struct pbuf *pbuf_pool_alloc_cache = NULL; |
|
|
static struct pbuf *pbuf_pool_free_cache = NULL; |
|
68 |
|
|
69 |
/** |
/** |
70 |
* Initializes the pbuf module. |
* Initializes the pbuf module. |
123 |
|
|
124 |
SYS_ARCH_DECL_PROTECT(old_level); |
SYS_ARCH_DECL_PROTECT(old_level); |
125 |
SYS_ARCH_PROTECT(old_level); |
SYS_ARCH_PROTECT(old_level); |
126 |
/* 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 { |
|
127 |
#if !SYS_LIGHTWEIGHT_PROT |
#if !SYS_LIGHTWEIGHT_PROT |
128 |
/* 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 |
129 |
pretend to be out of buffers and return NULL. */ |
pretend to be out of buffers and return NULL. */ |
130 |
if(pbuf_pool_free_lock) { |
if(pbuf_pool_free_lock) { |
131 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
132 |
++lwip_stats.pbuf.alloc_locked; |
++lwip_stats.pbuf.alloc_locked; |
133 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
134 |
return NULL; |
return NULL; |
135 |
} |
} |
136 |
pbuf_pool_alloc_lock = 1; |
pbuf_pool_alloc_lock = 1; |
137 |
if(!pbuf_pool_free_lock) { |
if(!pbuf_pool_free_lock) { |
138 |
#endif /* SYS_LIGHTWEIGHT_PROT */ |
#endif /* SYS_LIGHTWEIGHT_PROT */ |
139 |
p = pbuf_pool; |
p = pbuf_pool; |
140 |
if(p) { |
if(p) { |
141 |
pbuf_pool = p->next; |
pbuf_pool = p->next; |
142 |
} |
} |
143 |
#if !SYS_LIGHTWEIGHT_PROT |
#if !SYS_LIGHTWEIGHT_PROT |
144 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
145 |
} else { |
} else { |
146 |
++lwip_stats.pbuf.alloc_locked; |
++lwip_stats.pbuf.alloc_locked; |
147 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
|
} |
|
|
pbuf_pool_alloc_lock = 0; |
|
|
#endif /* SYS_LIGHTWEIGHT_PROT */ |
|
148 |
} |
} |
149 |
|
pbuf_pool_alloc_lock = 0; |
150 |
|
#endif /* SYS_LIGHTWEIGHT_PROT */ |
151 |
|
|
152 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
153 |
if(p != NULL) { |
if(p != NULL) { |
162 |
return p; |
return p; |
163 |
} |
} |
164 |
|
|
|
/** |
|
|
* @internal only called from pbuf_alloc() |
|
|
*/ |
|
|
static void |
|
|
pbuf_pool_free(struct pbuf *p) |
|
|
{ |
|
|
struct pbuf *q; |
|
|
SYS_ARCH_DECL_PROTECT(old_level); |
|
|
SYS_ARCH_PROTECT(old_level); |
|
|
|
|
|
#ifdef PBUF_STATS |
|
|
for(q = p; q != NULL; q = q->next) { |
|
|
--lwip_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; |
|
|
} |
|
|
SYS_ARCH_UNPROTECT(old_level); |
|
|
} |
|
165 |
|
|
166 |
/** |
/** |
167 |
* Allocates a pbuf. |
* Allocates a pbuf. |
236 |
/* make the payload pointer point 'offset' bytes into pbuf data memory */ |
/* make the payload pointer point 'offset' bytes into pbuf data memory */ |
237 |
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); |
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset))); |
238 |
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", |
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", |
239 |
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
240 |
/* the total length of the pbuf chain is the requested size */ |
/* the total length of the pbuf chain is the requested size */ |
241 |
p->tot_len = length; |
p->tot_len = length; |
242 |
/* set the length of the first pbuf in the chain */ |
/* set the length of the first pbuf in the chain */ |
259 |
++lwip_stats.pbuf.err; |
++lwip_stats.pbuf.err; |
260 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
261 |
/* bail out unsuccesfully */ |
/* bail out unsuccesfully */ |
262 |
pbuf_pool_free(p); |
pbuf_free(p); |
263 |
return NULL; |
return NULL; |
264 |
} |
} |
265 |
//q->next = NULL; |
//q->next = NULL; |
270 |
q->flags = PBUF_FLAG_POOL; |
q->flags = PBUF_FLAG_POOL; |
271 |
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf)); |
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf)); |
272 |
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", |
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", |
273 |
((u32_t)q->payload % MEM_ALIGNMENT) == 0); |
((u32_t)q->payload % MEM_ALIGNMENT) == 0); |
274 |
q->ref = 1; |
q->ref = 1; |
275 |
/* calculate remaining length to be allocated */ |
/* calculate remaining length to be allocated */ |
276 |
rem_len -= q->len; |
rem_len -= q->len; |
294 |
p->flags = PBUF_FLAG_RAM; |
p->flags = PBUF_FLAG_RAM; |
295 |
|
|
296 |
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", |
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", |
297 |
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
((u32_t)p->payload % MEM_ALIGNMENT) == 0); |
298 |
break; |
break; |
299 |
/* pbuf references existing (static constant) ROM payload? */ |
/* pbuf references existing (static constant) ROM payload? */ |
300 |
case PBUF_ROM: |
case PBUF_ROM: |
320 |
return p; |
return p; |
321 |
} |
} |
322 |
|
|
|
/** |
|
|
* |
|
|
* Moves free buffers from the pbuf_pool_free_cache to the pbuf_pool |
|
|
* list (if possible). |
|
|
* |
|
|
*/ |
|
|
void |
|
|
pbuf_refresh(void) |
|
|
{ |
|
|
struct pbuf *p; |
|
|
SYS_ARCH_DECL_PROTECT(old_level); |
|
|
SYS_ARCH_PROTECT(old_level); |
|
|
|
|
|
#if !SYS_LIGHTWEIGHT_PROT |
|
|
sys_sem_wait(pbuf_pool_free_sem); |
|
|
#endif /* else SYS_LIGHTWEIGHT_PROT */ |
|
|
|
|
|
if(pbuf_pool_free_cache != NULL) { |
|
|
#if !SYS_LIGHTWEIGHT_PROT |
|
|
pbuf_pool_free_lock = 1; |
|
|
if(!pbuf_pool_alloc_lock) { |
|
|
#endif /* SYS_LIGHTWEIGHT_PROT */ |
|
|
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; |
|
|
#if !SYS_LIGHTWEIGHT_PROT |
|
|
#ifdef PBUF_STATS |
|
|
} else { |
|
|
++lwip_stats.pbuf.refresh_locked; |
|
|
#endif /* PBUF_STATS */ |
|
|
} |
|
|
|
|
|
pbuf_pool_free_lock = 0; |
|
|
#endif /* SYS_LIGHTWEIGHT_PROT */ |
|
|
} |
|
|
SYS_ARCH_UNPROTECT(old_level); |
|
|
#if !SYS_LIGHTWEIGHT_PROT |
|
|
sys_sem_signal(pbuf_pool_free_sem); |
|
|
#endif /* SYS_LIGHTWEIGHT_PROT */ |
|
|
} |
|
323 |
|
|
324 |
#ifdef PBUF_STATS |
#ifdef PBUF_STATS |
325 |
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0) |
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0) |
328 |
#endif /* PBUF_STATS */ |
#endif /* PBUF_STATS */ |
329 |
|
|
330 |
#define PBUF_POOL_FAST_FREE(p) do { \ |
#define PBUF_POOL_FAST_FREE(p) do { \ |
331 |
p->next = pbuf_pool_free_cache; \ |
p->next = pbuf_pool; \ |
332 |
pbuf_pool_free_cache = p; \ |
pbuf_pool = p; \ |
333 |
DEC_PBUF_STATS; \ |
DEC_PBUF_STATS; \ |
334 |
} while (0) |
} while (0) |
335 |
|
|
417 |
/* q is last packet in chain */ |
/* q is last packet in chain */ |
418 |
q->next = NULL; |
q->next = NULL; |
419 |
|
|
|
pbuf_refresh(); |
|
420 |
} |
} |
421 |
|
|
422 |
/** |
/** |
561 |
} |
} |
562 |
} |
} |
563 |
SYS_ARCH_UNPROTECT(old_level); |
SYS_ARCH_UNPROTECT(old_level); |
|
pbuf_refresh(); |
|
564 |
PERF_STOP("pbuf_free"); |
PERF_STOP("pbuf_free"); |
565 |
/* return number of de-allocated pbufs */ |
/* return number of de-allocated pbufs */ |
566 |
return count; |
return count; |
733 |
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL); |
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL); |
734 |
if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n")); |
if (q == NULL) DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n")); |
735 |
} else { |
} else { |
736 |
/* no replacement pbuf yet */ |
/* no replacement pbuf yet */ |
737 |
q = NULL; |
q = NULL; |
738 |
DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n")); |
DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n")); |
739 |
} |
} |