(root)/
glibc-2.38/
htl/
pt-join.c
       1  /* Wait for thread termination.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library;  if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <pthread.h>
      21  #include <stddef.h>
      22  
      23  #include <pt-internal.h>
      24  
      25  /* Make calling thread wait for termination of thread THREAD.  Return
      26     the exit status of the thread in *STATUS.  */
      27  static int
      28  __pthread_join_common (pthread_t thread, void **status, int try,
      29  		       clockid_t clockid,
      30  		       const struct timespec *abstime)
      31  {
      32    struct __pthread *pthread;
      33    int err = 0;
      34  
      35    /* Lookup the thread structure for THREAD.  */
      36    pthread = __pthread_getid (thread);
      37    if (pthread == NULL)
      38      return ESRCH;
      39  
      40    if (pthread == _pthread_self ())
      41      return EDEADLK;
      42  
      43    __pthread_mutex_lock (&pthread->state_lock);
      44  
      45    if (try == 0)
      46      {
      47        pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock,
      48  			    &pthread->state_lock);
      49  
      50        /* Rely on pthread_cond_wait being a cancellation point to make
      51  	 pthread_join one too.  */
      52        while (pthread->state == PTHREAD_JOINABLE && err != ETIMEDOUT)
      53  	err = __pthread_cond_clockwait (&pthread->state_cond,
      54  					&pthread->state_lock,
      55  					clockid, abstime);
      56  
      57        pthread_cleanup_pop (0);
      58      }
      59  
      60    switch (pthread->state)
      61      {
      62      case PTHREAD_JOINABLE:
      63        __pthread_mutex_unlock (&pthread->state_lock);
      64        if (err != ETIMEDOUT)
      65  	err = EBUSY;
      66        break;
      67  
      68      case PTHREAD_EXITED:
      69        /* THREAD has already exited.  Salvage its exit status.  */
      70        if (status != NULL)
      71  	*status = pthread->status;
      72  
      73        __pthread_mutex_unlock (&pthread->state_lock);
      74  
      75        __pthread_dealloc (pthread);
      76        break;
      77  
      78      default:
      79        /* Thou shalt not join non-joinable threads!  */
      80        __pthread_mutex_unlock (&pthread->state_lock);
      81        err = EINVAL;
      82        break;
      83      }
      84  
      85    return err;
      86  }
      87  
      88  int
      89  __pthread_join (pthread_t thread, void **status)
      90  {
      91    return __pthread_join_common (thread, status, 0, CLOCK_REALTIME, NULL);
      92  }
      93  weak_alias (__pthread_join, pthread_join);
      94  
      95  int
      96  __pthread_tryjoin_np (pthread_t thread, void **status)
      97  {
      98    return __pthread_join_common (thread, status, 1, CLOCK_REALTIME, NULL);
      99  }
     100  weak_alias (__pthread_tryjoin_np, pthread_tryjoin_np);
     101  
     102  int
     103  __pthread_timedjoin_np (pthread_t thread, void **status,
     104  			const struct timespec *abstime)
     105  {
     106    return __pthread_join_common (thread, status, 0, CLOCK_REALTIME, abstime);
     107  }
     108  weak_alias (__pthread_timedjoin_np, pthread_timedjoin_np);
     109  
     110  int
     111  __pthread_clockjoin_np (pthread_t thread, void **status,
     112  			clockid_t clockid,
     113  			const struct timespec *abstime)
     114  {
     115    return __pthread_join_common (thread, status, 0, clockid, abstime);
     116  }
     117  weak_alias (__pthread_clockjoin_np, pthread_clockjoin_np);