diff --git a/include/pthread.h b/include/pthread.h index 191bbf4e8bf..38fce8d09c5 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -269,7 +269,7 @@ struct pthread_cond_s { sem_t sem; clockid_t clockid; - uint16_t wait_count; + int wait_count; }; #ifndef __PTHREAD_COND_T_DEFINED diff --git a/sched/pthread/pthread.h b/sched/pthread/pthread.h index d6c3bd76adf..baf48407c3d 100644 --- a/sched/pthread/pthread.h +++ b/sched/pthread/pthread.h @@ -78,6 +78,8 @@ # define mutex_setprioceiling(m,p,o) nxmutex_setprioceiling(m,p,o) #endif +#define COND_WAIT_COUNT(cond) ((FAR atomic_t *)&(cond)->wait_count) + /**************************************************************************** * Public Data ****************************************************************************/ diff --git a/sched/pthread/pthread_condbroadcast.c b/sched/pthread/pthread_condbroadcast.c index 58166654871..f67556009fd 100644 --- a/sched/pthread/pthread_condbroadcast.c +++ b/sched/pthread/pthread_condbroadcast.c @@ -31,6 +31,8 @@ #include #include +#include + #include "pthread/pthread.h" /**************************************************************************** @@ -42,10 +44,7 @@ * * Description: * A thread broadcast on a condition variable. - * pthread_cond_broadcast shall unblock all threads currently blocked on a - * specified condition variable cond. We need own the mutex that threads - * calling pthread_cond_wait or pthread_cond_timedwait have associated - * with the condition variable during their wait. + * * Input Parameters: * None * @@ -68,22 +67,24 @@ int pthread_cond_broadcast(FAR pthread_cond_t *cond) } else { + int wcnt = atomic_read(COND_WAIT_COUNT(cond)); + /* Loop until all of the waiting threads have been restarted. */ - while (cond->wait_count > 0) + while (wcnt > 0) { - /* If the value is less than zero (meaning that one or more - * thread is waiting), then post the condition semaphore. - * Only the highest priority waiting thread will get to execute - */ + if (atomic_cmpxchg(COND_WAIT_COUNT(cond), &wcnt, wcnt - 1)) + { + /* Post the condition semaphore to wake up a waiting thread. + * Only the highest priority waiting thread will get to execute + */ - ret = -nxsem_post(&cond->sem); + ret = -nxsem_post(&cond->sem); - /* Increment the semaphore count (as was done by the - * above post). - */ + /* Decrement the waiter count */ - cond->wait_count--; + wcnt--; + } } } diff --git a/sched/pthread/pthread_condclockwait.c b/sched/pthread/pthread_condclockwait.c index 77a62101f9a..120d72d3f5c 100644 --- a/sched/pthread/pthread_condclockwait.c +++ b/sched/pthread/pthread_condclockwait.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -113,7 +114,7 @@ int pthread_cond_clockwait(FAR pthread_cond_t *cond, sinfo("Give up mutex...\n"); - cond->wait_count++; + atomic_fetch_add(COND_WAIT_COUNT(cond), 1); /* Give up the mutex */ diff --git a/sched/pthread/pthread_condsignal.c b/sched/pthread/pthread_condsignal.c index 4e9055f773d..06a362836bc 100644 --- a/sched/pthread/pthread_condsignal.c +++ b/sched/pthread/pthread_condsignal.c @@ -30,6 +30,8 @@ #include #include +#include + #include "pthread/pthread.h" /**************************************************************************** @@ -41,10 +43,6 @@ * * Description: * A thread can signal on a condition variable. - * pthread_cond_signal shall unblock a thread currently blocked on a - * specified condition variable cond. We need own the mutex that threads - * calling pthread_cond_wait or pthread_cond_timedwait have associated - * with the condition variable during their wait. * * Input Parameters: * None @@ -68,11 +66,16 @@ int pthread_cond_signal(FAR pthread_cond_t *cond) } else { - if (cond->wait_count > 0) + int wcnt = atomic_read(COND_WAIT_COUNT(cond)); + + while (wcnt > 0) { - sinfo("Signalling...\n"); - cond->wait_count--; - ret = -nxsem_post(&cond->sem); + if (atomic_cmpxchg(COND_WAIT_COUNT(cond), &wcnt, wcnt - 1)) + { + sinfo("Signalling...\n"); + ret = -nxsem_post(&cond->sem); + break; + } } } diff --git a/sched/pthread/pthread_condwait.c b/sched/pthread/pthread_condwait.c index ca8f05511e4..731599db72e 100644 --- a/sched/pthread/pthread_condwait.c +++ b/sched/pthread/pthread_condwait.c @@ -32,6 +32,7 @@ #include #include +#include #include #include "pthread/pthread.h" @@ -88,7 +89,7 @@ int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex) sinfo("Give up mutex / take cond\n"); - cond->wait_count++; + atomic_fetch_add(COND_WAIT_COUNT(cond), 1); ret = pthread_mutex_breaklock(mutex, &nlocks); status = -nxsem_wait_uninterruptible(&cond->sem);