thr_join.c revision 53812
113546Sjulian/* 213546Sjulian * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 313546Sjulian * All rights reserved. 413546Sjulian * 513546Sjulian * Redistribution and use in source and binary forms, with or without 613546Sjulian * modification, are permitted provided that the following conditions 713546Sjulian * are met: 813546Sjulian * 1. Redistributions of source code must retain the above copyright 913546Sjulian * notice, this list of conditions and the following disclaimer. 1013546Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1113546Sjulian * notice, this list of conditions and the following disclaimer in the 1213546Sjulian * documentation and/or other materials provided with the distribution. 1313546Sjulian * 3. All advertising materials mentioning features or use of this software 1413546Sjulian * must display the following acknowledgement: 1513546Sjulian * This product includes software developed by John Birrell. 1613546Sjulian * 4. Neither the name of the author nor the names of any co-contributors 1713546Sjulian * may be used to endorse or promote products derived from this software 1813546Sjulian * without specific prior written permission. 1913546Sjulian * 2013546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 2113546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2213546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2349439Sdeischen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2413546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2513546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2613546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2713546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2813546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2913546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3013546Sjulian * SUCH DAMAGE. 3113546Sjulian * 3250476Speter * $FreeBSD: head/lib/libkse/thread/thr_join.c 53812 1999-11-28 05:38:13Z alfred $ 3313546Sjulian */ 3413546Sjulian#include <errno.h> 3513546Sjulian#ifdef _THREAD_SAFE 3613546Sjulian#include <pthread.h> 3713546Sjulian#include "pthread_private.h" 3813546Sjulian 3913546Sjulianint 4013546Sjulianpthread_join(pthread_t pthread, void **thread_return) 4113546Sjulian{ 4235509Sjb int ret = 0; 4335509Sjb pthread_t pthread1 = NULL; 4453812Salfred 4553812Salfred _thread_enter_cancellation_point(); 4613546Sjulian 4735008Sjb /* Check if the caller has specified an invalid thread: */ 4853812Salfred if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) { 4935008Sjb /* Invalid thread: */ 5053812Salfred _thread_leave_cancellation_point(); 5135008Sjb return(EINVAL); 5253812Salfred } 5335008Sjb 5435008Sjb /* Check if the caller has specified itself: */ 5553812Salfred if (pthread == _thread_run) { 5635008Sjb /* Avoid a deadlock condition: */ 5753812Salfred _thread_leave_cancellation_point(); 5835008Sjb return(EDEADLK); 5953812Salfred } 6035008Sjb 6135509Sjb /* 6235509Sjb * Find the thread in the list of active threads or in the 6335509Sjb * list of dead threads: 6435509Sjb */ 6535509Sjb if (_find_thread(pthread) == 0 || 6635509Sjb _find_dead_thread(pthread) == 0) 6735509Sjb pthread1 = pthread; 6813546Sjulian 6935509Sjb if (pthread1 == NULL) 7022315Sjulian /* Return an error: */ 7135509Sjb ret = ESRCH; 7222315Sjulian 7313546Sjulian /* Check if this thread has been detached: */ 7435509Sjb else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) 7513546Sjulian /* Return an error: */ 7635509Sjb ret = ESRCH; 7735509Sjb 7813546Sjulian /* Check if the thread is not dead: */ 7913546Sjulian else if (pthread->state != PS_DEAD) { 8053812Salfred /* Clear the interrupted flag: */ 8153812Salfred _thread_run->interrupted = 0; 8253812Salfred 8353812Salfred /* 8453812Salfred * Protect against being context switched out while 8553812Salfred * adding this thread to the join queue. 8653812Salfred */ 8753812Salfred _thread_kern_sig_defer(); 8853812Salfred 8913546Sjulian /* Add the running thread to the join queue: */ 9048046Sjb TAILQ_INSERT_TAIL(&(pthread->join_queue), _thread_run, qe); 9113546Sjulian 9213546Sjulian /* Schedule the next thread: */ 9313546Sjulian _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); 9413546Sjulian 9553812Salfred if (_thread_run->interrupted != 0) 9653812Salfred TAILQ_REMOVE(&(pthread->join_queue), _thread_run, qe); 9753812Salfred 9853812Salfred _thread_kern_sig_undefer(); 9953812Salfred 10053812Salfred if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) { 10153812Salfred _thread_exit_cleanup(); 10253812Salfred pthread_exit(PTHREAD_CANCELED); 10353812Salfred } 10453812Salfred 10513546Sjulian /* Check if the thread is not detached: */ 10637146Sjb if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) { 10713546Sjulian /* Check if the return value is required: */ 10835509Sjb if (thread_return) 10913546Sjulian /* Return the thread's return value: */ 11013546Sjulian *thread_return = pthread->ret; 11137146Sjb } 11235509Sjb else 11313546Sjulian /* Return an error: */ 11435509Sjb ret = ESRCH; 11513546Sjulian 11635509Sjb /* Check if the return value is required: */ 11735509Sjb } else if (thread_return != NULL) 11835509Sjb /* Return the thread's return value: */ 11935509Sjb *thread_return = pthread->ret; 12013546Sjulian 12153812Salfred _thread_leave_cancellation_point(); 12253812Salfred 12313546Sjulian /* Return the completion status: */ 12435509Sjb return (ret); 12513546Sjulian} 12613546Sjulian#endif 127