Blame htl/pt-dealloc.c

Packit 6c4009
/* Deallocate a thread structure.
Packit 6c4009
   Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library;  if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <pthread.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
Packit 6c4009
#include <pt-internal.h>
Packit 6c4009
Packit 6c4009
#include <atomic.h>
Packit 6c4009
Packit 6c4009
/* List of thread structures corresponding to free thread IDs.  */
Packit 6c4009
extern struct __pthread *__pthread_free_threads;
Packit 6c4009
extern pthread_mutex_t __pthread_free_threads_lock;
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Deallocate the thread structure for PTHREAD.  */
Packit 6c4009
void
Packit 6c4009
__pthread_dealloc (struct __pthread *pthread)
Packit 6c4009
{
Packit 6c4009
  assert (pthread->state != PTHREAD_TERMINATED);
Packit 6c4009
Packit 6c4009
  if (!atomic_decrement_and_test (&pthread->nr_refs))
Packit 6c4009
    return;
Packit 6c4009
Packit 6c4009
  /* Withdraw this thread from the thread ID lookup table.  */
Packit 6c4009
  __pthread_setid (pthread->thread, NULL);
Packit 6c4009
Packit 6c4009
  /* Mark the thread as terminated.  We broadcast the condition
Packit 6c4009
     here to prevent pthread_join from waiting for this thread to
Packit 6c4009
     exit where it was never really started.  Such a call to
Packit 6c4009
     pthread_join is completely bogus, but unfortunately allowed
Packit 6c4009
     by the standards.  */
Packit 6c4009
  __pthread_mutex_lock (&pthread->state_lock);
Packit 6c4009
  if (pthread->state != PTHREAD_EXITED)
Packit 6c4009
    __pthread_cond_broadcast (&pthread->state_cond);
Packit 6c4009
  __pthread_mutex_unlock (&pthread->state_lock);
Packit 6c4009
Packit 6c4009
  /* We do not actually deallocate the thread structure, but add it to
Packit 6c4009
     a list of re-usable thread structures.  */
Packit 6c4009
  __pthread_mutex_lock (&__pthread_free_threads_lock);
Packit 6c4009
  __pthread_enqueue (&__pthread_free_threads, pthread);
Packit 6c4009
  __pthread_mutex_unlock (&__pthread_free_threads_lock);
Packit 6c4009
Packit 6c4009
  /* Setting PTHREAD->STATE to PTHREAD_TERMINATED makes this TCB
Packit 6c4009
     available for reuse.  After that point, we can no longer assume
Packit 6c4009
     that PTHREAD is valid.
Packit 6c4009
Packit 6c4009
     Note that it is safe to not lock this update to PTHREAD->STATE:
Packit 6c4009
     the only way that it can now be accessed is in __pthread_alloc,
Packit 6c4009
     which reads this variable.  */
Packit 6c4009
  pthread->state = PTHREAD_TERMINATED;
Packit 6c4009
}