(root)/
glibc-2.38/
htl/
pt-exit.c
       1  /* 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 <assert.h>
      20  #include <errno.h>
      21  #include <pthread.h>
      22  #include <stdlib.h>
      23  
      24  #include <pt-internal.h>
      25  #include <pthreadP.h>
      26  
      27  #include <atomic.h>
      28  
      29  
      30  /* Terminate the current thread and make STATUS available to any
      31     thread that might join it.  */
      32  void
      33  __pthread_exit (void *status)
      34  {
      35    struct __pthread *self = _pthread_self ();
      36    struct __pthread_cancelation_handler **handlers;
      37    int oldstate;
      38  
      39    /* Run any cancelation handlers.  According to POSIX, the
      40       cancellation cleanup handlers should be called with cancellation
      41       disabled.  */
      42    __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
      43  
      44    for (handlers = __pthread_get_cleanup_stack ();
      45         *handlers != NULL;
      46         *handlers = (*handlers)->__next)
      47      (*handlers)->__handler ((*handlers)->__arg);
      48  
      49    __pthread_setcancelstate (oldstate, &oldstate);
      50  
      51    /* Decrease the number of threads.  We use an atomic operation to
      52       make sure that only the last thread calls `exit'.  */
      53    if (atomic_fetch_add_relaxed (&__pthread_total, -1) == 1)
      54      /* We are the last thread.  */
      55      exit (0);
      56  
      57    /* Destroy any thread specific data.  */
      58    __pthread_destroy_specific (self);
      59  
      60    /* Note that after this point the process can be terminated at any
      61       point if another thread calls `pthread_exit' and happens to be
      62       the last thread.  */
      63  
      64    __pthread_mutex_lock (&self->state_lock);
      65  
      66    if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending)
      67      status = PTHREAD_CANCELED;
      68  
      69    switch (self->state)
      70      {
      71      default:
      72        assert (!"Consistency error: unexpected self->state");
      73        abort ();
      74        break;
      75  
      76      case PTHREAD_DETACHED:
      77        __pthread_mutex_unlock (&self->state_lock);
      78  
      79        break;
      80  
      81      case PTHREAD_JOINABLE:
      82        /* We need to stay around for a while since another thread
      83           might want to join us.  */
      84        self->state = PTHREAD_EXITED;
      85  
      86        /* We need to remember the exit status.  A thread joining us
      87           might ask for it.  */
      88        self->status = status;
      89  
      90        /* Broadcast the condition.  This will wake up threads that are
      91           waiting to join us.  */
      92        __pthread_cond_broadcast (&self->state_cond);
      93        __pthread_mutex_unlock (&self->state_lock);
      94  
      95        break;
      96      }
      97  
      98    /* Destroy any signal state.  */
      99    __pthread_sigstate_destroy (self);
     100  
     101    /* Self terminating requires TLS, so defer the release of the TCB until
     102       the thread structure is reused.  */
     103  
     104    /* Release kernel resources, including the kernel thread and the stack,
     105       and drop the self reference.  */
     106    __pthread_thread_terminate (self);
     107  
     108    /* NOTREACHED */
     109    abort ();
     110  }
     111  
     112  weak_alias (__pthread_exit, pthread_exit);