Home | History | Annotate | Download | only in pthreads-win32
      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 (at) 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 */
    158