Skip to content

Commit

Permalink
pthread: remove enter_critical_section in pthread_barrier_wait
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
hujun260 authored and xiaoxiang781216 committed Nov 15, 2024
1 parent 370eefb commit 7ba0f11
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 42 deletions.
2 changes: 2 additions & 0 deletions include/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ struct pthread_barrier_s
{
sem_t sem;
unsigned int count;
unsigned int wait_count;
mutex_t mutex;
};

#ifndef __PTHREAD_BARRIER_T_DEFINED
Expand Down
2 changes: 2 additions & 0 deletions libs/libc/pthread/pthread_barrierinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ int pthread_barrier_init(FAR pthread_barrier_t *barrier,
{
sem_init(&barrier->sem, 0, 0);
barrier->count = count;
barrier->wait_count = 0;
nxmutex_init(&barrier->mutex);
}

return ret;
Expand Down
52 changes: 10 additions & 42 deletions sched/pthread/pthread_barrierwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,67 +82,35 @@

int pthread_barrier_wait(FAR pthread_barrier_t *barrier)
{
irqstate_t flags;
int semcount;
int ret;

if (barrier == NULL)
{
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 ((1 - semcount) >= (int)barrier->count)
nxmutex_lock(&barrier->mutex);

if ((barrier->wait_count + 1) >= barrier->count)
{
/* Free all of the waiting threads */

while (semcount < 0)
while (barrier->wait_count > 0)
{
barrier->wait_count--;
nxsem_post(&barrier->sem);
nxsem_get_value(&barrier->sem, &semcount);
}

/* Then return PTHREAD_BARRIER_SERIAL_THREAD to the final thread */

leave_critical_section(flags);
nxmutex_unlock(&barrier->mutex);

return PTHREAD_BARRIER_SERIAL_THREAD;
}

/* Otherwise, this thread must wait as well */

while ((ret = nxsem_wait(&barrier->sem)) != OK)
{
/* If the thread is awakened by a signal, just continue to wait */

if (ret != -EINTR)
{
/* If it is awakened by some other error, then there is a
* problem
*/

break;
}
}
barrier->wait_count++;

/* 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.
*/
nxmutex_unlock(&barrier->mutex);

leave_critical_section(flags);
return -ret;
return -nxsem_wait_uninterruptible(&barrier->sem);
}

0 comments on commit 7ba0f11

Please sign in to comment.