diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index e84c15a7730..fb6b3de1a82 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -103,7 +103,7 @@ #define TCB_FLAG_FREE_STACK (1 << 12) /* Bit 12: Free stack after exit */ #define TCB_FLAG_HEAP_CHECK (1 << 13) /* Bit 13: Heap check */ #define TCB_FLAG_HEAP_DUMP (1 << 14) /* Bit 14: Heap dump */ - /* Bits 15: Available */ +#define TCB_FLAG_DETACHED (1 << 15) /* Bit 15: Pthread detached */ /* Values for struct task_group tg_flags */ diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index cd9868a6714..6ff32920856 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -113,39 +113,6 @@ static inline void pthread_tcb_setup(FAR struct pthread_tcb_s *ptcb, ptcb->arg = arg; } -/**************************************************************************** - * Name: pthread_addjoininfo - * - * Description: - * Add a join structure to the local data set. - * - * Input Parameters: - * pjoin - * - * Returned Value: - * None - * - * Assumptions: - * The caller has provided protection from re-entrancy. - * - ****************************************************************************/ - -static inline void pthread_addjoininfo(FAR struct task_group_s *group, - FAR struct join_s *pjoin) -{ - pjoin->next = NULL; - if (!group->tg_jointail) - { - group->tg_joinhead = pjoin; - } - else - { - group->tg_jointail->next = pjoin; - } - - group->tg_jointail = pjoin; -} - /**************************************************************************** * Name: pthread_start * @@ -161,8 +128,6 @@ static void pthread_start(void) { FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)this_task(); - DEBUGASSERT(ptcb->joininfo != NULL); - /* The priority of this thread may have been boosted to avoid priority * inversion problems. If that is the case, then drop to the correct * execution priority. @@ -223,7 +188,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, pthread_startroutine_t entry, pthread_addr_t arg) { FAR struct pthread_tcb_s *ptcb; - FAR struct join_s *pjoin; struct sched_param param; int policy; int errcode; @@ -272,19 +236,9 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, } #endif - /* Allocate a detachable structure to support pthread_join logic */ - - pjoin = (FAR struct join_s *)kmm_zalloc(sizeof(struct join_s)); - if (!pjoin) - { - serr("ERROR: Failed to allocate join\n"); - errcode = ENOMEM; - goto errout_with_tcb; - } - if (attr->detachstate == PTHREAD_CREATE_DETACHED) { - pjoin->detached = true; + ptcb->cmn.flags |= TCB_FLAG_DETACHED; } if (attr->stackaddr) @@ -305,7 +259,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret != OK) { errcode = ENOMEM; - goto errout_with_join; + goto errout_with_tcb; } /* Initialize thread local storage */ @@ -314,7 +268,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret != OK) { errcode = -ret; - goto errout_with_join; + goto errout_with_tcb; } /* Should we use the priority and scheduler specified in the pthread @@ -332,7 +286,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret < 0) { errcode = -ret; - goto errout_with_join; + goto errout_with_tcb; } /* Get the scheduler policy for this thread */ @@ -341,7 +295,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (policy < 0) { errcode = -policy; - goto errout_with_join; + goto errout_with_tcb; } } else @@ -380,7 +334,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (repl_ticks < budget_ticks) { errcode = EINVAL; - goto errout_with_join; + goto errout_with_tcb; } /* Initialize the sporadic policy */ @@ -409,7 +363,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret < 0) { errcode = -ret; - goto errout_with_join; + goto errout_with_tcb; } } #endif @@ -421,7 +375,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret != OK) { errcode = EBUSY; - goto errout_with_join; + goto errout_with_tcb; } #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) @@ -431,7 +385,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret < 0) { errcode = ENOMEM; - goto errout_with_join; + goto errout_with_tcb; } #endif @@ -461,15 +415,11 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, if (ret < 0) { errcode = ENOMEM; - goto errout_with_join; + goto errout_with_tcb; } group_joined = true; - /* Attach the join info to the TCB. */ - - ptcb->joininfo = (FAR void *)pjoin; - /* Set the appropriate scheduling policy in the TCB */ ptcb->cmn.flags &= ~TCB_FLAG_POLICY_MASK; @@ -508,21 +458,10 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, #endif /* Get the assigned pid before we start the task (who knows what - * could happen to ptcb after this!). Copy this ID into the join structure - * as well. + * could happen to ptcb after this!). */ pid = ptcb->cmn.pid; - pjoin->thread = (pthread_t)pid; - - /* Initialize the semaphore in the join structure to zero. */ - - ret = nxsem_init(&pjoin->exit_sem, 0, 0); - - if (ret < 0) - { - ret = -ret; - } /* If the priority of the new pthread is lower than the priority of the * parent thread, then starting the pthread could result in both the @@ -533,18 +472,15 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, * so it has the same priority as the parent thread. */ - if (ret == OK) - { - FAR struct tcb_s *parent = this_task(); - DEBUGASSERT(parent != NULL); + FAR struct tcb_s *parent = this_task(); + DEBUGASSERT(parent != NULL); - if (ptcb->cmn.sched_priority < parent->sched_priority) + if (ptcb->cmn.sched_priority < parent->sched_priority) + { + ret = nxsched_set_priority(&ptcb->cmn, parent->sched_priority); + if (ret < 0) { - ret = nxsched_set_priority(&ptcb->cmn, parent->sched_priority); - if (ret < 0) - { - ret = -ret; - } + ret = -ret; } } @@ -553,9 +489,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, sched_lock(); if (ret == OK) { - nxmutex_lock(&ptcb->cmn.group->tg_joinlock); - pthread_addjoininfo(ptcb->cmn.group, pjoin); - nxmutex_unlock(&ptcb->cmn.group->tg_joinlock); nxtask_activate((FAR struct tcb_s *)ptcb); /* Return the thread information to the caller */ @@ -571,18 +504,13 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, { sched_unlock(); dq_rem((FAR dq_entry_t *)ptcb, &g_inactivetasks); - nxsem_destroy(&pjoin->exit_sem); errcode = EIO; - goto errout_with_join; + goto errout_with_tcb; } return ret; -errout_with_join: - kmm_free(pjoin); - ptcb->joininfo = NULL; - errout_with_tcb: /* Clear group binding */ diff --git a/sched/pthread/pthread_findjoininfo.c b/sched/pthread/pthread_findjoininfo.c index 181b480b762..f977a336428 100644 --- a/sched/pthread/pthread_findjoininfo.c +++ b/sched/pthread/pthread_findjoininfo.c @@ -26,16 +26,85 @@ #include #include +#include #include "group/group.h" #include "pthread/pthread.h" +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_createjoininfo + * + * Description: + * Allocate a detachable structure to support pthread_join logic and add + * the joininfo to the thread. + * + * Input Parameters: + * ptcb + * + * Returned Value: + * joininfo point. + * + * Assumptions: + * + ****************************************************************************/ + +static FAR struct join_s * +pthread_createjoininfo(FAR struct pthread_tcb_s *ptcb) +{ + FAR struct join_s *pjoin; + + /* Allocate a detachable structure to support pthread_join logic */ + + pjoin = (FAR struct join_s *)kmm_zalloc(sizeof(struct join_s)); + if (!pjoin) + { + serr("ERROR: Failed to allocate join\n"); + return NULL; + } + + pjoin->thread = (pthread_t)ptcb->cmn.pid; + + /* Initialize the semaphore in the join structure to zero. */ + + if (nxsem_init(&pjoin->exit_sem, 0, 0) < 0) + { + kmm_free(pjoin); + return NULL; + } + else + { + FAR struct task_group_s *group = ptcb->cmn.group; + + /* Attach the join info to the TCB. */ + + ptcb->joininfo = (FAR void *)pjoin; + + pjoin->next = NULL; + if (!group->tg_jointail) + { + group->tg_joinhead = pjoin; + } + else + { + group->tg_jointail->next = pjoin; + } + + group->tg_jointail = pjoin; + } + + return pjoin; +} + /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: thread_findjoininfo + * Name: pthread_findjoininfo * * Description: * Find a join structure in a local data set. @@ -67,5 +136,15 @@ FAR struct join_s *pthread_findjoininfo(FAR struct task_group_s *group, /* and return it */ + if (pjoin == NULL) + { + FAR struct tcb_s *tcb = nxsched_get_tcb((pthread_t)pid); + + if (tcb != NULL && (tcb->flags & TCB_FLAG_DETACHED) == 0) + { + pjoin = pthread_createjoininfo((FAR struct pthread_tcb_s *)tcb); + } + } + return pjoin; }