/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "pthreadP.h"
#include <hp-timing.h>
#include <ldsodefs.h>
#include <atomic.h>
#include <libc-internal.h>
#include <resolv.h>
#include <kernel-features.h>
#include <shlib-compat.h>
#include <stap-probe.h>
/* Local function to start thread and handle cleanup. */
static int start_thread (void *arg);
/* Nozero if debugging mode is enabled. */
int __pthread_debug;
/* Globally enabled events. */
static td_thr_events_t __nptl_threads_events __attribute_used__;
/* Pointer to descriptor with the last event. */
static struct pthread *__nptl_last_event __attribute_used__;
/* Number of threads running. */
unsigned int __nptl_nthreads = 1;
/* Code to allocate and deallocate a stack. */
#include "allocatestack.c"
/* Code to create the thread. */
#include <createthread.c>
struct pthread *
internal_function
__find_in_stack_list (pd)
struct pthread *pd;
{
list_t *entry;
struct pthread *result = NULL;
lll_lock (stack_cache_lock, LLL_PRIVATE);
list_for_each (entry, &stack_used)
{
struct pthread *curp;
curp = list_entry (entry, struct pthread, list);
if (curp == pd)
{
result = curp;
break;
}
}
if (result == NULL)
list_for_each (entry, &__stack_user)
{
struct pthread *curp;
curp = list_entry (entry, struct pthread, list);
if (curp == pd)
{
result = curp;
break;
}
}
lll_unlock (stack_cache_lock, LLL_PRIVATE);
return result;
}
/* Deallocate POSIX thread-local-storage. */
void
attribute_hidden
__nptl_deallocate_tsd (void)
{
struct pthread *self = THREAD_SELF;
/* Maybe no data was ever allocated. This happens often so we have
a flag for this. */
if (THREAD_GETMEM (self, specific_used))
{
size_t round;
size_t cnt;
round = 0;
do
{
size_t idx;
/* So far no new nonzero data entry. */
THREAD_SETMEM (self, specific_used, false);
for (cnt = idx = 0; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt)
{
struct pthread_key_data *level2;
level2 = THREAD_GETMEM_NC (self, specific, cnt);
if (level2 != NULL)
{
size_t inner;
for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE;
++inner, ++idx)
{
void *data = level2[inner].data;