/**************************************************************************** * sched/pthread/pthread_completejoin.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include "sched/sched.h" #include "group/group.h" #include "pthread/pthread.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: pthread_completejoin * * Description: * A thread has been terminated -- either by returning, calling * pthread_exit(), or through pthread_cancel(). In any event, we must * complete any pending join events. * * Input Parameters: * exit_value * * Returned Value: * OK unless there is no join information associated with the pid. * This could happen, for example, if a task started with task_create() * calls pthread_exit(). * * Assumptions: * ****************************************************************************/ int pthread_completejoin(pid_t pid, FAR void *exit_value) { FAR struct tcb_s *tcb = nxsched_get_tcb(pid); FAR struct task_group_s *group = tcb->group; FAR struct task_join_s *join; FAR struct tcb_s *wtcb; FAR sq_entry_t *curr; FAR sq_entry_t *next; int ret = OK; sinfo("pid=%d exit_value=%p\n", pid, exit_value); nxrmutex_lock(&group->tg_joinlock); if (!sq_empty(&tcb->join_queue)) { sq_for_every_safe(&tcb->join_queue, curr, next) { /* Remove join entry from queue */ sq_rem(curr, &tcb->join_queue); /* Get tcb entry which waiting for the join */ wtcb = container_of(curr, struct tcb_s, join_entry); /* Save the return exit value in the thread structure. */ wtcb->join_val = exit_value; /* Notify waiters of the availability of the exit value */ nxsem_post(&wtcb->join_sem); } } else if (!sq_is_singular(&tcb->group->tg_members) && (tcb->flags & TCB_FLAG_DETACHED) == 0) { ret = pthread_findjoininfo(tcb->group, pid, &join, true); if (ret == OK) { join->exit_value = exit_value; } } tcb->flags |= TCB_FLAG_JOIN_COMPLETED; nxrmutex_unlock(&group->tg_joinlock); return ret; } /**************************************************************************** * Name: pthread_destroyjoin * * Description: * This is called from pthread_completejoin if the join info was * detached or from pthread_join when the last waiting thread has * received the thread exit info. * * Or it may never be called if the join info was never detached or if * no thread ever calls pthread_join. In case, there is a memory leak! * * Assumptions: * The caller holds tg_joinlock * ****************************************************************************/ void pthread_destroyjoin(FAR struct task_group_s *group, FAR struct task_join_s *pjoin) { sinfo("pjoin=%p\n", pjoin); /* Remove the join info from the set of joins */ nxrmutex_lock(&group->tg_joinlock); sq_rem(&pjoin->entry, &group->tg_joinqueue); nxrmutex_unlock(&group->tg_joinlock); /* And deallocate the pjoin structure */ kmm_free(pjoin); }