thr_join.c revision 76909
1252391Sray/* 2252391Sray * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 3252391Sray * All rights reserved. 4252391Sray * 5252391Sray * Redistribution and use in source and binary forms, with or without 6252391Sray * modification, are permitted provided that the following conditions 7252391Sray * are met: 8252391Sray * 1. Redistributions of source code must retain the above copyright 9252391Sray * notice, this list of conditions and the following disclaimer. 10252391Sray * 2. Redistributions in binary form must reproduce the above copyright 11252391Sray * notice, this list of conditions and the following disclaimer in the 12252391Sray * documentation and/or other materials provided with the distribution. 13252391Sray * 3. All advertising materials mentioning features or use of this software 14252391Sray * must display the following acknowledgement: 15252391Sray * This product includes software developed by John Birrell. 16252391Sray * 4. Neither the name of the author nor the names of any co-contributors 17252391Sray * may be used to endorse or promote products derived from this software 18252391Sray * without specific prior written permission. 19252391Sray * 20252391Sray * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21252391Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22252391Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23252391Sray * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24252391Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25252391Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26252391Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27252391Sray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28252391Sray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29252391Sray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30252391Sray * SUCH DAMAGE. 31252391Sray * 32252391Sray * $FreeBSD: head/lib/libkse/thread/thr_join.c 76909 2001-05-20 23:08:33Z jasone $ 33252391Sray */ 34252391Sray#include <errno.h> 35252391Sray#include <pthread.h> 36252391Sray#include "pthread_private.h" 37252391Sray 38252391Sray__weak_reference(_pthread_join, pthread_join); 39252391Sray 40252391Srayint 41252391Sray_pthread_join(pthread_t pthread, void **thread_return) 42252391Sray{ 43252391Sray struct pthread *curthread = _get_curthread(); 44252391Sray int ret = 0; 45252391Sray 46252391Sray _thread_enter_cancellation_point(); 47252391Sray 48254495Scognet /* Check if the caller has specified an invalid thread: */ 49252391Sray if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) { 50252391Sray /* Invalid thread: */ 51252391Sray _thread_leave_cancellation_point(); 52252391Sray return(EINVAL); 53252391Sray } 54252391Sray 55252391Sray /* Check if the caller has specified itself: */ 56252391Sray if (pthread == curthread) { 57252391Sray /* Avoid a deadlock condition: */ 58252391Sray _thread_leave_cancellation_point(); 59252391Sray return(EDEADLK); 60252391Sray } 61252391Sray 62252391Sray /* 63252391Sray * Find the thread in the list of active threads or in the 64252391Sray * list of dead threads: 65252391Sray */ 66252391Sray if ((_find_thread(pthread) != 0) && (_find_dead_thread(pthread) != 0)) 67252391Sray /* Return an error: */ 68252391Sray ret = ESRCH; 69252391Sray 70252391Sray /* Check if this thread has been detached: */ 71252391Sray else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) 72252391Sray /* Return an error: */ 73252391Sray ret = ESRCH; 74252391Sray 75252391Sray else if (pthread->joiner != NULL) 76252391Sray /* Multiple joiners are not supported. */ 77252391Sray ret = ENOTSUP; 78252391Sray 79252391Sray /* Check if the thread is not dead: */ 80252391Sray else if (pthread->state != PS_DEAD) { 81254495Scognet /* Set the running thread to be the joiner: */ 82252391Sray pthread->joiner = curthread; 83252391Sray 84252391Sray /* Schedule the next thread: */ 85252391Sray _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); 86252391Sray 87252391Sray /* 88252391Sray * The thread return value and error are set by the thread we're 89252391Sray * joining to when it exits or detaches: 90252391Sray */ 91252391Sray ret = curthread->error; 92252391Sray if ((ret == 0) && (thread_return != NULL)) 93252391Sray *thread_return = curthread->ret; 94252391Sray } else { 95252391Sray /* 96252391Sray * The thread exited (is dead) without being detached, and no 97252391Sray * thread has joined it. 98252391Sray */ 99252391Sray 100252391Sray /* Check if the return value is required: */ 101252391Sray if (thread_return != NULL) { 102252391Sray /* Return the thread's return value: */ 103252391Sray *thread_return = pthread->ret; 104252391Sray } 105 106 /* 107 * Make the thread collectable by the garbage collector. There 108 * is a race here with the garbage collector if multiple threads 109 * try to join the thread, but the behavior of multiple joiners 110 * is undefined, so don't bother protecting against the race. 111 */ 112 pthread->attr.flags |= PTHREAD_DETACHED; 113 } 114 115 _thread_leave_cancellation_point(); 116 117 /* Return the completion status: */ 118 return (ret); 119} 120