thr_join.c revision 78873
1202412Sbrueffer/* 2202412Sbrueffer * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 3202412Sbrueffer * All rights reserved. 4202412Sbrueffer * 5202412Sbrueffer * Redistribution and use in source and binary forms, with or without 6202412Sbrueffer * modification, are permitted provided that the following conditions 7202412Sbrueffer * are met: 8202412Sbrueffer * 1. Redistributions of source code must retain the above copyright 9202412Sbrueffer * notice, this list of conditions and the following disclaimer. 10202412Sbrueffer * 2. Redistributions in binary form must reproduce the above copyright 11202412Sbrueffer * notice, this list of conditions and the following disclaimer in the 12202412Sbrueffer * documentation and/or other materials provided with the distribution. 13202412Sbrueffer * 3. All advertising materials mentioning features or use of this software 14202412Sbrueffer * must display the following acknowledgement: 15202412Sbrueffer * This product includes software developed by John Birrell. 16202412Sbrueffer * 4. Neither the name of the author nor the names of any co-contributors 17202412Sbrueffer * may be used to endorse or promote products derived from this software 18202412Sbrueffer * without specific prior written permission. 19202412Sbrueffer * 20202412Sbrueffer * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21202412Sbrueffer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22202412Sbrueffer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23202412Sbrueffer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24202412Sbrueffer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25202412Sbrueffer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26202412Sbrueffer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27301407Slandonf * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28202412Sbrueffer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29202412Sbrueffer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30202412Sbrueffer * SUCH DAMAGE. 31202412Sbrueffer * 32202412Sbrueffer * $FreeBSD: head/lib/libkse/thread/thr_join.c 78873 2001-06-27 11:41:15Z jasone $ 33202412Sbrueffer */ 34202412Sbrueffer#include <errno.h> 35202412Sbrueffer#include <pthread.h> 36202412Sbrueffer#include "pthread_private.h" 37299097Sadrian 38202412Sbrueffer__weak_reference(_pthread_join, pthread_join); 39202412Sbrueffer 40202412Sbruefferint 41202412Sbrueffer_pthread_join(pthread_t pthread, void **thread_return) 42202412Sbrueffer{ 43202412Sbrueffer struct pthread *curthread = _get_curthread(); 44202412Sbrueffer int ret = 0; 45202412Sbrueffer pthread_t thread; 46202412Sbrueffer 47202412Sbrueffer _thread_enter_cancellation_point(); 48202412Sbrueffer 49202412Sbrueffer /* Check if the caller has specified an invalid thread: */ 50299097Sadrian if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) { 51299097Sadrian /* Invalid thread: */ 52299097Sadrian _thread_leave_cancellation_point(); 53299097Sadrian return(EINVAL); 54299097Sadrian } 55202412Sbrueffer 56299097Sadrian /* Check if the caller has specified itself: */ 57301589Strasz if (pthread == curthread) { 58301589Strasz /* Avoid a deadlock condition: */ 59202412Sbrueffer _thread_leave_cancellation_point(); 60202412Sbrueffer return(EDEADLK); 61202412Sbrueffer } 62202412Sbrueffer 63202412Sbrueffer /* 64202412Sbrueffer * Lock the garbage collector mutex to ensure that the garbage 65202412Sbrueffer * collector is not using the dead thread list. 66202412Sbrueffer */ 67202412Sbrueffer if (pthread_mutex_lock(&_gc_mutex) != 0) 68202412Sbrueffer PANIC("Cannot lock gc mutex"); 69202412Sbrueffer 70299097Sadrian /* 71299097Sadrian * Defer signals to protect the thread list from access 72202412Sbrueffer * by the signal handler: 73202412Sbrueffer */ 74202412Sbrueffer _thread_kern_sig_defer(); 75202412Sbrueffer 76202412Sbrueffer /* 77299097Sadrian * Unlock the garbage collector mutex, now that the garbage collector 78299097Sadrian * can't be run: 79299097Sadrian */ 80299097Sadrian if (pthread_mutex_unlock(&_gc_mutex) != 0) 81299097Sadrian PANIC("Cannot lock gc mutex"); 82202412Sbrueffer 83202412Sbrueffer /* 84202412Sbrueffer * Search for the specified thread in the list of active threads. This 85202412Sbrueffer * is done manually here rather than calling _find_thread() because 86299097Sadrian * the searches in _thread_list and _dead_list (as well as setting up 87267938Sbapt * join/detach state) have to be done atomically. 88202412Sbrueffer */ 89267938Sbapt TAILQ_FOREACH(thread, &_thread_list, tle) { 90299097Sadrian if (thread == pthread) 91301407Slandonf break; 92299097Sadrian } 93301407Slandonf if (thread == NULL) { 94 /* 95 * Search for the specified thread in the list of dead threads: 96 */ 97 TAILQ_FOREACH(thread, &_dead_list, dle) { 98 if (thread == pthread) 99 break; 100 } 101 } 102 103 /* Check if the thread was not found or has been detached: */ 104 if (thread == NULL || 105 ((pthread->attr.flags & PTHREAD_DETACHED) != 0)) { 106 /* Undefer and handle pending signals, yielding if necessary: */ 107 _thread_kern_sig_undefer(); 108 109 /* Return an error: */ 110 ret = ESRCH; 111 112 } else if (pthread->joiner != NULL) { 113 /* Undefer and handle pending signals, yielding if necessary: */ 114 _thread_kern_sig_undefer(); 115 116 /* Multiple joiners are not supported. */ 117 ret = ENOTSUP; 118 119 /* Check if the thread is not dead: */ 120 } else if (pthread->state != PS_DEAD) { 121 /* Set the running thread to be the joiner: */ 122 pthread->joiner = curthread; 123 124 /* Schedule the next thread: */ 125 _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); 126 127 /* 128 * The thread return value and error are set by the thread we're 129 * joining to when it exits or detaches: 130 */ 131 ret = curthread->error; 132 if ((ret == 0) && (thread_return != NULL)) 133 *thread_return = curthread->ret; 134 } else { 135 /* 136 * The thread exited (is dead) without being detached, and no 137 * thread has joined it. 138 */ 139 140 /* Check if the return value is required: */ 141 if (thread_return != NULL) { 142 /* Return the thread's return value: */ 143 *thread_return = pthread->ret; 144 } 145 146 /* Make the thread collectable by the garbage collector. */ 147 pthread->attr.flags |= PTHREAD_DETACHED; 148 149 /* Undefer and handle pending signals, yielding if necessary: */ 150 _thread_kern_sig_undefer(); 151 } 152 153 _thread_leave_cancellation_point(); 154 155 /* Return the completion status: */ 156 return (ret); 157} 158