Blame sysdeps/mach/htl/pt-thread-terminate.c

Packit 6c4009
/* Deallocate the kernel thread resources.  Mach version.
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 <errno.h>
Packit 6c4009
#include <mach.h>
Packit 6c4009
Packit 6c4009
#include <mach/mig_support.h>
Packit 6c4009
Packit 6c4009
#include <pt-internal.h>
Packit 6c4009
Packit 6c4009
/* Terminate the kernel thread associated with THREAD, and deallocate its
Packit 6c4009
   right reference and its stack.  The function also drops a reference
Packit 6c4009
   on THREAD.  */
Packit 6c4009
void
Packit 6c4009
__pthread_thread_terminate (struct __pthread *thread)
Packit 6c4009
{
Packit 6c4009
  thread_t kernel_thread, self_ktid;
Packit 6c4009
  mach_port_t wakeup_port, reply_port;
Packit 6c4009
  void *stackaddr;
Packit 6c4009
  size_t stacksize;
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  kernel_thread = thread->kernel_thread;
Packit 6c4009
Packit 6c4009
  if (thread->stack)
Packit 6c4009
    {
Packit 6c4009
      stackaddr = thread->stackaddr;
Packit 6c4009
      stacksize = ((thread->guardsize + __vm_page_size - 1)
Packit 6c4009
		   / __vm_page_size) * __vm_page_size + thread->stacksize;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      stackaddr = NULL;
Packit 6c4009
      stacksize = 0;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  wakeup_port = thread->wakeupmsg.msgh_remote_port;
Packit 6c4009
Packit 6c4009
  /* Each thread has its own reply port, allocated from MiG stub code calling
Packit 6c4009
     __mig_get_reply_port.  Destroying it is a bit tricky because the calls
Packit 6c4009
     involved are also RPCs, causing the creation of a new reply port if
Packit 6c4009
     currently null. The __thread_terminate_release call is actually a one way
Packit 6c4009
     simple routine designed not to require a reply port.  */
Packit 6c4009
  self_ktid = __mach_thread_self ();
Packit 6c4009
  reply_port = (self_ktid == kernel_thread)
Packit 6c4009
      ? __mig_get_reply_port () : MACH_PORT_NULL;
Packit 6c4009
  __mach_port_deallocate (__mach_task_self (), self_ktid);
Packit 6c4009
Packit 6c4009
  /* Finally done with the thread structure.  */
Packit 6c4009
  __pthread_dealloc (thread);
Packit 6c4009
Packit 6c4009
  /* The wake up port is now no longer needed.  */
Packit 6c4009
  __mach_port_destroy (__mach_task_self (), wakeup_port);
Packit 6c4009
Packit 6c4009
  /* Terminate and release all that's left.  */
Packit 6c4009
  err = __thread_terminate_release (kernel_thread, mach_task_self (),
Packit 6c4009
				    kernel_thread, reply_port,
Packit 6c4009
				    (vm_address_t) stackaddr, stacksize);
Packit 6c4009
Packit 6c4009
  /* The kernel does not support it yet.  Leak but at least terminate
Packit 6c4009
     correctly.  */
Packit 6c4009
  err = __thread_terminate (kernel_thread);
Packit 6c4009
Packit 6c4009
  /* We are out of luck.  */
Packit 6c4009
  assert_perror (err);
Packit 6c4009
}