diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | pthread/pt-alloc.c | 22 | ||||
-rw-r--r-- | pthread/pt-create.c | 69 | ||||
-rw-r--r-- | pthread/pt-dealloc.c | 5 | ||||
-rw-r--r-- | pthread/pt-detach.c | 24 | ||||
-rw-r--r-- | pthread/pt-exit.c | 35 | ||||
-rw-r--r-- | pthread/pt-internal.h | 36 | ||||
-rw-r--r-- | pthread/pt-join.c | 18 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sigstate-destroy.c | 2 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sigstate-init.c | 18 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sysdep.c | 5 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sysdep.h | 3 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-alloc.c | 31 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-dealloc.c | 3 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-halt.c | 37 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-start.c | 4 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-terminate.c | 72 |
17 files changed, 194 insertions, 192 deletions
@@ -121,7 +121,7 @@ libpthread-routines := pt-attr pt-attr-destroy pt-attr-getdetachstate \ pt-thread-alloc \ pt-thread-dealloc \ pt-thread-start \ - pt-thread-halt \ + pt-thread-terminate \ pt-startup \ \ pt-getconcurrency pt-setconcurrency \ diff --git a/pthread/pt-alloc.c b/pthread/pt-alloc.c index 604d376..af544c5 100644 --- a/pthread/pt-alloc.c +++ b/pthread/pt-alloc.c @@ -47,7 +47,7 @@ struct __pthread *__pthread_free_threads; pthread_mutex_t __pthread_free_threads_lock; static inline error_t -initialize_pthread (struct __pthread *new, int recycling) +initialize_pthread (struct __pthread *new) { error_t err; @@ -55,6 +55,7 @@ initialize_pthread (struct __pthread *new, int recycling) if (err) return err; + new->nr_refs = 1; new->cancel_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; new->cancel_hook = NULL; new->cancel_hook_arg = NULL; @@ -62,14 +63,6 @@ initialize_pthread (struct __pthread *new, int recycling) new->cancel_type = PTHREAD_CANCEL_DEFERRED; new->cancel_pending = 0; - if (recycling) - /* Since we are recycling PTHREAD, we can assume certains things - about PTHREAD's current state and save some cycles by not - rewriting the memory. */ - return 0; - - new->stack = 0; - new->state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER; @@ -117,22 +110,15 @@ __pthread_alloc (struct __pthread **pthread) 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); - #ifdef ENABLE_TLS if (new->tcb) { /* Drop old values */ _dl_deallocate_tls (new->tcb, 1); - new->tcb = NULL; } #endif /* ENABLE_TLS */ - err = initialize_pthread (new, 1); + err = initialize_pthread (new); if (! err) *pthread = new; return err; @@ -143,7 +129,7 @@ __pthread_alloc (struct __pthread **pthread) if (new == NULL) return ENOMEM; - err = initialize_pthread (new, 0); + err = initialize_pthread (new); if (err) { free (new); diff --git a/pthread/pt-create.c b/pthread/pt-create.c index fd6800f..99d1b47 100644 --- a/pthread/pt-create.c +++ b/pthread/pt-create.c @@ -103,47 +103,30 @@ __pthread_create_internal (struct __pthread **thread, pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED ? PTHREAD_DETACHED : PTHREAD_JOINABLE); - /* If the user supplied a stack, it is not our responsibility to - setup a stack guard. */ if (setup->stackaddr) - pthread->guardsize = 0; - else - pthread->guardsize = (setup->guardsize <= setup->stacksize - ? setup->guardsize : setup->stacksize); - - /* Find a stack. There are several scenarios: if a detached thread - kills itself, it has no way to deallocate its stack, thus it - leaves PTHREAD->stack set to true. We try to reuse it here, - however, if the user supplied a stack or changes the size, - we cannot use the old one. Right now, we simply deallocate it. */ - if (pthread->stack) { - if ((setup->stackaddr && setup->stackaddr != pthread->stackaddr) - || (setup->stacksize != pthread->stacksize)) - { - __pthread_stack_dealloc (pthread->stackaddr, - pthread->stacksize); - pthread->stackaddr = setup->stackaddr; - pthread->stacksize = setup->stacksize; - } + pthread->stackaddr = setup->stackaddr; + + /* If the user supplied a stack, it is not our responsibility to + setup a stack guard. */ + pthread->guardsize = 0; + pthread->stack = 0; } else { - pthread->stacksize = setup->stacksize; - - if (setup->stackaddr) - pthread->stackaddr = setup->stackaddr; - else - { - err = __pthread_stack_alloc (&pthread->stackaddr, - setup->stacksize); - if (err) - goto failed_stack_alloc; - - pthread->stack = 1; - } + /* Allocate a stack. */ + err = __pthread_stack_alloc (&pthread->stackaddr, + setup->stacksize); + if (err) + goto failed_stack_alloc; + + pthread->guardsize = (setup->guardsize <= setup->stacksize + ? setup->guardsize : setup->stacksize); + pthread->stack = 1; } + pthread->stacksize = setup->stacksize; + /* Allocate the kernel thread and other required resources. */ err = __pthread_thread_alloc (pthread); if (err) @@ -169,6 +152,10 @@ __pthread_create_internal (struct __pthread **thread, if (err) goto failed_sigstate; + /* If the new thread is joinable, add a reference for the caller. */ + if (pthread->state == PTHREAD_JOINABLE) + pthread->nr_refs++; + /* Set the new thread's signal mask and set the pending signals to empty. POSIX says: "The signal mask shall be inherited from the creating thread. The set of signals pending for the new thread @@ -216,6 +203,10 @@ __pthread_create_internal (struct __pthread **thread, return 0; failed_starting: + /* If joinable, a reference was added for the caller. */ + if (pthread->state == PTHREAD_JOINABLE) + __pthread_dealloc (pthread); + __pthread_setid (pthread->thread, NULL); __atomic_dec (&__pthread_total); failed_sigstate: @@ -227,10 +218,14 @@ __pthread_create_internal (struct __pthread **thread, failed_thread_tls_alloc: #endif /* ENABLE_TLS */ __pthread_thread_dealloc (pthread); - __pthread_thread_halt (pthread); + __pthread_thread_terminate (pthread); + + /* __pthread_thread_terminate has taken care of deallocating the stack and + the thread structure. */ + goto failed; failed_thread_alloc: - __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); - pthread->stack = 0; + if (pthread->stack) + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); failed_stack_alloc: __pthread_dealloc (pthread); failed: diff --git a/pthread/pt-dealloc.c b/pthread/pt-dealloc.c index 92fe1fd..e324800 100644 --- a/pthread/pt-dealloc.c +++ b/pthread/pt-dealloc.c @@ -23,6 +23,8 @@ #include <pt-internal.h> +#include <bits/pt-atomic.h> + /* List of thread structures corresponding to free thread IDs. */ extern struct __pthread *__pthread_free_threads; extern pthread_mutex_t __pthread_free_threads_lock; @@ -34,6 +36,9 @@ __pthread_dealloc (struct __pthread *pthread) { assert (pthread->state != PTHREAD_TERMINATED); + if (! __atomic_dec_and_test (&pthread->nr_refs)) + return; + /* Withdraw this thread from the thread ID lookup table. */ __pthread_setid (pthread->thread, NULL); diff --git a/pthread/pt-detach.c b/pthread/pt-detach.c index 4ed8d2c..3431f1b 100644 --- a/pthread/pt-detach.c +++ b/pthread/pt-detach.c @@ -50,30 +50,16 @@ pthread_detach (pthread_t thread) consequences instead of blocking indefinitely. */ pthread_cond_broadcast (&pthread->state_cond); __pthread_mutex_unlock (&pthread->state_lock); + + __pthread_dealloc (pthread); break; case PTHREAD_EXITED: - /* THREAD has already exited. Make sure that nobody can - reference it anymore, and mark it as terminated. */ - __pthread_mutex_unlock (&pthread->state_lock); - /* Make sure the thread is not running before we remove its - stack. (The only possibility is that it is in a call to - __pthread_thread_halt itself, but that is enough to cause a - sigsegv.) */ - __pthread_thread_halt (pthread); - - /* Destroy the stack, the kernel resources and the control - block. */ - if (pthread->stack) - { - __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); - pthread->stack = 0; - } - - __pthread_thread_dealloc (pthread); - + /* THREAD has already exited. PTHREAD remained after the thread + exited in order to provide the exit status, but it turns out + it won't be needed. */ __pthread_dealloc (pthread); break; diff --git a/pthread/pt-exit.c b/pthread/pt-exit.c index 8468b80..ea61732 100644 --- a/pthread/pt-exit.c +++ b/pthread/pt-exit.c @@ -48,12 +48,6 @@ __pthread_exit (void *status) pthread_setcancelstate (oldstate, &oldstate); - /* Destory any thread specific data. */ - __pthread_destroy_specific (self); - - /* Destroy any signal state. */ - __pthread_sigstate_destroy (self); - /* Decrease the number of threads. We use an atomic operation to make sure that only the last thread calls `exit'. */ if (__atomic_dec_and_test (&__pthread_total)) @@ -77,15 +71,8 @@ __pthread_exit (void *status) break; case PTHREAD_DETACHED: - /* Make sure that nobody can reference this thread anymore, and - mark it as terminated. Our thread ID will immediately become - available for re-use. For obvious reasons, we cannot - deallocate our own stack and TLS. However, it will eventually be - reused when this thread structure is recycled. */ __pthread_mutex_unlock (&self->state_lock); - __pthread_dealloc (self); - break; case PTHREAD_JOINABLE: @@ -105,12 +92,22 @@ __pthread_exit (void *status) break; } - /* Note that after this point the resources used by this thread can - be freed at any moment if another thread joins or detaches us. - This means that before freeing any resources, such a thread - should make sure that this thread is really halted. */ - - __pthread_thread_halt (self); + /* Destroy any thread specific data. */ + __pthread_destroy_specific (self); + + /* Destroy any signal state. */ + __pthread_sigstate_destroy (self); + + /* Kernel resources may be used to implement synchronization objects, + release them late. */ + __pthread_thread_dealloc (self); + + /* Self terminating requires TLS, so defer the release of the TCB until + the thread structure is reused. */ + + /* Terminate the kernel thread, release the stack and drop the + self reference. */ + __pthread_thread_terminate (self); /* NOTREACHED */ abort (); diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index aeac009..9e0bbe9 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -72,6 +72,12 @@ struct __pthread /* Thread ID. */ pthread_t thread; + __atomic_t nr_refs; /* Detached threads have a self reference only, + while joinable threads have two references. + These are used to keep the structure valid at + thread destruction. Detaching/joining a thread + drops a reference. */ + /* Cancellation. */ pthread_mutex_t cancel_lock; /* Protect cancel_xxx members. */ void (*cancel_hook)(void *); /* Called to unblock a thread blocking @@ -208,12 +214,13 @@ extern int __pthread_create_internal (struct __pthread **__restrict pthread, void *__restrict arg); /* Allocate a new thread structure and a pthread thread ID (but not a - kernel thread or a stack). */ + kernel thread or a stack). THREAD has one reference. */ extern int __pthread_alloc (struct __pthread **thread); /* Deallocate the thread structure. This is the dual of - __pthread_alloc (N.B. it does not call __pthread_stack_alloc nor - __pthread_thread_halt). */ + __pthread_alloc (N.B. it does not call __pthread_stack_dealloc nor + __pthread_thread_terminate). THREAD loses one reference and is + released if the reference counter drops to 0. */ extern void __pthread_dealloc (struct __pthread *thread); @@ -238,22 +245,23 @@ extern int __pthread_setup (struct __pthread *__restrict thread, resources) for THREAD; it must not be placed on the run queue. */ extern int __pthread_thread_alloc (struct __pthread *thread); -/* Deallocate any kernel resources associated with THREAD. The thread - must not be running (that is, if __pthread_thread_start was called, - __pthread_thread_halt must first be called). This function will - never be called by a thread on itself. In the case that a thread - exits, its thread structure will be cached and cleaned up - later. */ +/* Deallocate any kernel resources associated with THREAD. */ extern void __pthread_thread_dealloc (struct __pthread *thread); /* Start THREAD making it eligible to run. */ extern int __pthread_thread_start (struct __pthread *thread); -/* Stop the kernel thread associated with THREAD. This function may - be called by two threads in parallel. In particular, by the thread - itself and another thread trying to join it. This function must be - implemented such that this is safe. */ -extern void __pthread_thread_halt (struct __pthread *thread); +/* Terminate the kernel thread associated with THREAD, and deallocate its + stack. In addition, THREAD loses one reference. + + This function can be called by any thread, including the target thread. + Since some resources that are destroyed along the kernel thread are + stored in thread-local variables, the conditions required for this + function to behave correctly are a bit unusual : as long as the target + thread hasn't been started, any thread can terminate it, but once it + has started, no other thread can terminate it, so that thread-local + variables created by that thread are correctly released. */ +extern void __pthread_thread_terminate (struct __pthread *thread); /* Called by a thread just before it calls the provided start diff --git a/pthread/pt-join.c b/pthread/pt-join.c index 417f433..122d130 100644 --- a/pthread/pt-join.c +++ b/pthread/pt-join.c @@ -50,27 +50,11 @@ pthread_join (pthread_t thread, void **status) switch (pthread->state) { case PTHREAD_EXITED: - __pthread_mutex_unlock (&pthread->state_lock); - /* THREAD has already exited. Salvage its exit status. */ if (status) *status = pthread->status; - /* Make sure the thread is not running before we remove its - stack. (The only possibility is that it is in a call to - __pthread_thread_halt itself, but that is enough to cause a - sigsegv.) */ - __pthread_thread_halt (pthread); - - /* Destroy the stack, the kernel resources and the control - block. */ - if (pthread->stack) - { - __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); - pthread->stack = 0; - } - - __pthread_thread_dealloc (pthread); + __pthread_mutex_unlock (&pthread->state_lock); __pthread_dealloc (pthread); break; diff --git a/sysdeps/mach/hurd/pt-sigstate-destroy.c b/sysdeps/mach/hurd/pt-sigstate-destroy.c index 8e56c5c..d5e28d2 100644 --- a/sysdeps/mach/hurd/pt-sigstate-destroy.c +++ b/sysdeps/mach/hurd/pt-sigstate-destroy.c @@ -24,5 +24,5 @@ void __pthread_sigstate_destroy (struct __pthread *thread) { - /* Nothing to do. */ + _hurd_sigstate_delete (thread->kernel_thread); } diff --git a/sysdeps/mach/hurd/pt-sigstate-init.c b/sysdeps/mach/hurd/pt-sigstate-init.c index dd56d90..500b4d4 100644 --- a/sysdeps/mach/hurd/pt-sigstate-init.c +++ b/sysdeps/mach/hurd/pt-sigstate-init.c @@ -23,6 +23,22 @@ error_t __pthread_sigstate_init (struct __pthread *thread) { - /* Nothing to do. */ + static int do_init_global; + + /* Mark the thread as a global signal receiver so as to conform with + the pthread semantics. However, we must be careful. The first + pthread created is the main thread, during libpthread initialization. + We must not mark it, otherwise the sigprocmask call in + __pthread_create would try to access _hurd_global_sigstate, + which is not initialized yet. When glibc runs _hurdsig_init later + on, the message thread is created, which must not be marked either. */ + if (do_init_global) + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (thread->kernel_thread); + _hurd_sigstate_set_global_rcv (ss); + } + else if (__pthread_num_threads >= 2) + do_init_global = 1; + return 0; } diff --git a/sysdeps/mach/hurd/pt-sysdep.c b/sysdeps/mach/hurd/pt-sysdep.c index 09f0dcb..fd71aba 100644 --- a/sysdeps/mach/hurd/pt-sysdep.c +++ b/sysdeps/mach/hurd/pt-sysdep.c @@ -65,6 +65,11 @@ init_routine (void) err = __pthread_create_internal (&thread, 0, 0, 0); assert_perror (err); + /* XXX The caller copies the command line arguments and the environment + to the new stack. Pretend it wasn't allocated so that it remains + valid if the main thread terminates. */ + thread->stack = 0; + ___pthread_self = thread; /* Decrease the number of threads, to take into account that the diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h index 89592f9..35912a3 100644 --- a/sysdeps/mach/hurd/pt-sysdep.h +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -30,8 +30,7 @@ #define PTHREAD_SYSDEP_MEMBERS \ thread_t kernel_thread; \ - mach_msg_header_t wakeupmsg; \ - int have_kernel_resources; + mach_msg_header_t wakeupmsg; extern __thread struct __pthread *___pthread_self; #define _pthread_self() \ diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c index 794f63e..77aa933 100644 --- a/sysdeps/mach/pt-thread-alloc.c +++ b/sysdeps/mach/pt-thread-alloc.c @@ -67,44 +67,29 @@ create_wakeupmsg (struct __pthread *thread) int __pthread_thread_alloc (struct __pthread *thread) { - if (thread->have_kernel_resources) - return 0; - + static int do_create; error_t err; err = create_wakeupmsg (thread); if (err) return err; - /* If there are no pthreads in the system then the pthread library - is bootstrapping and the main thread must create initialize - itself. The thread itself is already running, it just has not - pthread context. We want to reuse what it already has (including - the kernel thread), however, we must determine which thread is - the main thread. - - We cannot test if __pthread_total is one as we later decrement - before creating the signal thread. Currently, we check if - __pthread_num_threads--the number of allocated thread - structures--is one. __pthread_alloc has already been called in - __pthread_create_internal for us. This predicate could be improved, - however, it is sufficient for now. */ - if (__pthread_num_threads == 1) + if (! do_create) { assert (__pthread_total == 0); thread->kernel_thread = __mach_thread_self (); - /* We implicitly hold a reference drop the one that we just - acquired. */ - __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); + do_create = 1; } else { err = __thread_create (__mach_task_self (), &thread->kernel_thread); if (err) - return EAGAIN; + { + __mach_port_destroy (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } } - thread->have_kernel_resources = 1; - return 0; } diff --git a/sysdeps/mach/pt-thread-dealloc.c b/sysdeps/mach/pt-thread-dealloc.c index 55d8c4d..e977c3f 100644 --- a/sysdeps/mach/pt-thread-dealloc.c +++ b/sysdeps/mach/pt-thread-dealloc.c @@ -24,8 +24,7 @@ #include <pt-internal.h> /* Deallocate any kernel resources associated with THREAD except don't - halt the thread itself. On return, the thread will be marked as - dead and __pthread_halt will be called. */ + terminate the thread itself. */ void __pthread_thread_dealloc (struct __pthread *thread) { diff --git a/sysdeps/mach/pt-thread-halt.c b/sysdeps/mach/pt-thread-halt.c deleted file mode 100644 index 973cde1..0000000 --- a/sysdeps/mach/pt-thread-halt.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Deallocate the kernel thread resources. Mach version. - Copyright (C) 2000, 2002, 2005 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 - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include <assert.h> -#include <errno.h> -#include <mach.h> - -#include <pt-internal.h> - -/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is - true, the function must call __pthread_dealloc on THREAD. - - NB: The thread executing this function may be the thread which is - being halted, thus the last action should be halting the thread - itself. */ -void -__pthread_thread_halt (struct __pthread *thread) -{ - error_t err = __thread_terminate (thread->kernel_thread); - assert_perror (err); -} diff --git a/sysdeps/mach/pt-thread-start.c b/sysdeps/mach/pt-thread-start.c index 11b017f..df490ab 100644 --- a/sysdeps/mach/pt-thread-start.c +++ b/sysdeps/mach/pt-thread-start.c @@ -27,9 +27,10 @@ int __pthread_thread_start (struct __pthread *thread) { + static int do_start; error_t err; - if (__pthread_num_threads == 1) + if (! do_start) { /* The main thread is already running: do nothing. */ assert (__pthread_total == 1); @@ -38,6 +39,7 @@ __pthread_thread_start (struct __pthread *thread) __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); ok; })); + do_start = 1; } else { diff --git a/sysdeps/mach/pt-thread-terminate.c b/sysdeps/mach/pt-thread-terminate.c new file mode 100644 index 0000000..a89e505 --- /dev/null +++ b/sysdeps/mach/pt-thread-terminate.c @@ -0,0 +1,72 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 2000, 2002, 2005 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 + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> +#include <mach.h> + +#include <mach/mig_support.h> + +#include <pt-internal.h> + +/* Terminate the kernel thread associated with THREAD, and deallocate its + right reference and its stack. The function also drops a reference + on THREAD. */ +void +__pthread_thread_terminate (struct __pthread *thread) +{ + thread_t kernel_thread, self_ktid; + mach_port_t reply_port; + void *stackaddr; + size_t stacksize; + error_t err; + + kernel_thread = thread->kernel_thread; + + if (thread->stack) + { + stackaddr = thread->stackaddr; + stacksize = thread->stacksize; + } + else + { + stackaddr = NULL; + stacksize = 0; + } + + /* Each thread has its own reply port, allocated from MiG stub code calling + __mig_get_reply_port. Destroying it is a bit tricky because the calls + involved are also RPCs, causing the creation of a new reply port if + currently null. The __thread_terminate_release call is actually a one way + simple routine designed not to require a reply port. */ + self_ktid = __mach_thread_self (); + reply_port = (self_ktid == kernel_thread) + ? __mig_get_reply_port () + : MACH_PORT_NULL; + __mach_port_deallocate (__mach_task_self (), self_ktid); + + /* Finally done with the thread structure. */ + __pthread_dealloc (thread); + + /* Terminate and release all that's left. */ + err = __thread_terminate_release (kernel_thread, mach_task_self (), + kernel_thread, reply_port, + stackaddr, stacksize); + assert_perror (err); +} |