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