Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pthread: remove enter_critical_section in pthread_barrier_wait #14626

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's create a new patch moving pthread_barrierwait.c to libc/pthread, since the new implementation doesn't call the kernel internal api.

{
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);
xiaoxiang781216 marked this conversation as resolved.
Show resolved Hide resolved
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);
}
Loading