- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / third_party / pthreads-win32 / pthread_join.c
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
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 */