Added lightweight protection. In coldfire this is implemented by disabling

interrupts. In unixsim this is implemented by using a mutex. Uses #define
SYS_LIGHTWEIGHT_PROT to enable. It is enabled in coldfire by default, but
disabled in unixsim.

Fixes bug 2005 if you enable SYS_LIGHTWEIGHT_PROT. So the bug is closed.
This commit is contained in:
davidhaas 2003-02-04 22:52:22 +00:00
parent 987e9df948
commit 98fbb855fb
4 changed files with 151 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science. * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved. * All rights reserved.
* *

View File

@ -212,9 +212,19 @@ void *
memp_mallocp(memp_t type) memp_mallocp(memp_t type)
{ {
void *mem; void *mem;
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level = sys_arch_protect();
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex); sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
mem = memp_malloc(type); mem = memp_malloc(type);
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex); sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
return mem; return mem;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -243,8 +253,19 @@ memp_free(memp_t type, void *mem)
void void
memp_freep(memp_t type, void *mem) memp_freep(memp_t type, void *mem)
{ {
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level = sys_arch_protect();
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex); sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
memp_free(type, mem); memp_free(type, mem);
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex); sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -52,8 +52,12 @@
#include "arch/perf.h" #include "arch/perf.h"
static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))]; static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
#ifndef SYS_LIGHTWEIGHT_PROT
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock; static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
static sys_sem_t pbuf_pool_free_sem; static sys_sem_t pbuf_pool_free_sem;
#endif
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_alloc_cache = NULL;
static struct pbuf *pbuf_pool_free_cache = NULL; static struct pbuf *pbuf_pool_free_cache = NULL;
@ -99,10 +103,11 @@ pbuf_init(void)
are no more pbufs in the pool. */ are no more pbufs in the pool. */
q->next = NULL; q->next = NULL;
#ifndef SYS_LIGHTWEIGHT_PROT
pbuf_pool_alloc_lock = 0; pbuf_pool_alloc_lock = 0;
pbuf_pool_free_lock = 0; pbuf_pool_free_lock = 0;
pbuf_pool_free_sem = sys_sem_new(1); pbuf_pool_free_sem = sys_sem_new(1);
#endif
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* The following two functions are only called from pbuf_alloc(). */ /* The following two functions are only called from pbuf_alloc(). */
@ -112,6 +117,12 @@ pbuf_pool_alloc(void)
{ {
struct pbuf *p = NULL; struct pbuf *p = NULL;
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level;
old_level = sys_arch_protect();
#endif /* SYS_LIGHTWEIGHT_PROT */
/* First, see if there are pbufs in the cache. */ /* First, see if there are pbufs in the cache. */
if(pbuf_pool_alloc_cache) { if(pbuf_pool_alloc_cache) {
p = pbuf_pool_alloc_cache; p = pbuf_pool_alloc_cache;
@ -119,6 +130,7 @@ pbuf_pool_alloc(void)
pbuf_pool_alloc_cache = p->next; pbuf_pool_alloc_cache = p->next;
} }
} else { } else {
#ifndef SYS_LIGHTWEIGHT_PROT
/* 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
pretend to be out of buffers and return NULL. */ pretend to be out of buffers and return NULL. */
if(pbuf_pool_free_lock) { if(pbuf_pool_free_lock) {
@ -129,18 +141,21 @@ pbuf_pool_alloc(void)
} }
pbuf_pool_alloc_lock = 1; pbuf_pool_alloc_lock = 1;
if(!pbuf_pool_free_lock) { if(!pbuf_pool_free_lock) {
#endif /* SYS_LIGHTWEIGHT_PROT */
p = pbuf_pool; p = pbuf_pool;
if(p) { if(p) {
pbuf_pool = p->next; pbuf_pool = p->next;
} }
#ifndef SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS #ifdef PBUF_STATS
} else { } else {
++lwip_stats.pbuf.alloc_locked; ++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
} }
pbuf_pool_alloc_lock = 0; pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
#ifdef PBUF_STATS #ifdef PBUF_STATS
if(p != NULL) { if(p != NULL) {
++lwip_stats.pbuf.used; ++lwip_stats.pbuf.used;
@ -150,6 +165,10 @@ pbuf_pool_alloc(void)
} }
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
return p; return p;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -157,19 +176,33 @@ static void
pbuf_pool_free(struct pbuf *p) pbuf_pool_free(struct pbuf *p)
{ {
struct pbuf *q; struct pbuf *q;
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level;
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef SYS_LIGHTWEIGHT_PROT
old_level = sys_arch_protect();
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef PBUF_STATS #ifdef PBUF_STATS
for(q = p; q != NULL; q = q->next) { for(q = p; q != NULL; q = q->next) {
--lwip_stats.pbuf.used; --lwip_stats.pbuf.used;
} }
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
#ifdef SYS_LIGHTWEIGHT_PROT
old_level = sys_arch_protect();
#endif /* SYS_LIGHTWEIGHT_PROT */
if(pbuf_pool_alloc_cache == NULL) { if(pbuf_pool_alloc_cache == NULL) {
pbuf_pool_alloc_cache = p; pbuf_pool_alloc_cache = p;
} else { } else {
for(q = pbuf_pool_alloc_cache; q->next != NULL; q = q->next); for(q = pbuf_pool_alloc_cache; q->next != NULL; q = q->next);
q->next = p; q->next = p;
} }
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* pbuf_alloc(): /* pbuf_alloc():
@ -313,12 +346,19 @@ void
pbuf_refresh(void) pbuf_refresh(void)
{ {
struct pbuf *p; struct pbuf *p;
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level;
old_level = sys_arch_protect();
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(pbuf_pool_free_sem); sys_sem_wait(pbuf_pool_free_sem);
#endif /* else SYS_LIGHTWEIGHT_PROT */
if(pbuf_pool_free_cache != NULL) { if(pbuf_pool_free_cache != NULL) {
#ifndef SYS_LIGHTWEIGHT_PROT
pbuf_pool_free_lock = 1; pbuf_pool_free_lock = 1;
if(!pbuf_pool_alloc_lock) { if(!pbuf_pool_alloc_lock) {
#endif /* SYS_LIGHTWEIGHT_PROT */
if(pbuf_pool == NULL) { if(pbuf_pool == NULL) {
pbuf_pool = pbuf_pool_free_cache; pbuf_pool = pbuf_pool_free_cache;
} else { } else {
@ -326,23 +366,48 @@ pbuf_refresh(void)
p->next = pbuf_pool_free_cache; p->next = pbuf_pool_free_cache;
} }
pbuf_pool_free_cache = NULL; pbuf_pool_free_cache = NULL;
#ifndef SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS #ifdef PBUF_STATS
} else { } else {
++lwip_stats.pbuf.refresh_locked; ++lwip_stats.pbuf.refresh_locked;
#endif /* PBUF_STATS */ #endif /* PBUF_STATS */
} }
pbuf_pool_free_lock = 0; pbuf_pool_free_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(pbuf_pool_free_sem); sys_sem_signal(pbuf_pool_free_sem);
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
#define PBUF_POOL_FREE(p) do { \
sys_sem_wait(pbuf_pool_free_sem); \ #ifdef PBUF_STATS
p->next = pbuf_pool_free_cache; \ #define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
pbuf_pool_free_cache = p; \ #else /* PBUF_STATS */
sys_sem_signal(pbuf_pool_free_sem); \ #define DEC_PBUF_STATS
#endif /* PBUF_STATS */
#define PBUF_POOL_FAST_FREE(p) do { \
p->next = pbuf_pool_free_cache; \
pbuf_pool_free_cache = p; \
DEC_PBUF_STATS; \
} while (0)
#ifdef SYS_LIGHTWEIGHT_PROT
#define PBUF_POOL_FREE(p) do { \
u32_t old_level = sys_arch_protect(); \
PBUF_POOL_FAST_FREE(p); \
sys_arch_unprotect(old_level); \
} while(0) } while(0)
#else /* SYS_LIGHTWEIGHT_PROT */
#define PBUF_POOL_FREE(p) do { \
sys_sem_wait(pbuf_pool_free_sem); \
PBUF_POOL_FAST_FREE(p); \
sys_sem_signal(pbuf_pool_free_sem); \
} while(0)
#endif /* SYS_LIGHTWEIGHT_PROT */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* pbuf_realloc: /* pbuf_realloc:
* *
@ -389,9 +454,6 @@ pbuf_realloc(struct pbuf *p, u16_t size)
while(q != NULL) { while(q != NULL) {
r = q->next; r = q->next;
PBUF_POOL_FREE(q); PBUF_POOL_FREE(q);
#ifdef PBUF_STATS
--lwip_stats.pbuf.used;
#endif /* PBUF_STATS */
q = r; q = r;
} }
break; break;
@ -477,7 +539,10 @@ pbuf_free(struct pbuf *p)
{ {
struct pbuf *q; struct pbuf *q;
u8_t count = 0; u8_t count = 0;
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level;
#endif /* SYS_LIGHTWEIGHT_PROT */
if(p == NULL) { if(p == NULL) {
return 0; return 0;
} }
@ -489,14 +554,23 @@ pbuf_free(struct pbuf *p)
p->flags == PBUF_FLAG_RAM); p->flags == PBUF_FLAG_RAM);
ASSERT("pbuf_free: p->ref > 0", p->ref > 0); ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
#ifdef SYS_LIGHTWEIGHT_PROT
/* Since decrementing ref cannot be guarranteed to be a single machine operation
we must protect it. Also, the later test of ref must be protected.
*/
old_level = sys_arch_protect();
#endif /* SYS_LIGHTWEIGHT_PROT */
/* Decrement reference count. */ /* Decrement reference count. */
p->ref--; p->ref--;
q = NULL; q = NULL;
/* If reference count == 0, actually deallocate pbuf. */ /* If reference count == 0, actually deallocate pbuf. */
if(p->ref == 0) { if(p->ref == 0) {
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#endif
while(p != NULL) { while(p != NULL) {
/* Check if this is a pbuf from the pool. */ /* Check if this is a pbuf from the pool. */
if(p->flags == PBUF_FLAG_POOL) { if(p->flags == PBUF_FLAG_POOL) {
@ -504,21 +578,25 @@ pbuf_free(struct pbuf *p)
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf)); p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
q = p->next; q = p->next;
PBUF_POOL_FREE(p); PBUF_POOL_FREE(p);
#ifdef PBUF_STATS
--lwip_stats.pbuf.used;
#endif /* PBUF_STATS */
} else if(p->flags == PBUF_FLAG_ROM) {
q = p->next;
memp_freep(MEMP_PBUF, p);
} else { } else {
q = p->next; if(p->flags == PBUF_FLAG_ROM) {
mem_free(p); q = p->next;
memp_freep(MEMP_PBUF, p);
} else {
q = p->next;
mem_free(p);
}
} }
p = q; p = q;
++count; ++count;
} }
pbuf_refresh(); pbuf_refresh();
} }
#ifdef SYS_LIGHTWEIGHT_PROT
else
sys_arch_unprotect(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
PERF_STOP("pbuf_free"); PERF_STOP("pbuf_free");
@ -553,10 +631,21 @@ pbuf_clen(struct pbuf *p)
void void
pbuf_ref(struct pbuf *p) pbuf_ref(struct pbuf *p)
{ {
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level;
#endif /* SYS_LIGHTWEIGHT_PROT */
if(p == NULL) { if(p == NULL) {
return; return;
} }
#ifdef SYS_LIGHTWEIGHT_PROT
old_level = sys_arch_protect();
#endif /* SYS_LIGHTWEIGHT_PROT */
++(p->ref); ++(p->ref);
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
@ -567,10 +656,18 @@ pbuf_ref(struct pbuf *p)
void void
pbuf_ref_chain(struct pbuf *p) pbuf_ref_chain(struct pbuf *p)
{ {
#ifdef SYS_LIGHTWEIGHT_PROT
u32_t old_level = sys_arch_protect();
#endif /* SYS_LIGHTWEIGHT_PROT */
while (p != NULL) { while (p != NULL) {
p->ref++; p->ref++;
p=p->next; p=p->next;
} }
#ifdef SYS_LIGHTWEIGHT_PROT
sys_arch_unprotect(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* pbuf_chain(): /* pbuf_chain():
@ -665,5 +762,3 @@ pbuf_unref(struct pbuf *f)
} }
return f; return f;
} }

View File

@ -103,6 +103,14 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);
void sys_mbox_free(sys_mbox_t mbox); void sys_mbox_free(sys_mbox_t mbox);
void sys_mbox_fetch(sys_mbox_t mbox, void **msg); void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
/* Critical Region Protection */
/* These functions must be implemented in the sys_arch.c file.
In some implementations they can provide a more light-weight protection
mechanism than using semaphores. Otherwise semaphores can be used for
implementation */
u32_t sys_arch_protect(void);
void sys_arch_unprotect(u32_t pval);
/* Thread functions. */ /* Thread functions. */
void sys_thread_new(void (* thread)(void *arg), void *arg); void sys_thread_new(void (* thread)(void *arg), void *arg);