BUG23408: avoid deadlock by splitting mail semaphore into "not_empty"

and "not_full"
This commit is contained in:
kieranm 2008-05-30 11:28:28 +00:00
parent 24282a28df
commit 43c61c1317

View File

@ -72,7 +72,8 @@ struct sys_mbox_msg {
struct sys_mbox { struct sys_mbox {
int first, last; int first, last;
void *msgs[SYS_MBOX_SIZE]; void *msgs[SYS_MBOX_SIZE];
struct sys_sem *mail; struct sys_sem *not_empty;
struct sys_sem *not_full;
struct sys_sem *mutex; struct sys_sem *mutex;
int wait_send; int wait_send;
}; };
@ -96,8 +97,8 @@ static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t lwprot_thread = (pthread_t) 0xDEAD; static pthread_t lwprot_thread = (pthread_t) 0xDEAD;
static int lwprot_count = 0; static int lwprot_count = 0;
static struct sys_sem *sys_sem_new_(u8_t count); static struct sys_sem *sys_sem_new_internal(u8_t count);
static void sys_sem_free_(struct sys_sem *sem); static void sys_sem_free_internal(struct sys_sem *sem);
static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex,
u32_t timeout); u32_t timeout);
@ -183,8 +184,9 @@ sys_mbox_new(int size)
mbox = malloc(sizeof(struct sys_mbox)); mbox = malloc(sizeof(struct sys_mbox));
if (mbox != NULL) { if (mbox != NULL) {
mbox->first = mbox->last = 0; mbox->first = mbox->last = 0;
mbox->mail = sys_sem_new_(0); mbox->not_empty = sys_sem_new_internal(0);
mbox->mutex = sys_sem_new_(1); mbox->not_full = sys_sem_new_internal(0);
mbox->mutex = sys_sem_new_internal(1);
mbox->wait_send = 0; mbox->wait_send = 0;
#if SYS_STATS #if SYS_STATS
@ -206,9 +208,10 @@ sys_mbox_free(struct sys_mbox *mbox)
#endif /* SYS_STATS */ #endif /* SYS_STATS */
sys_sem_wait(mbox->mutex); sys_sem_wait(mbox->mutex);
sys_sem_free_(mbox->mail); sys_sem_free_internal(mbox->not_empty);
sys_sem_free_(mbox->mutex); sys_sem_free_internal(mbox->not_full);
mbox->mail = mbox->mutex = NULL; sys_sem_free_internal(mbox->mutex);
mbox->not_empty = mbox->not_full = mbox->mutex = NULL;
/* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
free(mbox); free(mbox);
} }
@ -238,7 +241,7 @@ sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
mbox->last++; mbox->last++;
if (first) { if (first) {
sys_sem_signal(mbox->mail); sys_sem_signal(mbox->not_empty);
} }
sys_sem_signal(mbox->mutex); sys_sem_signal(mbox->mutex);
@ -258,7 +261,7 @@ sys_mbox_post(struct sys_mbox *mbox, void *msg)
while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
mbox->wait_send++; mbox->wait_send++;
sys_sem_signal(mbox->mutex); sys_sem_signal(mbox->mutex);
sys_arch_sem_wait(mbox->mail, 0); sys_arch_sem_wait(mbox->not_full, 0);
sys_arch_sem_wait(mbox->mutex, 0); sys_arch_sem_wait(mbox->mutex, 0);
mbox->wait_send--; mbox->wait_send--;
} }
@ -274,7 +277,7 @@ sys_mbox_post(struct sys_mbox *mbox, void *msg)
mbox->last++; mbox->last++;
if (first) { if (first) {
sys_sem_signal(mbox->mail); sys_sem_signal(mbox->not_empty);
} }
sys_sem_signal(mbox->mutex); sys_sem_signal(mbox->mutex);
@ -301,7 +304,7 @@ sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
mbox->first++; mbox->first++;
if (mbox->wait_send) { if (mbox->wait_send) {
sys_sem_signal(mbox->mail); sys_sem_signal(mbox->not_full);
} }
sys_sem_signal(mbox->mutex); sys_sem_signal(mbox->mutex);
@ -324,13 +327,13 @@ sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
/* We block while waiting for a mail to arrive in the mailbox. We /* We block while waiting for a mail to arrive in the mailbox. We
must be prepared to timeout. */ must be prepared to timeout. */
if (timeout != 0) { if (timeout != 0) {
time = sys_arch_sem_wait(mbox->mail, timeout); time = sys_arch_sem_wait(mbox->not_empty, timeout);
if (time == SYS_ARCH_TIMEOUT) { if (time == SYS_ARCH_TIMEOUT) {
return SYS_ARCH_TIMEOUT; return SYS_ARCH_TIMEOUT;
} }
} else { } else {
sys_arch_sem_wait(mbox->mail, 0); sys_arch_sem_wait(mbox->not_empty, 0);
} }
sys_arch_sem_wait(mbox->mutex, 0); sys_arch_sem_wait(mbox->mutex, 0);
@ -347,29 +350,16 @@ sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
mbox->first++; mbox->first++;
if (mbox->wait_send) { if (mbox->wait_send) {
sys_sem_signal(mbox->mail); sys_sem_signal(mbox->not_full);
} }
sys_sem_signal(mbox->mutex); sys_sem_signal(mbox->mutex);
return time; return time;
} }
/*-----------------------------------------------------------------------------------*/
struct sys_sem *
sys_sem_new(u8_t count)
{
#if SYS_STATS
lwip_stats.sys.sem.used++;
if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
#endif /* SYS_STATS */
return sys_sem_new_(count);
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static struct sys_sem * static struct sys_sem *
sys_sem_new_(u8_t count) sys_sem_new_internal(u8_t count)
{ {
struct sys_sem *sem; struct sys_sem *sem;
@ -381,7 +371,18 @@ sys_sem_new_(u8_t count)
} }
return sem; return sem;
} }
/*-----------------------------------------------------------------------------------*/
struct sys_sem *
sys_sem_new(u8_t count)
{
#if SYS_STATS
lwip_stats.sys.sem.used++;
if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
#endif /* SYS_STATS */
return sys_sem_new_internal(count);
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static u32_t static u32_t
cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout)
@ -465,6 +466,14 @@ sys_sem_signal(struct sys_sem *sem)
pthread_mutex_unlock(&(sem->mutex)); pthread_mutex_unlock(&(sem->mutex));
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static void
sys_sem_free_internal(struct sys_sem *sem)
{
pthread_cond_destroy(&(sem->cond));
pthread_mutex_destroy(&(sem->mutex));
free(sem);
}
/*-----------------------------------------------------------------------------------*/
void void
sys_sem_free(struct sys_sem *sem) sys_sem_free(struct sys_sem *sem)
{ {
@ -472,18 +481,9 @@ sys_sem_free(struct sys_sem *sem)
#if SYS_STATS #if SYS_STATS
lwip_stats.sys.sem.used--; lwip_stats.sys.sem.used--;
#endif /* SYS_STATS */ #endif /* SYS_STATS */
sys_sem_free_(sem); sys_sem_free_internal(sem);
} }
} }
/*-----------------------------------------------------------------------------------*/
static void
sys_sem_free_(struct sys_sem *sem)
{
pthread_cond_destroy(&(sem->cond));
pthread_mutex_destroy(&(sem->mutex));
free(sem);
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
unsigned long unsigned long
sys_unix_now() sys_unix_now()