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

lib/pthread: Fix create/join race in thread lifecycle #57721

Closed
wants to merge 2 commits into from
Closed
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
1 change: 1 addition & 0 deletions kernel/include/ksched.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ void z_ready_thread(struct k_thread *thread);
void z_requeue_current(struct k_thread *curr);
struct k_thread *z_swap_next_thread(void);
void z_thread_abort(struct k_thread *thread);
void z_thread_wake_joiners(struct k_thread *thread);

static inline void z_pend_curr_unlocked(_wait_q_t *wait_q, k_timeout_t timeout)
{
Expand Down
7 changes: 7 additions & 0 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1729,6 +1729,13 @@ static void end_thread(struct k_thread *thread)
}
}

void z_thread_wake_joiners(struct k_thread *thread)
{
LOCKED(&sched_spinlock) {
unpend_all(&thread->join_queue);
}
}

void z_thread_abort(struct k_thread *thread)
{
k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
Expand Down
1 change: 0 additions & 1 deletion lib/posix/posix_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ struct posix_thread {
/* Pthread State */
enum pthread_state state;
pthread_mutex_t state_lock;
pthread_cond_t state_cond;
};

typedef struct pthread_key_obj {
Expand Down
21 changes: 7 additions & 14 deletions lib/posix/pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr,
k_spinlock_key_t key;
uint32_t pthread_num;
k_spinlock_key_t cancel_key;
pthread_condattr_t cond_attr;
struct posix_thread *thread;
const struct pthread_attr *attr = (const struct pthread_attr *)_attr;

Expand Down Expand Up @@ -207,7 +206,6 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr,
thread->state = attr->detachstate;
pthread_mutex_unlock(&thread->state_lock);

pthread_cond_init(&thread->state_cond, &cond_attr);
sys_slist_init(&thread->key_list);

*newthread = pthread_num;
Expand Down Expand Up @@ -274,7 +272,6 @@ int pthread_cancel(pthread_t pthread)
} else {
thread->retval = PTHREAD_CANCELED;
thread->state = PTHREAD_EXITED;
pthread_cond_broadcast(&thread->state_cond);
}
pthread_mutex_unlock(&thread->state_lock);

Expand Down Expand Up @@ -395,7 +392,6 @@ void pthread_exit(void *retval)
if (self->state == PTHREAD_JOINABLE) {
self->state = PTHREAD_EXITED;
self->retval = retval;
pthread_cond_broadcast(&self->state_cond);
} else {
self->state = PTHREAD_TERMINATED;
}
Expand All @@ -413,8 +409,6 @@ void pthread_exit(void *retval)
pthread_mutex_unlock(&self->state_lock);
pthread_mutex_destroy(&self->state_lock);

pthread_cond_destroy(&self->state_cond);

k_thread_abort((k_tid_t)self);
}

Expand All @@ -436,12 +430,14 @@ int pthread_join(pthread_t thread, void **status)
return ESRCH;
}

pthread_mutex_lock(&pthread->state_lock);

if (pthread->state == PTHREAD_JOINABLE) {
pthread_cond_wait(&pthread->state_cond, &pthread->state_lock);
if (pthread->state == PTHREAD_DETACHED) {
return EINVAL;
}

k_thread_join(&pthread->thread, K_FOREVER);

pthread_mutex_lock(&pthread->state_lock);

if (pthread->state == PTHREAD_EXITED) {
if (status != NULL) {
*status = pthread->retval;
Expand Down Expand Up @@ -479,10 +475,7 @@ int pthread_detach(pthread_t thread)
switch (pthread->state) {
case PTHREAD_JOINABLE:
pthread->state = PTHREAD_DETACHED;
/* Broadcast the condition.
* This will make threads waiting to join this thread continue.
*/
pthread_cond_broadcast(&pthread->state_cond);
z_thread_wake_joiners(&pthread->thread);
break;
case PTHREAD_EXITED:
pthread->state = PTHREAD_TERMINATED;
Expand Down