about summary refs log tree commit diff
path: root/sysdeps/mach/htl/pt-thread-terminate.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/htl/pt-thread-terminate.c')
-rw-r--r--sysdeps/mach/htl/pt-thread-terminate.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/sysdeps/mach/htl/pt-thread-terminate.c b/sysdeps/mach/htl/pt-thread-terminate.c
new file mode 100644
index 0000000000..418fb400f5
--- /dev/null
+++ b/sysdeps/mach/htl/pt-thread-terminate.c
@@ -0,0 +1,82 @@
+/* Deallocate the kernel thread resources.  Mach version.
+   Copyright (C) 2000-2018 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, see <http://www.gnu.org/licenses/>.  */
+
+#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 wakeup_port, reply_port;
+  void *stackaddr;
+  size_t stacksize;
+  error_t err;
+
+  kernel_thread = thread->kernel_thread;
+
+  if (thread->stack)
+    {
+      stackaddr = thread->stackaddr;
+      stacksize = ((thread->guardsize + __vm_page_size - 1)
+		   / __vm_page_size) * __vm_page_size + thread->stacksize;
+    }
+  else
+    {
+      stackaddr = NULL;
+      stacksize = 0;
+    }
+
+  wakeup_port = thread->wakeupmsg.msgh_remote_port;
+
+  /* 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);
+
+  /* The wake up port is now no longer needed.  */
+  __mach_port_destroy (__mach_task_self (), wakeup_port);
+
+  /* Terminate and release all that's left.  */
+  err = __thread_terminate_release (kernel_thread, mach_task_self (),
+				    kernel_thread, reply_port,
+				    (vm_address_t) stackaddr, stacksize);
+
+  /* The kernel does not support it yet.  Leak but at least terminate
+     correctly.  */
+  err = __thread_terminate (kernel_thread);
+
+  /* We are out of luck.  */
+  assert_perror (err);
+}