mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 06:18:40 +08:00
pthread: remove enter_critical_section in pthread_barrier_wait
reason: We decouple semcount from business logic by using an independent counting variable, which allows us to remove critical sections in many cases. Signed-off-by: hujun5 <hujun5@xiaomi.com>
This commit is contained in:
parent
370eefb491
commit
7ba0f11d70
3 changed files with 14 additions and 42 deletions
|
@ -368,6 +368,8 @@ struct pthread_barrier_s
|
||||||
{
|
{
|
||||||
sem_t sem;
|
sem_t sem;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
unsigned int wait_count;
|
||||||
|
mutex_t mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef __PTHREAD_BARRIER_T_DEFINED
|
#ifndef __PTHREAD_BARRIER_T_DEFINED
|
||||||
|
|
|
@ -87,6 +87,8 @@ int pthread_barrier_init(FAR pthread_barrier_t *barrier,
|
||||||
{
|
{
|
||||||
sem_init(&barrier->sem, 0, 0);
|
sem_init(&barrier->sem, 0, 0);
|
||||||
barrier->count = count;
|
barrier->count = count;
|
||||||
|
barrier->wait_count = 0;
|
||||||
|
nxmutex_init(&barrier->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -82,67 +82,35 @@
|
||||||
|
|
||||||
int pthread_barrier_wait(FAR pthread_barrier_t *barrier)
|
int pthread_barrier_wait(FAR pthread_barrier_t *barrier)
|
||||||
{
|
{
|
||||||
irqstate_t flags;
|
|
||||||
int semcount;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (barrier == NULL)
|
if (barrier == NULL)
|
||||||
{
|
{
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable pre-emption throughout the following */
|
|
||||||
|
|
||||||
flags = enter_critical_section();
|
|
||||||
|
|
||||||
/* Find out how many threads are already waiting at the barrier */
|
|
||||||
|
|
||||||
ret = nxsem_get_value(&barrier->sem, &semcount);
|
|
||||||
if (ret != OK)
|
|
||||||
{
|
|
||||||
leave_critical_section(flags);
|
|
||||||
return -ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the number of waiters would be equal to the count, then we are done */
|
/* If the number of waiters would be equal to the count, then we are done */
|
||||||
|
|
||||||
if ((1 - semcount) >= (int)barrier->count)
|
nxmutex_lock(&barrier->mutex);
|
||||||
|
|
||||||
|
if ((barrier->wait_count + 1) >= barrier->count)
|
||||||
{
|
{
|
||||||
/* Free all of the waiting threads */
|
/* Free all of the waiting threads */
|
||||||
|
|
||||||
while (semcount < 0)
|
while (barrier->wait_count > 0)
|
||||||
{
|
{
|
||||||
|
barrier->wait_count--;
|
||||||
nxsem_post(&barrier->sem);
|
nxsem_post(&barrier->sem);
|
||||||
nxsem_get_value(&barrier->sem, &semcount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then return PTHREAD_BARRIER_SERIAL_THREAD to the final thread */
|
/* Then return PTHREAD_BARRIER_SERIAL_THREAD to the final thread */
|
||||||
|
|
||||||
leave_critical_section(flags);
|
nxmutex_unlock(&barrier->mutex);
|
||||||
|
|
||||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, this thread must wait as well */
|
barrier->wait_count++;
|
||||||
|
|
||||||
while ((ret = nxsem_wait(&barrier->sem)) != OK)
|
nxmutex_unlock(&barrier->mutex);
|
||||||
{
|
|
||||||
/* If the thread is awakened by a signal, just continue to wait */
|
|
||||||
|
|
||||||
if (ret != -EINTR)
|
return -nxsem_wait_uninterruptible(&barrier->sem);
|
||||||
{
|
|
||||||
/* If it is awakened by some other error, then there is a
|
|
||||||
* problem
|
|
||||||
*/
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We will only get here when we are one of the N-1 threads that were
|
|
||||||
* waiting for the final thread at the barrier. We just need to return
|
|
||||||
* zero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
return -ret;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue