• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * pthread_join.c
3  *
4  * Description:
5  * This translation unit implements functions related to thread
6  * synchronisation.
7  *
8  * --------------------------------------------------------------------------
9  *
10  *      Pthreads-win32 - POSIX Threads Library for Win32
11  *      Copyright(C) 1998 John E. Bossom
12  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
13  *
14  *      Contact Email: rpj@callisto.canberra.edu.au
15  *
16  *      The current list of contributors is contained
17  *      in the file CONTRIBUTORS included with the source
18  *      code distribution. The list can also be seen at the
19  *      following World Wide Web location:
20  *      http://sources.redhat.com/pthreads-win32/contributors.html
21  *
22  *      This library is free software; you can redistribute it and/or
23  *      modify it under the terms of the GNU Lesser General Public
24  *      License as published by the Free Software Foundation; either
25  *      version 2 of the License, or (at your option) any later version.
26  *
27  *      This library is distributed in the hope that it will be useful,
28  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30  *      Lesser General Public License for more details.
31  *
32  *      You should have received a copy of the GNU Lesser General Public
33  *      License along with this library in the file COPYING.LIB;
34  *      if not, write to the Free Software Foundation, Inc.,
35  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
36  */
37 
38 #include "pthread.h"
39 #include "implement.h"
40 
41 /*
42  * Not needed yet, but defining it should indicate clashes with build target
43  * environment that should be fixed.
44  */
45 #if !defined(WINCE)
46 #  include <signal.h>
47 #endif
48 
49 
50 int
pthread_join(pthread_t thread,void ** value_ptr)51 pthread_join (pthread_t thread, void **value_ptr)
52      /*
53       * ------------------------------------------------------
54       * DOCPUBLIC
55       *      This function waits for 'thread' to terminate and
56       *      returns the thread's exit value if 'value_ptr' is not
57       *      NULL. This also detaches the thread on successful
58       *      completion.
59       *
60       * PARAMETERS
61       *      thread
62       *              an instance of pthread_t
63       *
64       *      value_ptr
65       *              pointer to an instance of pointer to void
66       *
67       *
68       * DESCRIPTION
69       *      This function waits for 'thread' to terminate and
70       *      returns the thread's exit value if 'value_ptr' is not
71       *      NULL. This also detaches the thread on successful
72       *      completion.
73       *      NOTE:   detached threads cannot be joined or canceled
74       *
75       * RESULTS
76       *              0               'thread' has completed
77       *              EINVAL          thread is not a joinable thread,
78       *              ESRCH           no thread could be found with ID 'thread',
79       *              ENOENT          thread couldn't find it's own valid handle,
80       *              EDEADLK         attempt to join thread with self
81       *
82       * ------------------------------------------------------
83       */
84 {
85   int result;
86   pthread_t self;
87   ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
88   ptw32_mcs_local_node_t node;
89 
90   ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
91 
92   if (NULL == tp
93       || thread.x != tp->ptHandle.x)
94     {
95       result = ESRCH;
96     }
97   else if (PTHREAD_CREATE_DETACHED == tp->detachState)
98     {
99       result = EINVAL;
100     }
101   else
102     {
103       result = 0;
104     }
105 
106   ptw32_mcs_lock_release(&node);
107 
108   if (result == 0)
109     {
110       /*
111        * The target thread is joinable and can't be reused before we join it.
112        */
113       self = pthread_self();
114 
115       if (NULL == self.p)
116 	{
117 	  result = ENOENT;
118 	}
119       else if (pthread_equal (self, thread))
120 	{
121 	  result = EDEADLK;
122 	}
123       else
124 	{
125 	  /*
126 	   * Pthread_join is a cancelation point.
127 	   * If we are canceled then our target thread must not be
128 	   * detached (destroyed). This is guarranteed because
129 	   * pthreadCancelableWait will not return if we
130 	   * are canceled.
131 	   */
132 	  result = pthreadCancelableWait (tp->threadH);
133 
134 	  if (0 == result)
135 	    {
136 	      if (value_ptr != NULL)
137 		{
138 		  *value_ptr = tp->exitStatus;
139 		}
140 
141 	      /*
142 	       * The result of making multiple simultaneous calls to
143 	       * pthread_join() or pthread_detach() specifying the same
144 	       * target is undefined.
145 	       */
146 	      result = pthread_detach (thread);
147 	    }
148 	  else
149 	    {
150 	      result = ESRCH;
151 	    }
152 	}
153     }
154 
155   return (result);
156 
157 }				/* pthread_join */
158