summaryrefslogtreecommitdiff
path: root/sysdeps/mach/htl
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/htl')
-rw-r--r--sysdeps/mach/htl/Implies1
-rw-r--r--sysdeps/mach/htl/bits/spin-lock-inline.h87
-rw-r--r--sysdeps/mach/htl/bits/types/__pthread_spinlock_t.h34
-rw-r--r--sysdeps/mach/htl/pt-block.c38
-rw-r--r--sysdeps/mach/htl/pt-spin.c31
-rw-r--r--sysdeps/mach/htl/pt-stack-alloc.c67
-rw-r--r--sysdeps/mach/htl/pt-thread-alloc.c94
-rw-r--r--sysdeps/mach/htl/pt-thread-start.c53
-rw-r--r--sysdeps/mach/htl/pt-thread-terminate.c82
-rw-r--r--sysdeps/mach/htl/pt-timedblock.c65
-rw-r--r--sysdeps/mach/htl/pt-wakeup.c37
11 files changed, 589 insertions, 0 deletions
diff --git a/sysdeps/mach/htl/Implies b/sysdeps/mach/htl/Implies
new file mode 100644
index 0000000000..5215f33d98
--- /dev/null
+++ b/sysdeps/mach/htl/Implies
@@ -0,0 +1 @@
+htl
diff --git a/sysdeps/mach/htl/bits/spin-lock-inline.h b/sysdeps/mach/htl/bits/spin-lock-inline.h
new file mode 100644
index 0000000000..695c6dccde
--- /dev/null
+++ b/sysdeps/mach/htl/bits/spin-lock-inline.h
@@ -0,0 +1,87 @@
+/* Definitions of user-visible names for spin locks.
+ Copyright (C) 1994-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 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/>. */
+
+#ifndef _BITS_SPIN_LOCK_INLINE_H
+#define _BITS_SPIN_LOCK_INLINE_H 1
+
+#include <features.h>
+#include <bits/types/__pthread_spinlock_t.h>
+#include <lock-intern.h> /* This does all the work. */
+
+__BEGIN_DECLS
+
+#if defined __USE_EXTERN_INLINES || defined _FORCE_INLINES
+
+# ifndef __EBUSY
+# include <errno.h>
+# define __EBUSY EBUSY
+# endif
+
+# ifndef __PT_SPIN_INLINE
+# define __PT_SPIN_INLINE __extern_inline
+# endif
+
+__PT_SPIN_INLINE int __pthread_spin_destroy (__pthread_spinlock_t *__lock);
+
+__PT_SPIN_INLINE int
+__pthread_spin_destroy (__pthread_spinlock_t *__lock)
+{
+ return 0;
+}
+
+__PT_SPIN_INLINE int __pthread_spin_init (__pthread_spinlock_t *__lock,
+ int __pshared);
+
+__PT_SPIN_INLINE int
+__pthread_spin_init (__pthread_spinlock_t *__lock, int __pshared)
+{
+ *__lock = __PTHREAD_SPIN_LOCK_INITIALIZER;
+ return 0;
+}
+
+__PT_SPIN_INLINE int __pthread_spin_trylock (__pthread_spinlock_t *__lock);
+
+__PT_SPIN_INLINE int
+__pthread_spin_trylock (__pthread_spinlock_t *__lock)
+{
+ return __spin_try_lock ((__spin_lock_t *) __lock) ? 0 : __EBUSY;
+}
+
+__PT_SPIN_INLINE int __pthread_spin_lock (__pthread_spinlock_t *__lock);
+
+__PT_SPIN_INLINE int
+__pthread_spin_lock (__pthread_spinlock_t *__lock)
+{
+ __spin_lock ((__spin_lock_t *) __lock);
+ return 0;
+}
+
+__PT_SPIN_INLINE int __pthread_spin_unlock (__pthread_spinlock_t *__lock);
+
+__PT_SPIN_INLINE int
+__pthread_spin_unlock (__pthread_spinlock_t *__lock)
+{
+ __spin_unlock ((__spin_lock_t *) __lock);
+ return 0;
+}
+
+#endif /* Use extern inlines or force inlines. */
+
+__END_DECLS
+
+#endif /* bits/types/__pthread_spinlock_t.h */
diff --git a/sysdeps/mach/htl/bits/types/__pthread_spinlock_t.h b/sysdeps/mach/htl/bits/types/__pthread_spinlock_t.h
new file mode 100644
index 0000000000..038e2b429c
--- /dev/null
+++ b/sysdeps/mach/htl/bits/types/__pthread_spinlock_t.h
@@ -0,0 +1,34 @@
+/* Definitions of user-visible names for spin locks.
+ Copyright (C) 1994-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 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/>. */
+
+#ifndef _BITS_TYPES___PTHREAD_SPINLOCK_T_H
+#define _BITS_TYPES___PTHREAD_SPINLOCK_T_H 1
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+/* The type of a spin lock object. */
+typedef volatile int __pthread_spinlock_t;
+
+/* Initializer for a spin lock object. */
+#define __PTHREAD_SPIN_LOCK_INITIALIZER 0
+
+__END_DECLS
+
+#endif /* bits/types/__pthread_spinlock_t.h */
diff --git a/sysdeps/mach/htl/pt-block.c b/sysdeps/mach/htl/pt-block.c
new file mode 100644
index 0000000000..f62134c895
--- /dev/null
+++ b/sysdeps/mach/htl/pt-block.c
@@ -0,0 +1,38 @@
+/* Block a thread. 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 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 <assert.h>
+#include <errno.h>
+
+#include <mach.h>
+#include <mach/message.h>
+
+#include <pt-internal.h>
+
+/* Block THREAD. */
+void
+__pthread_block (struct __pthread *thread)
+{
+ mach_msg_header_t msg;
+ error_t err;
+
+ err = __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg,
+ thread->wakeupmsg.msgh_remote_port,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ assert_perror (err);
+}
diff --git a/sysdeps/mach/htl/pt-spin.c b/sysdeps/mach/htl/pt-spin.c
new file mode 100644
index 0000000000..2b0b3c1175
--- /dev/null
+++ b/sysdeps/mach/htl/pt-spin.c
@@ -0,0 +1,31 @@
+/* Spin locks. Mach version.
+ Copyright (C) 2002-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 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 <machine-lock.h>
+
+/* In glibc. */
+extern void __spin_lock_solid (__spin_lock_t *lock);
+
+/* Lock the spin lock object LOCK. If the lock is held by another
+ thread spin until it becomes available. */
+int
+_pthread_spin_lock (__spin_lock_t *lock)
+{
+ __spin_lock_solid (lock);
+ return 0;
+}
diff --git a/sysdeps/mach/htl/pt-stack-alloc.c b/sysdeps/mach/htl/pt-stack-alloc.c
new file mode 100644
index 0000000000..dc31ab745a
--- /dev/null
+++ b/sysdeps/mach/htl/pt-stack-alloc.c
@@ -0,0 +1,67 @@
+/* Allocate a new stack. 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 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 <errno.h>
+
+#include <mach.h>
+#include <mach/machine/vm_param.h>
+
+#include <pt-internal.h>
+
+/* The next address to use for stack allocation. */
+static vm_address_t next_stack_base = VM_MIN_ADDRESS;
+
+
+/* Allocate a new stack of size STACKSIZE. If successful, store the
+ address of the newly allocated stack in *STACKADDR and return 0.
+ Otherwise return an error code (EINVAL for an invalid stack size,
+ EAGAIN if the system lacked the necessary resources to allocate a
+ new stack). */
+int
+__pthread_stack_alloc (void **stackaddr, size_t stacksize)
+{
+ vm_offset_t base;
+ int i = 0;
+
+get_stack:
+ i++;
+ for (base = next_stack_base;
+ base < VM_MAX_ADDRESS
+ && __vm_allocate (__mach_task_self (), &base,
+ stacksize, FALSE) != KERN_SUCCESS; base += stacksize)
+ ;
+
+ if (base >= VM_MAX_ADDRESS)
+ {
+ if (i == 1)
+ {
+ next_stack_base = VM_MIN_ADDRESS;
+ goto get_stack;
+ }
+ else
+ return EAGAIN;
+ }
+
+ if (base >= VM_MAX_ADDRESS)
+ return EAGAIN;
+
+ next_stack_base = base + stacksize;
+
+ (*stackaddr) = (void *) base;
+ return 0;
+}
diff --git a/sysdeps/mach/htl/pt-thread-alloc.c b/sysdeps/mach/htl/pt-thread-alloc.c
new file mode 100644
index 0000000000..39993e4993
--- /dev/null
+++ b/sysdeps/mach/htl/pt-thread-alloc.c
@@ -0,0 +1,94 @@
+/* Start thread. 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 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 <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <mach.h>
+
+#include <pt-internal.h>
+
+/* Prepare a wakeup message. */
+static error_t
+create_wakeupmsg (struct __pthread *thread)
+{
+ kern_return_t err;
+
+ /* Build wakeup message. */
+ thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
+ thread->wakeupmsg.msgh_size = 0;
+
+ err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+ &thread->wakeupmsg.msgh_remote_port);
+ if (err)
+ return EAGAIN;
+
+ thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL;
+ thread->wakeupmsg.msgh_seqno = 0;
+ thread->wakeupmsg.msgh_id = 0;
+
+ err = __mach_port_insert_right (__mach_task_self (),
+ thread->wakeupmsg.msgh_remote_port,
+ thread->wakeupmsg.msgh_remote_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ if (err)
+ {
+ __mach_port_destroy (__mach_task_self (),
+ thread->wakeupmsg.msgh_remote_port);
+ return EAGAIN;
+ }
+
+ /* No need to queue more than one wakeup message on this port. */
+ __mach_port_set_qlimit (__mach_task_self (),
+ thread->wakeupmsg.msgh_remote_port, 1);
+
+ return 0;
+}
+
+/* Allocate any resouces for THREAD. The new kernel thread should not
+ be eligible to be scheduled. */
+int
+__pthread_thread_alloc (struct __pthread *thread)
+{
+ static int do_create;
+ error_t err;
+
+ err = create_wakeupmsg (thread);
+ if (err)
+ return err;
+
+ if (!do_create)
+ {
+ assert (__pthread_total == 0);
+ thread->kernel_thread = __mach_thread_self ();
+ do_create = 1;
+ }
+ else
+ {
+ err = __thread_create (__mach_task_self (), &thread->kernel_thread);
+ if (err)
+ {
+ __mach_port_destroy (__mach_task_self (),
+ thread->wakeupmsg.msgh_remote_port);
+ return EAGAIN;
+ }
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/htl/pt-thread-start.c b/sysdeps/mach/htl/pt-thread-start.c
new file mode 100644
index 0000000000..a79eb0c523
--- /dev/null
+++ b/sysdeps/mach/htl/pt-thread-start.c
@@ -0,0 +1,53 @@
+/* Start thread. 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 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 <assert.h>
+#include <errno.h>
+#include <mach.h>
+
+#include <pt-internal.h>
+
+/* Start THREAD. Get the kernel thread scheduled and running. */
+int
+__pthread_thread_start (struct __pthread *thread)
+{
+ static int do_start;
+ error_t err;
+
+ if (!do_start)
+ {
+ /* The main thread is already running: do nothing. */
+ assert (__pthread_total == 1);
+ assert ((
+ {
+ mach_port_t ktid = __mach_thread_self ();
+ int ok = thread->kernel_thread == ktid;
+ __mach_port_deallocate (__mach_task_self (),
+ thread->kernel_thread);
+ ok;
+ }));
+ do_start = 1;
+ }
+ else
+ {
+ err = __thread_resume (thread->kernel_thread);
+ assert_perror (err);
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/htl/pt-thread-terminate.c b/sysdeps/mach/htl/pt-thread-terminate.c
new file mode 100644
index 0000000000..b4ec882916
--- /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 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 <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);
+}
diff --git a/sysdeps/mach/htl/pt-timedblock.c b/sysdeps/mach/htl/pt-timedblock.c
new file mode 100644
index 0000000000..9301b8fa18
--- /dev/null
+++ b/sysdeps/mach/htl/pt-timedblock.c
@@ -0,0 +1,65 @@
+/* Block a thread with a timeout. 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 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 <assert.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include <mach.h>
+#include <mach/message.h>
+
+#include <pt-internal.h>
+
+/* Block THREAD. */
+error_t
+__pthread_timedblock (struct __pthread *thread,
+ const struct timespec *abstime, clockid_t clock_id)
+{
+ error_t err;
+ mach_msg_header_t msg;
+ mach_msg_timeout_t timeout;
+ struct timespec now;
+
+ /* We have an absolute time and now we have to convert it to a
+ relative time. Arg. */
+
+ err = clock_gettime (clock_id, &now);
+ assert (!err);
+
+ if (now.tv_sec > abstime->tv_sec
+ || (now.tv_sec == abstime->tv_sec && now.tv_nsec > abstime->tv_nsec))
+ return ETIMEDOUT;
+
+ timeout = (abstime->tv_sec - now.tv_sec) * 1000;
+
+ if (abstime->tv_nsec >= now.tv_nsec)
+ timeout += (abstime->tv_nsec - now.tv_nsec + 999999) / 1000000;
+ else
+ /* Need to do a carry. */
+ timeout -= (now.tv_nsec - abstime->tv_nsec + 999999) / 1000000;
+
+ err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
+ sizeof msg, thread->wakeupmsg.msgh_remote_port,
+ timeout, MACH_PORT_NULL);
+ if (err == EMACH_RCV_TIMED_OUT)
+ return ETIMEDOUT;
+
+ assert_perror (err);
+ return 0;
+}
diff --git a/sysdeps/mach/htl/pt-wakeup.c b/sysdeps/mach/htl/pt-wakeup.c
new file mode 100644
index 0000000000..069d232d7a
--- /dev/null
+++ b/sysdeps/mach/htl/pt-wakeup.c
@@ -0,0 +1,37 @@
+/* Wakeup a thread. 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 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 <assert.h>
+#include <errno.h>
+
+#include <mach.h>
+#include <mach/message.h>
+
+#include <pt-internal.h>
+
+/* Wakeup THREAD. */
+void
+__pthread_wakeup (struct __pthread *thread)
+{
+ error_t err;
+
+ err = __mach_msg (&thread->wakeupmsg, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
+ sizeof (thread->wakeupmsg), 0, MACH_PORT_NULL,
+ 0, MACH_PORT_NULL);
+ assert_perror (err);
+}