summaryrefslogtreecommitdiff
path: root/pthread/pt-alloc.c
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2008-08-16 13:13:07 +0000
committerThomas Schwinge <tschwinge@gnu.org>2009-04-07 23:57:46 +0200
commit437dc507644e3067cac5899b00b6eb074997cd1c (patch)
tree61d9f45aca6212b7896443ccec3cc35679e04121 /pthread/pt-alloc.c
parentbd70818a914257c32ca47623206632ed4a484802 (diff)
2008-08-16 Neal H. Walfield <neal@gnu.org>
* pthread/pt-alloc.c: Don't include <bits/atomic.h>. (__pthread_free_threads): Change to a struct __pthread *. (__pthread_free_threads_lock): New variable. (__pthread_alloc): When looking for a TCB to reuse, iterate over __pthread_free_threads taking the first for which the STATE field is PTHREAD_TERMINATED. When reusing a TCB, first call __pthread_thread_halt on it. * pthread/pt-dealloc.c: Don't include <bits/atomic.h>. (__pthread_free_threads): Change to a struct __pthread *. (__pthread_free_threads_lock): New declaration. (__pthread_dealloc): Enqueue PTHREAD on __PTHREAD_FREE_THREADS. Set PTHREAD->STATE to PTHREAD_TERMINATED after everything else. * pthread/pt-join.c (pthread_join): Call __pthread_thread_halt before destroying the thread. When destroying the thread, call __pthread_thread_dealloc on it. * pthread/pt-detach.c (pthread_detach): If destroying the thread, call __pthread_thread_halt before deallocating the stack. In this case, also call __pthread_thread_dealloc on the tcb. * pthread/pt-exit.c (pthread_exit): Call __pthread_dealloc only if the thread is detached and then as the last thing we do before calling __pthread_thread_halt. * pthread/pt-internal.h (__pthread_thread_halt): Remove argument NEED_DEALLOC. Update users. * sysdeps/mach/pt-thread-halt.c (__pthread_thread_halt): Remove argument need_dealloc. * sysdeps/mach/hurd/pt-sysdep.h (PTHREAD_SYSDEP_MEMBERS): Add field have_kernel_resources. * sysdeps/mach/hurd/pt-thread-alloc.c (__pthread_thread_alloc): If THREAD->HAVE_KERNEL_RESOURCES is true, just return. After allocating the resources, set THREAD->HAVE_KERNEL_RESOURCES to true.
Diffstat (limited to 'pthread/pt-alloc.c')
-rw-r--r--pthread/pt-alloc.c56
1 files changed, 28 insertions, 28 deletions
diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c
index 30dcede0..6af2da92 100644
--- a/pthread/pt-alloc.c
+++ b/pthread/pt-alloc.c
@@ -1,5 +1,5 @@
/* Allocate a new thread structure.
- Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2005, 2007, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,8 +25,6 @@
#include <pt-internal.h>
-#include <bits/atomic.h>
-
/* This braindamage is necessary because the standard says that some
of the threads functions "shall fail" if "No thread could be found
corresponding to that specified by the given thread ID." */
@@ -44,9 +42,9 @@ int __pthread_num_threads;
/* A lock for the table, and the other variables above. */
pthread_rwlock_t __pthread_threads_lock;
-
/* List of thread structures corresponding to free thread IDs. */
-__atomicptr_t __pthread_free_threads;
+struct __pthread *__pthread_free_threads;
+pthread_mutex_t __pthread_free_threads_lock;
static inline error_t
initialize_pthread (struct __pthread *new, int recycling)
@@ -94,33 +92,35 @@ __pthread_alloc (struct __pthread **pthread)
int max_threads;
int new_max_threads;
- /* Try to re-use a thread structure before creating a new one. */
- while ((new = (struct __pthread *)__pthread_free_threads))
+ pthread_mutex_lock (&__pthread_free_threads_lock);
+ for (new = __pthread_free_threads; new; new = new->next)
{
- if (__atomicptr_compare_and_swap (&__pthread_free_threads,
- new, new->next))
+ /* There is no need to take NEW->STATE_LOCK: if NEW is on this
+ list, then it is protected by __PTHREAD_FREE_THREADS_LOCK
+ except in __pthread_dealloc where after it is added to the
+ list (with the lock held), it drops the lock and then sets
+ NEW->STATE and immediately stops using NEW. */
+ if (new->state == PTHREAD_TERMINATED)
{
- /* Yes, we managed to get one. The thread number in the
- thread structure still refers to the correct slot. */
- err = initialize_pthread (new, 1);
- if (err)
- /* An error occured, however, we cannot just free NEW as
- there may be resources attached to it. We must return
- it to the free list. */
- while (1)
- {
- new->next = (struct __pthread *)__pthread_free_threads;
- if (__atomicptr_compare_and_swap (&__pthread_free_threads,
- new->next, new))
- break;
- }
-
- if (! err)
- *pthread = new;
-
- return err;
+ __pthread_dequeue (new);
+ break;
}
}
+ pthread_mutex_unlock (&__pthread_free_threads_lock);
+
+ if (new)
+ {
+ /* The thread may still be running. Make sure it is stopped.
+ If this is the case, then the thread is either at the end of
+ __pthread_dealloc or in __pthread_thread_halt. In both
+ cases, we are interrupt it. */
+ __pthread_thread_halt (new);
+
+ err = initialize_pthread (new, 1);
+ if (! err)
+ *pthread = new;
+ return err;
+ }
/* Allocate a new thread structure. */
new = malloc (sizeof (struct __pthread));