diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-04-02 01:43:22 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-04-02 01:44:14 +0200 |
commit | 33574c17eefcf326c1cd30eb9f915ad26d3d9ef2 (patch) | |
tree | 2c1b143f2b7a0ceba9fba000b70dd2889d56e60f /sysdeps/mach | |
parent | 03e2aa50fd512449025bba8c244d16338d8526a4 (diff) | |
download | glibc-33574c17eefcf326c1cd30eb9f915ad26d3d9ef2.tar.gz glibc-33574c17eefcf326c1cd30eb9f915ad26d3d9ef2.tar.xz glibc-33574c17eefcf326c1cd30eb9f915ad26d3d9ef2.zip |
hurd: Add hurd thread library
Contributed by Agustina Arzille <avarzille@riseup.net> Amos Jeffries <squid3@treenet.co.nz> David Michael <fedora.dm0@gmail.com> Marco Gerards <marco@gnu.org> Marcus Brinkmann <marcus@gnu.org> Neal H. Walfield <neal@gnu.org> Pino Toscano <toscano.pino@tiscali.it> Richard Braun <rbraun@sceen.net> Roland McGrath <roland@gnu.org> Samuel Thibault <samuel.thibault@ens-lyon.org> Thomas DiModica <ricinwich@yahoo.com> Thomas Schwinge <tschwinge@gnu.org> * htl: New directory. * sysdeps/htl: New directory. * sysdeps/hurd/htl: New directory. * sysdeps/i386/htl: New directory. * sysdeps/mach/htl: New directory. * sysdeps/mach/hurd/htl: New directory. * sysdeps/mach/hurd/i386/htl: New directory. * nscd/Depend, resolv/Depend, rt/Depend: Add htl dependency. * sysdeps/mach/hurd/i386/Implies: Add mach/hurd/i386/htl imply. * sysdeps/mach/hurd/i386/libpthread.abilist: New file.
Diffstat (limited to 'sysdeps/mach')
53 files changed, 2790 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..1ffda81f1f --- /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 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/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..b2e00eab81 --- /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 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 <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..6c38c92f64 --- /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 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 <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..3c763ef7cb --- /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 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 <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..571c1f2a62 --- /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 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 <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..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); +} diff --git a/sysdeps/mach/htl/pt-timedblock.c b/sysdeps/mach/htl/pt-timedblock.c new file mode 100644 index 0000000000..4255f77397 --- /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 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 <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..1e5488f14b --- /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 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/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); +} diff --git a/sysdeps/mach/hurd/htl/Implies b/sysdeps/mach/hurd/htl/Implies new file mode 100644 index 0000000000..64daad184a --- /dev/null +++ b/sysdeps/mach/hurd/htl/Implies @@ -0,0 +1,2 @@ +hurd/htl +mach/htl diff --git a/sysdeps/mach/hurd/htl/bits/pthread-np.h b/sysdeps/mach/hurd/htl/bits/pthread-np.h new file mode 100644 index 0000000000..0acee62186 --- /dev/null +++ b/sysdeps/mach/hurd/htl/bits/pthread-np.h @@ -0,0 +1,37 @@ +/* Non-portable functions. Hurd on Mach version. + Copyright (C) 2008-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/>. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +/* Same as pthread_cond_wait, but for Hurd-specific cancellation. + See hurd_thread_cancel. */ +extern int pthread_hurd_cond_wait_np (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Same as pthread_cond_timedwait, but for Hurd-specific cancellation. + See hurd_thread_cancel. */ +extern int pthread_hurd_cond_timedwait_np (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + const struct timespec *__abstime); + +#endif /* bits/pthread-np.h */ diff --git a/sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h b/sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h new file mode 100644 index 0000000000..4fe87cc5f5 --- /dev/null +++ b/sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h @@ -0,0 +1,49 @@ +/* Mutex type. Generic 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/>. */ + +#ifndef _BITS_TYPES_STRUCT___PTHREAD_MUTEX_H +#define _BITS_TYPES_STRUCT___PTHREAD_MUTEX_H 1 + +#include <bits/types/struct___pthread_mutexattr.h> + +/* User visible part of a mutex. */ +struct __pthread_mutex +{ + unsigned int __lock; + unsigned int __owner_id; + unsigned int __cnt; + int __shpid; + int __type; + int __flags; + unsigned int __reserved1; + unsigned int __reserved2; +}; + +/* Static mutex initializers. */ +#define __PTHREAD_MUTEX_INITIALIZER \ + { 0, 0, 0, 0, __PTHREAD_MUTEX_TIMED, 0, 0, 0 } + +/* The +1 is to mantain binary compatibility with the old + * libpthread implementation. */ +#define __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER \ + { 0, 0, 0, 0, __PTHREAD_MUTEX_ERRORCHECK + 1, 0, 0, 0 } + +#define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER \ + { 0, 0, 0, 0, __PTHREAD_MUTEX_RECURSIVE + 1, 0, 0, 0 } + +#endif /* bits/types/struct___pthread_mutex.h */ diff --git a/sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c b/sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c new file mode 100644 index 0000000000..711ae67043 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c @@ -0,0 +1,27 @@ +/* pthread_attr_setstackaddr. Hurd on 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 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 <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr) +{ + attr->__stackaddr = stackaddr; + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-attr-setstacksize.c b/sysdeps/mach/hurd/htl/pt-attr-setstacksize.c new file mode 100644 index 0000000000..6a96370ebe --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-attr-setstacksize.c @@ -0,0 +1,27 @@ +/* pthread_attr_setstacksize. Hurd on 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 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 <pthread.h> +#include <pt-internal.h> + +int +pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize) +{ + attr->__stacksize = stacksize; + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-docancel.c b/sysdeps/mach/hurd/htl/pt-docancel.c new file mode 100644 index 0000000000..a8bcb24cdb --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-docancel.c @@ -0,0 +1,65 @@ +/* Cancel a thread. + 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 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 <pthread.h> + +#include <pt-internal.h> + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + mach_port_t ktid; + int me; + + assert (p->cancel_pending == 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + __pthread_mutex_unlock (&p->cancel_lock); + + ktid = __mach_thread_self (); + me = p->kernel_thread == ktid; + __mach_port_deallocate (__mach_task_self (), ktid); + + if (me) + call_exit (); + else + { + error_t err; + + err = __thread_suspend (p->kernel_thread); + assert_perror (err); + + err = __thread_abort (p->kernel_thread); + assert_perror (err); + + err = __thread_set_pcsptp (p->kernel_thread, + 1, (void *) call_exit, 0, 0, 0, 0); + assert_perror (err); + + err = __thread_resume (p->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c b/sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c new file mode 100644 index 0000000000..41792e3711 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c @@ -0,0 +1,169 @@ +/* pthread_hurd_cond_timedwait_np. Hurd-specific wait on a condition. + Copyright (C) 2012-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 <pthread.h> +#include <assert.h> +#include <hurd/signal.h> + +#include <pt-internal.h> + +extern int __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec + *abstime); + +int +__pthread_hurd_cond_timedwait_np (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + return __pthread_hurd_cond_timedwait_internal (cond, mutex, abstime); +} + +strong_alias (__pthread_hurd_cond_timedwait_np, pthread_hurd_cond_timedwait_np); + +int +__pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + struct hurd_sigstate *ss = _hurd_self_sigstate (); + struct __pthread *self = _pthread_self (); + error_t err = 0; + int cancel, drain; + clockid_t clock_id = __pthread_default_condattr.__clock; + + /* This function will be called by hurd_thread_cancel while we are blocked + We wake up our thread if it's still blocking or about to block, so it will + progress and notice the cancellation flag. */ + void cancel_me (void) + { + int unblock; + + __pthread_spin_lock (&cond->__lock); + /* The thread only needs to be awaken if it's blocking or about to block. + If it was already unblocked, it's not queued any more. */ + unblock = self->prevp != NULL; + if (unblock) + __pthread_dequeue (self); + __pthread_spin_unlock (&cond->__lock); + + if (unblock) + __pthread_wakeup (self); + } + + assert (ss->intr_port == MACH_PORT_NULL); /* Sanity check for signal bugs. */ + + if (abstime != NULL && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) + return EINVAL; + + /* Atomically enqueue our thread on the condition variable's queue of + waiters, and mark our sigstate to indicate that `cancel_me' must be + called to wake us up. We must hold the sigstate lock while acquiring + the condition variable's lock and tweaking it, so that + hurd_thread_cancel can never suspend us and then deadlock waiting for + the condition variable's lock. */ + + __spin_lock (&ss->lock); + __pthread_spin_lock (&cond->__lock); + cancel = ss->cancel; + if (cancel) + /* We were cancelled before doing anything. Don't block at all. */ + ss->cancel = 0; + else + { + /* Put us on the queue so that pthread_cond_broadcast will know to wake + us up. */ + __pthread_enqueue (&cond->__queue, self); + if (cond->__attr) + clock_id = cond->__attr->__clock; + /* Tell hurd_thread_cancel how to unblock us. */ + ss->cancel_hook = &cancel_me; + } + __pthread_spin_unlock (&cond->__lock); + __spin_unlock (&ss->lock); + + if (cancel) + { + /* Cancelled on entry. Just leave the mutex locked. */ + mutex = NULL; + + __spin_lock (&ss->lock); + } + else + { + /* Release MUTEX before blocking. */ + __pthread_mutex_unlock (mutex); + + /* Block the thread. */ + if (abstime != NULL) + err = __pthread_timedblock (self, abstime, clock_id); + else + { + err = 0; + __pthread_block (self); + } + + /* As it was done when enqueueing, prevent hurd_thread_cancel from + suspending us while the condition lock is held. */ + __spin_lock (&ss->lock); + __pthread_spin_lock (&cond->__lock); + if (self->prevp == NULL) + /* Another thread removed us from the list of waiters, which means + a wakeup message has been sent. It was either consumed while + we were blocking, or queued after we timed out and before we + acquired the condition lock, in which case the message queue + must be drained. */ + drain = err ? 1 : 0; + else + { + /* We're still in the list of waiters. Noone attempted to wake us + up, i.e. we timed out. */ + __pthread_dequeue (self); + drain = 0; + } + __pthread_spin_unlock (&cond->__lock); + + if (drain) + __pthread_block (self); + } + + /* Clear the hook, now that we are done blocking. */ + ss->cancel_hook = NULL; + /* Check the cancellation flag; we might have unblocked due to + cancellation rather than a normal pthread_cond_signal or + pthread_cond_broadcast (or we might have just happened to get cancelled + right after waking up). */ + cancel |= ss->cancel; + ss->cancel = 0; + __spin_unlock (&ss->lock); + + if (mutex != NULL) + /* Reacquire the mutex and return. */ + __pthread_mutex_lock (mutex); + + if (cancel) + return EINTR; + else if (err) + { + assert (err == ETIMEDOUT); + return err; + } + + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c b/sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c new file mode 100644 index 0000000000..2f2b6c293f --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c @@ -0,0 +1,40 @@ +/* pthread_hurd_cond_wait. Hurd-specific wait on a condition. + Copyright (C) 2012-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 <pthread.h> +#include <assert.h> +#include <hurd/signal.h> + +#include <pt-internal.h> + +/* Implemented in pt-hurd-cond-timedwait.c. */ +extern int __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec + *abstime); + +int +__pthread_hurd_cond_wait_np (pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + error_t err; + + err = __pthread_hurd_cond_timedwait_internal (cond, mutex, NULL); + return err == EINTR; +} + +strong_alias (__pthread_hurd_cond_wait_np, pthread_hurd_cond_wait_np); diff --git a/sysdeps/mach/hurd/htl/pt-mutex-consistent.c b/sysdeps/mach/hurd/htl/pt-mutex-consistent.c new file mode 100644 index 0000000000..9fd6342be4 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-consistent.c @@ -0,0 +1,48 @@ +/* pthread_mutex_consistent. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutex_consistent (pthread_mutex_t *mtxp) +{ + int ret = EINVAL; + unsigned int val = mtxp->__lock; + + if ((mtxp->__flags & PTHREAD_MUTEX_ROBUST) != 0 && + (val & LLL_DEAD_OWNER) != 0 && + atomic_compare_and_exchange_bool_acq (&mtxp->__lock, + __getpid () | LLL_WAITERS, + val) == 0) + { + /* The mutex is now ours, and it's consistent. */ + mtxp->__owner_id = _pthread_self ()->thread; + mtxp->__cnt = 1; + ret = 0; + } + + return ret; +} + +weak_alias (pthread_mutex_consistent, pthread_mutex_consistent_np) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-destroy.c b/sysdeps/mach/hurd/htl/pt-mutex-destroy.c new file mode 100644 index 0000000000..89b4916eb6 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-destroy.c @@ -0,0 +1,38 @@ +/* pthread_mutex_destroy. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +_pthread_mutex_destroy (pthread_mutex_t *mtxp) +{ + atomic_read_barrier (); + if (*(volatile unsigned int *) &mtxp->__lock != 0) + return EBUSY; + + mtxp->__type = -1; + return 0; +} + +strong_alias (_pthread_mutex_destroy, pthread_mutex_destroy) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c new file mode 100644 index 0000000000..fa6b82b667 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c @@ -0,0 +1,35 @@ +/* pthread_mutex_getprioceiling. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutex_getprioceiling (const pthread_mutex_t *mtxp, int *clp) +{ + (void) mtxp; + (void) clp; + return ENOSYS; +} + +stub_warning (pthread_mutex_getprioceiling) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-init.c b/sysdeps/mach/hurd/htl/pt-mutex-init.c new file mode 100644 index 0000000000..8218eb150e --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-init.c @@ -0,0 +1,56 @@ +/* pthread_mutex_init. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +static const pthread_mutexattr_t dfl_attr = { + .__prioceiling = 0, + .__protocol = PTHREAD_PRIO_NONE, + .__pshared = PTHREAD_PROCESS_PRIVATE, + .__mutex_type = __PTHREAD_MUTEX_TIMED +}; + +int +_pthread_mutex_init (pthread_mutex_t *mtxp, const pthread_mutexattr_t *attrp) +{ + if (attrp == NULL) + attrp = &dfl_attr; + + mtxp->__flags = (attrp->__pshared == PTHREAD_PROCESS_SHARED ? + GSYNC_SHARED : 0) | ((attrp-> + __prioceiling & PTHREAD_MUTEX_ROBUST) ? + PTHREAD_MUTEX_ROBUST : 0); + + mtxp->__type = attrp->__mutex_type + + (attrp->__mutex_type != __PTHREAD_MUTEX_TIMED); + + mtxp->__owner_id = 0; + mtxp->__shpid = 0; + mtxp->__cnt = 0; + mtxp->__lock = 0; + + return 0; +} + +strong_alias (_pthread_mutex_init, pthread_mutex_init) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-lock.c b/sysdeps/mach/hurd/htl/pt-mutex-lock.c new file mode 100644 index 0000000000..e4a86f0e49 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-lock.c @@ -0,0 +1,81 @@ +/* pthread_mutex_lock. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +__pthread_mutex_lock (pthread_mutex_t *mtxp) +{ + struct __pthread *self; + int flags = mtxp->__flags & GSYNC_SHARED; + int ret = 0; + + switch (MTX_TYPE (mtxp)) + { + case PT_MTX_NORMAL: + lll_lock (&mtxp->__lock, flags); + break; + + case PT_MTX_RECURSIVE: + self = _pthread_self (); + if (mtx_owned_p (mtxp, self, flags)) + { + if (__glibc_unlikely (mtxp->__cnt + 1 == 0)) + return EAGAIN; + + ++mtxp->__cnt; + return ret; + } + + lll_lock (&mtxp->__lock, flags); + mtx_set_owner (mtxp, self, flags); + mtxp->__cnt = 1; + break; + + case PT_MTX_ERRORCHECK: + self = _pthread_self (); + if (mtx_owned_p (mtxp, self, flags)) + return EDEADLK; + + lll_lock (&mtxp->__lock, flags); + mtx_set_owner (mtxp, self, flags); + break; + + case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST: + case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST: + case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST: + self = _pthread_self (); + ROBUST_LOCK (self, mtxp, __lll_robust_lock, flags); + break; + + default: + ret = EINVAL; + break; + } + + return ret; +} + +strong_alias (__pthread_mutex_lock, _pthread_mutex_lock) +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c new file mode 100644 index 0000000000..5f39ebb959 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c @@ -0,0 +1,36 @@ +/* pthread_mutex_setprioceiling. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutex_setprioceiling (pthread_mutex_t *mtxp, int cl, int *prp) +{ + (void) mtxp; + (void) cl; + (void) prp; + return ENOSYS; +} + +stub_warning (pthread_mutex_setprioceiling) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c b/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c new file mode 100644 index 0000000000..0457445c86 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c @@ -0,0 +1,79 @@ +/* pthread_mutex_timedlock. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp) +{ + struct __pthread *self; + int ret, flags = mtxp->__flags & GSYNC_SHARED; + + switch (MTX_TYPE (mtxp)) + { + case PT_MTX_NORMAL: + ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags); + break; + + case PT_MTX_RECURSIVE: + self = _pthread_self (); + if (mtx_owned_p (mtxp, self, flags)) + { + if (__glibc_unlikely (mtxp->__cnt + 1 == 0)) + return EAGAIN; + + ++mtxp->__cnt; + ret = 0; + } + else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags)) == 0) + { + mtx_set_owner (mtxp, self, flags); + mtxp->__cnt = 1; + } + + break; + + case PT_MTX_ERRORCHECK: + self = _pthread_self (); + if (mtx_owned_p (mtxp, self, flags)) + ret = EDEADLK; + else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags)) == 0) + mtx_set_owner (mtxp, self, flags); + + break; + + case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST: + case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST: + case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST: + self = _pthread_self (); + ROBUST_LOCK (self, mtxp, lll_robust_abstimed_lock, tsp, flags); + break; + + default: + ret = EINVAL; + break; + } + + return ret; +} diff --git a/sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c b/sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c new file mode 100644 index 0000000000..e89c8dcac7 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c @@ -0,0 +1,77 @@ +/* pthread_mutex_transfer_np. Transfer mutex ownership to another thread. + Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +__pthread_mutex_transfer_np (pthread_mutex_t *mtxp, pthread_t th) +{ + struct __pthread *self = _pthread_self (); + struct __pthread *pt = __pthread_getid (th); + + if (pt == NULL) + return ESRCH; + else if (pt == self) + return 0; + + int ret = 0; + int flags = mtxp->__flags & GSYNC_SHARED; + + switch (MTX_TYPE (mtxp)) + { + case PT_MTX_NORMAL: + break; + + case PT_MTX_RECURSIVE: + case PT_MTX_ERRORCHECK: + if (!mtx_owned_p (mtxp, self, flags)) + ret = EPERM; + else + mtx_set_owner (mtxp, pt, flags); + + break; + + case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST: + case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST: + case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST: + /* Note that this can be used to transfer an inconsistent + * mutex as well. The new owner will still have the same + * flags as the original. */ + if (mtxp->__owner_id != self->thread || + (int) (mtxp->__lock & LLL_OWNER_MASK) != __getpid ()) + ret = EPERM; + else + mtxp->__owner_id = pt->thread; + + break; + + default: + ret = EINVAL; + } + + return ret; +} + +weak_alias (__pthread_mutex_transfer_np, pthread_mutex_transfer_np) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-trylock.c b/sysdeps/mach/hurd/htl/pt-mutex-trylock.c new file mode 100644 index 0000000000..36d4f5921c --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-trylock.c @@ -0,0 +1,85 @@ +/* pthread_mutex_trylock. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +__pthread_mutex_trylock (pthread_mutex_t *mtxp) +{ + struct __pthread *self; + int ret; + + switch (MTX_TYPE (mtxp)) + { + case PT_MTX_NORMAL: + ret = lll_trylock (&mtxp->__lock); + if (ret) + ret = EBUSY; + break; + + case PT_MTX_RECURSIVE: + self = _pthread_self (); + if (mtx_owned_p (mtxp, self, mtxp->__flags)) + { + if (__glibc_unlikely (mtxp->__cnt + 1 == 0)) + return EAGAIN; + + ++mtxp->__cnt; + ret = 0; + } + else if ((ret = lll_trylock (&mtxp->__lock)) == 0) + { + mtx_set_owner (mtxp, self, mtxp->__flags); + mtxp->__cnt = 1; + } + else + ret = EBUSY; + + break; + + case PT_MTX_ERRORCHECK: + self = _pthread_self (); + if ((ret = lll_trylock (&mtxp->__lock)) == 0) + mtx_set_owner (mtxp, self, mtxp->__flags); + else + ret = EBUSY; + break; + + case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST: + case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST: + case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST: + self = _pthread_self (); + ROBUST_LOCK (self, mtxp, __lll_robust_trylock); + break; + + default: + ret = EINVAL; + break; + } + + return ret; +} + +strong_alias (__pthread_mutex_trylock, _pthread_mutex_trylock) +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) diff --git a/sysdeps/mach/hurd/htl/pt-mutex-unlock.c b/sysdeps/mach/hurd/htl/pt-mutex-unlock.c new file mode 100644 index 0000000000..30c62fcb24 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex-unlock.c @@ -0,0 +1,92 @@ +/* pthread_mutex_unlock. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +__pthread_mutex_unlock (pthread_mutex_t *mtxp) +{ + struct __pthread *self; + int ret = 0, flags = mtxp->__flags & GSYNC_SHARED; + + switch (MTX_TYPE (mtxp)) + { + case PT_MTX_NORMAL: + lll_unlock (&mtxp->__lock, flags); + break; + + case PT_MTX_RECURSIVE: + self = _pthread_self (); + if (!mtx_owned_p (mtxp, self, flags)) + ret = EPERM; + else if (--mtxp->__cnt == 0) + { + mtxp->__owner_id = mtxp->__shpid = 0; + lll_unlock (&mtxp->__lock, flags); + } + + break; + + case PT_MTX_ERRORCHECK: + self = _pthread_self (); + if (!mtx_owned_p (mtxp, self, flags)) + ret = EPERM; + else + { + mtxp->__owner_id = mtxp->__shpid = 0; + lll_unlock (&mtxp->__lock, flags); + } + + break; + + case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST: + case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST: + case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST: + self = _pthread_self (); + if (mtxp->__owner_id == NOTRECOVERABLE_ID) + ; /* Nothing to do. */ + else if (mtxp->__owner_id != self->thread || + (int) (mtxp->__lock & LLL_OWNER_MASK) != __getpid ()) + ret = EPERM; + else if (--mtxp->__cnt == 0) + { + /* Release the lock. If it's in an inconsistent + * state, mark it as irrecoverable. */ + mtxp->__owner_id = (mtxp->__lock & LLL_DEAD_OWNER) ? + NOTRECOVERABLE_ID : 0; + __lll_robust_unlock (&mtxp->__lock, flags); + } + + break; + + default: + ret = EINVAL; + break; + } + + return ret; +} + +strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock) +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) diff --git a/sysdeps/mach/hurd/htl/pt-mutex.h b/sysdeps/mach/hurd/htl/pt-mutex.h new file mode 100644 index 0000000000..2daf63e986 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutex.h @@ -0,0 +1,90 @@ +/* Internal definitions for pthreads library. + Copyright (C) 2016-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/>. */ + +#ifndef _PT_MUTEX_H +#define _PT_MUTEX_H 1 + +/* Special ID used to signal an unrecoverable robust mutex. */ +#define NOTRECOVERABLE_ID (1U << 31) + +/* Common path for robust mutexes. Assumes the variable 'ret' + * is bound in the function this is called from. */ +#define ROBUST_LOCK(self, mtxp, cb, ...) \ + if (mtxp->__owner_id == NOTRECOVERABLE_ID) \ + return ENOTRECOVERABLE; \ + else if (mtxp->__owner_id == self->thread && \ + __getpid () == (int)(mtxp->__lock & LLL_OWNER_MASK)) \ + { \ + if (mtxp->__type == PT_MTX_RECURSIVE) \ + { \ + if (__glibc_unlikely (mtxp->__cnt + 1 == 0)) \ + return EAGAIN; \ + \ + ++mtxp->__cnt; \ + return 0; \ + } \ + else if (mtxp->__type == PT_MTX_ERRORCHECK) \ + return EDEADLK; \ + } \ + \ + ret = cb (&mtxp->__lock, ##__VA_ARGS__); \ + if (ret == 0 || ret == EOWNERDEAD) \ + { \ + if (mtxp->__owner_id == ENOTRECOVERABLE) \ + ret = ENOTRECOVERABLE; \ + else \ + { \ + mtxp->__owner_id = self->thread; \ + mtxp->__cnt = 1; \ + if (ret == EOWNERDEAD) \ + { \ + mtxp->__lock = mtxp->__lock | LLL_DEAD_OWNER; \ + atomic_write_barrier (); \ + } \ + } \ + } \ + (void)0 + +/* Check that a thread owns the mutex. For non-robust, task-shared + * objects, we have to check the thread *and* process-id. */ +#define mtx_owned_p(mtx, pt, flags) \ + ((mtx)->__owner_id == (pt)->thread && \ + (((flags) & GSYNC_SHARED) == 0 || \ + (mtx)->__shpid == __getpid ())) + +/* Record a thread as the owner of the mutex. */ +#define mtx_set_owner(mtx, pt, flags) \ + (void) \ + ({ \ + (mtx)->__owner_id = (pt)->thread; \ + if ((flags) & GSYNC_SHARED) \ + (mtx)->__shpid = __getpid (); \ + }) + +/* Redefined mutex types. The +1 is for binary compatibility. */ +#define PT_MTX_NORMAL __PTHREAD_MUTEX_TIMED +#define PT_MTX_RECURSIVE (__PTHREAD_MUTEX_RECURSIVE + 1) +#define PT_MTX_ERRORCHECK (__PTHREAD_MUTEX_ERRORCHECK + 1) + +/* Mutex type, including robustness. */ +#define MTX_TYPE(mtxp) \ + ((mtxp)->__type | ((mtxp)->__flags & PTHREAD_MUTEX_ROBUST)) + +extern int __getpid (void) __attribute__ ((const)); + +#endif /* pt-mutex.h */ diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c b/sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c new file mode 100644 index 0000000000..9c6cffc5bd --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c @@ -0,0 +1,34 @@ +/* pthread_mutexattr_destroy. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +__pthread_mutexattr_destroy (pthread_mutexattr_t *attrp) +{ + (void) attrp; + return 0; +} + +weak_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c new file mode 100644 index 0000000000..4532eca989 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c @@ -0,0 +1,35 @@ +/* pthread_mutexattr_getprioceiling. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *ap, int *clp) +{ + (void) ap; + (void) clp; + return ENOSYS; +} + +stub_warning (pthread_mutexattr_getprioceiling) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c new file mode 100644 index 0000000000..33cdc158b2 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c @@ -0,0 +1,32 @@ +/* pthread_mutexattr_getprotocol. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attrp, int *ptp) +{ + *ptp = attrp->__protocol; + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c new file mode 100644 index 0000000000..d393b4bb7f --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c @@ -0,0 +1,32 @@ +/* pthread_mutexattr_getpshared. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_getpshared (const pthread_mutexattr_t *attrp, int *outp) +{ + *outp = attrp->__pshared; + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c new file mode 100644 index 0000000000..0999db02d7 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c @@ -0,0 +1,35 @@ +/* pthread_mutexattr_getrobust. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_getrobust (const pthread_mutexattr_t *attrp, int *outp) +{ + *outp = (attrp->__prioceiling & PTHREAD_MUTEX_ROBUST) ? + PTHREAD_MUTEX_ROBUST : PTHREAD_MUTEX_STALLED; + return 0; +} + +weak_alias (pthread_mutexattr_getrobust, pthread_mutexattr_getrobust_np) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c b/sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c new file mode 100644 index 0000000000..6881a5b816 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c @@ -0,0 +1,32 @@ +/* pthread_mutexattr_gettype. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_gettype (const pthread_mutexattr_t *attrp, int *outp) +{ + *outp = attrp->__mutex_type; + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-init.c b/sysdeps/mach/hurd/htl/pt-mutexattr-init.c new file mode 100644 index 0000000000..b135126553 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-init.c @@ -0,0 +1,40 @@ +/* pthread_mutexattr_init. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +static const pthread_mutexattr_t dfl_attr = { + .__prioceiling = 0, + .__protocol = PTHREAD_PRIO_NONE, + .__pshared = PTHREAD_PROCESS_PRIVATE, + .__mutex_type = __PTHREAD_MUTEX_TIMED +}; + +int +__pthread_mutexattr_init (pthread_mutexattr_t *attrp) +{ + *attrp = dfl_attr; + return 0; +} +weak_alias (__pthread_mutexattr_init, pthread_mutexattr_init) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c new file mode 100644 index 0000000000..6011ffb94e --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c @@ -0,0 +1,35 @@ +/* pthread_mutexattr_setprioceiling. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attrp, int cl) +{ + (void) attrp; + (void) cl; + return ENOSYS; +} + +stub_warning (pthread_mutexattr_setprioceiling) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c new file mode 100644 index 0000000000..5173a487c4 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c @@ -0,0 +1,34 @@ +/* pthread_mutexattr_setprotocol. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_setprotocol (pthread_mutexattr_t *attrp, int proto) +{ + (void) attrp; + return proto == PTHREAD_PRIO_NONE ? 0 : + proto != PTHREAD_PRIO_INHERIT && + proto != PTHREAD_PRIO_PROTECT ? EINVAL : ENOTSUP; +} diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c new file mode 100644 index 0000000000..7e0e607151 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c @@ -0,0 +1,35 @@ +/* pthread_mutexattr_setpshared. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_setpshared (pthread_mutexattr_t *attrp, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + attrp->__pshared = pshared; + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c new file mode 100644 index 0000000000..f38c7a747e --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c @@ -0,0 +1,37 @@ +/* pthread_mutexattr_setrobust. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +pthread_mutexattr_setrobust (pthread_mutexattr_t *attrp, int robust) +{ + if (robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED) + return EINVAL; + + attrp->__prioceiling |= robust; + return 0; +} + +weak_alias (pthread_mutexattr_setrobust, pthread_mutexattr_setrobust_np) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-settype.c b/sysdeps/mach/hurd/htl/pt-mutexattr-settype.c new file mode 100644 index 0000000000..c856fd7859 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr-settype.c @@ -0,0 +1,36 @@ +/* pthread_mutexattr_settype. Hurd version. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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. + + This program 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 this program; if not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <pthread.h> +#include <stdlib.h> +#include <assert.h> +#include <pt-internal.h> +#include "pt-mutex.h" +#include <hurdlock.h> + +int +__pthread_mutexattr_settype (pthread_mutexattr_t *attrp, int type) +{ + if (type < 0 || type > __PTHREAD_MUTEX_RECURSIVE) + return EINVAL; + + attrp->__mutex_type = type; + return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr.c b/sysdeps/mach/hurd/htl/pt-mutexattr.c new file mode 100644 index 0000000000..40a8c178f1 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-mutexattr.c @@ -0,0 +1 @@ +/* empty */ diff --git a/sysdeps/mach/hurd/htl/pt-sigstate-destroy.c b/sysdeps/mach/hurd/htl/pt-sigstate-destroy.c new file mode 100644 index 0000000000..69de5cad01 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-sigstate-destroy.c @@ -0,0 +1,26 @@ +/* Destroy the signal state. Hurd on 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 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 <pthread.h> + +#include <pt-internal.h> + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ +} diff --git a/sysdeps/mach/hurd/htl/pt-sigstate-init.c b/sysdeps/mach/hurd/htl/pt-sigstate-init.c new file mode 100644 index 0000000000..a6b4f76b25 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-sigstate-init.c @@ -0,0 +1,44 @@ +/* Initialize the signal state. Hurd on 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 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 <pthread.h> +#include <pt-internal.h> +#include <hurd/signal.h> + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + 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); + (void) ss; + } + else if (__pthread_num_threads >= 2) + do_init_global = 1; + + return 0; +} diff --git a/sysdeps/mach/hurd/htl/pt-sigstate.c b/sysdeps/mach/hurd/htl/pt-sigstate.c new file mode 100644 index 0000000000..5f0a1b4f9a --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-sigstate.c @@ -0,0 +1,70 @@ +/* Set a thread's signal state. Hurd on 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 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 <pthread.h> +#include <assert.h> +#include <signal.h> +#include <hurd/signal.h> + +#include <pt-internal.h> + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, int clear_pending) +{ + error_t err = 0; + struct hurd_sigstate *ss; + + ss = _hurd_thread_sigstate (thread->kernel_thread); + assert (ss); + + __spin_lock (&ss->lock); + + if (oset != NULL) + *oset = ss->blocked; + + if (set != NULL) + { + switch (how) + { + case SIG_BLOCK: + ss->blocked |= *set; + break; + + case SIG_SETMASK: + ss->blocked = *set; + break; + + case SIG_UNBLOCK: + ss->blocked &= ~*set; + break; + + default: + err = EINVAL; + break; + } + ss->blocked &= ~_SIG_CANT_MASK; + } + + if (!err && clear_pending) + __sigemptyset (&ss->pending); + + __spin_unlock (&ss->lock); + + return err; +} diff --git a/sysdeps/mach/hurd/htl/pt-sysdep.c b/sysdeps/mach/hurd/htl/pt-sysdep.c new file mode 100644 index 0000000000..40ebc8e6d6 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-sysdep.c @@ -0,0 +1,99 @@ +/* System dependent pthreads code. Hurd 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 <stddef.h> +#include <stdint.h> + +#include <mach.h> +#include <mach/mig_support.h> + +#include <pt-internal.h> + +__thread struct __pthread *___pthread_self; + +/* Forward. */ +static void *init_routine (void); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void *(*_cthread_init_routine) (void) = &init_routine; + +/* This function is called from the Hurd-specific startup code. It + should return a new stack pointer for the main thread. The caller + will switch to this new stack before doing anything serious. */ +static void * +_init_routine (void *stack) +{ + struct __pthread *thread; + int err; + pthread_attr_t attr, *attrp = 0; + + if (__pthread_threads != NULL) + /* Already initialized */ + return 0; + + /* Initialize the library. */ + ___pthread_init (); + + if (stack != NULL) + { + /* We are getting initialized due to dlopening a library using libpthread + while the main program was not linked against libpthread. */ + /* Avoid allocating another stack */ + attrp = &attr; + pthread_attr_init (attrp); + pthread_attr_setstack (attrp, stack, __vm_page_size); + } + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, attrp, 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 + signal thread (which will be created by the glibc startup code + when we return from here) shouldn't be seen as a user thread. */ + __pthread_total--; + + /* Make MiG code thread aware. */ + __mig_init (thread->stackaddr); + + return thread->mcontext.sp; +} + +static void * +init_routine (void) +{ + return _init_routine (0); +} + +#ifdef SHARED +__attribute__ ((constructor)) +static void +dynamic_init_routine (void) +{ + _init_routine (__libc_stack_end); +} +#endif diff --git a/sysdeps/mach/hurd/htl/pt-sysdep.h b/sysdeps/mach/hurd/htl/pt-sysdep.h new file mode 100644 index 0000000000..09778068b7 --- /dev/null +++ b/sysdeps/mach/hurd/htl/pt-sysdep.h @@ -0,0 +1,65 @@ +/* Internal definitions for pthreads library. + 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/>. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include <mach.h> + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size. */ +#define PTHREAD_STACK_DEFAULT (8 * 1024 * 1024) + +#define PTHREAD_SYSDEP_MEMBERS \ + thread_t kernel_thread; \ + mach_msg_header_t wakeupmsg; + +extern __thread struct __pthread *___pthread_self; +#define _pthread_self() \ + ({ \ + struct __pthread *thread; \ + \ + assert (__pthread_threads); \ + thread = ___pthread_self; \ + \ + assert (thread); \ + assert (({ mach_port_t ktid = __mach_thread_self (); \ + int ok = thread->kernel_thread == ktid; \ + __mach_port_deallocate (__mach_task_self (), ktid);\ + ok; })); \ + thread; \ + }) + +extern inline void +__attribute__ ((__always_inline__)) +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize); +} + +/* Change thread THREAD's program counter to PC if SET_PC is true, + its stack pointer to SP if SET_IP is true, and its thread pointer + to TP if SET_TP is true. */ +extern int __thread_set_pcsptp (thread_t thread, + int set_pc, void *pc, + int set_sp, void *sp, int set_tp, void *tp); + + +#endif /* pt-sysdep.h */ diff --git a/sysdeps/mach/hurd/i386/Implies b/sysdeps/mach/hurd/i386/Implies index 94db5e92ef..eedc9eada9 100644 --- a/sysdeps/mach/hurd/i386/Implies +++ b/sysdeps/mach/hurd/i386/Implies @@ -1 +1,2 @@ mach/hurd/x86 +mach/hurd/i386/htl diff --git a/sysdeps/mach/hurd/i386/htl/Implies b/sysdeps/mach/hurd/i386/htl/Implies new file mode 100644 index 0000000000..7a0f99d772 --- /dev/null +++ b/sysdeps/mach/hurd/i386/htl/Implies @@ -0,0 +1,2 @@ +mach/hurd/htl +i386/htl diff --git a/sysdeps/mach/hurd/i386/htl/pt-machdep.c b/sysdeps/mach/hurd/i386/htl/pt-machdep.c new file mode 100644 index 0000000000..9b2083d2da --- /dev/null +++ b/sysdeps/mach/hurd/i386/htl/pt-machdep.c @@ -0,0 +1,82 @@ +/* Machine dependent pthreads code. Hurd/i386 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 <errno.h> + +#include <mach.h> +#include <mach/i386/thread_status.h> +#include <mach/i386/mach_i386.h> +#include <mach/mig_errors.h> +#include <mach/thread_status.h> + +#define HURD_TLS_DESC_DECL(desc, tcb) \ + struct descriptor desc = \ + { /* low word: */ \ + 0xffff /* limit 0..15 */ \ + | (((unsigned int) (tcb)) << 16) /* base 0..15 */ \ + , /* high word: */ \ + ((((unsigned int) (tcb)) >> 16) & 0xff) /* base 16..23 */ \ + | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ \ + | (0xf << 16) /* limit 16..19 */ \ + | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ \ + | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ + } + +int +__thread_set_pcsptp (thread_t thread, + int set_ip, void *ip, + int set_sp, void *sp, + int set_tp, void *tp) +{ + error_t err; + struct i386_thread_state state; + mach_msg_type_number_t state_count; + + state_count = i386_THREAD_STATE_COUNT; + + err = __thread_get_state (thread, i386_REGS_SEGS_STATE, + (thread_state_t) &state, &state_count); + if (err) + return err; + + if (set_sp) + state.uesp = (unsigned int) sp; + if (set_ip) + state.eip = (unsigned int) ip; + if (set_tp) + { + HURD_TLS_DESC_DECL (desc, tp); + int sel; + + asm ("mov %%gs, %w0": "=q" (sel):"0" (0)); + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ + err = __i386_set_ldt (thread, sel, &desc, 1); + else + err = __i386_set_gdt (thread, &sel, desc); + if (err) + return err; + state.gs = sel; + } + + err = __thread_set_state (thread, i386_REGS_SEGS_STATE, + (thread_state_t) &state, i386_THREAD_STATE_COUNT); + if (err) + return err; + + return 0; +} diff --git a/sysdeps/mach/hurd/i386/htl/pt-setup.c b/sysdeps/mach/hurd/i386/htl/pt-setup.c new file mode 100644 index 0000000000..a59f71b7be --- /dev/null +++ b/sysdeps/mach/hurd/i386/htl/pt-setup.c @@ -0,0 +1,110 @@ +/* Setup thread stack. Hurd/i386 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 <stdint.h> +#include <assert.h> +#include <mach.h> + +#include <pt-internal.h> + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- + */ + +/* Set up the stack for THREAD, such that it appears as if + START_ROUTINE and ARG were passed to the new thread's entry-point. + Return the stack pointer for the new thread. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine) (void *), void *arg) +{ + error_t err; + uintptr_t *bottom, *top; + + /* Calculate the top of the new stack. */ + bottom = thread->stackaddr; + top = (uintptr_t *) ((uintptr_t) bottom + thread->stacksize + + ((thread->guardsize + __vm_page_size - 1) + / __vm_page_size) * __vm_page_size); + + if (start_routine != NULL) + { + /* And then the call frame. */ + top -= 3; + top = (uintptr_t *) ((uintptr_t) top & ~0xf); + top[2] = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + top[1] = (uintptr_t) start_routine; + top[0] = (uintptr_t) thread; + *--top = 0; /* Fake return address. */ + } + + if (thread->guardsize) + { + err = __vm_protect (__mach_task_self (), (vm_address_t) bottom, + thread->guardsize, 0, 0); + assert_perror (err); + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point) (struct __pthread *, void *(*)(void *), + void *), void *(*start_routine) (void *), + void *arg) +{ + tcbhead_t *tcb; + error_t err; + mach_port_t ktid; + + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + ktid = __mach_thread_self (); + if (thread->kernel_thread == ktid) + /* Fix up the TCB for the main thread. The C library has already + installed a TCB, which we want to keep using. This TCB must not + be freed so don't register it in the thread structure. On the + other hand, it's not yet possible to reliably release a TCB. + Leave the unused one registered so that it doesn't leak. The + only thing left to do is to correctly set the `self' member in + the already existing TCB. */ + tcb = THREAD_SELF; + else + { + err = __thread_set_pcsptp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp, + 1, thread->tcb); + assert_perror (err); + tcb = thread->tcb; + } + __mach_port_deallocate (__mach_task_self (), ktid); + + tcb->self = thread->kernel_thread; + + return 0; +} diff --git a/sysdeps/mach/hurd/i386/libpthread.abilist b/sysdeps/mach/hurd/i386/libpthread.abilist new file mode 100644 index 0000000000..e11569f176 --- /dev/null +++ b/sysdeps/mach/hurd/i386/libpthread.abilist @@ -0,0 +1,151 @@ +GLIBC_2.12 GLIBC_2.12 A +GLIBC_2.12 __mutex_lock_solid F +GLIBC_2.12 __mutex_unlock_solid F +GLIBC_2.12 __pthread_get_cleanup_stack F +GLIBC_2.12 __pthread_key_create F +GLIBC_2.12 __pthread_kill F +GLIBC_2.12 __pthread_mutex_transfer_np F +GLIBC_2.12 __pthread_spin_destroy F +GLIBC_2.12 __pthread_spin_init F +GLIBC_2.12 __pthread_spin_lock F +GLIBC_2.12 __pthread_spin_trylock F +GLIBC_2.12 __pthread_spin_unlock F +GLIBC_2.12 _cthread_init_routine D 0x4 +GLIBC_2.12 _cthreads_flockfile F +GLIBC_2.12 _cthreads_ftrylockfile F +GLIBC_2.12 _cthreads_funlockfile F +GLIBC_2.12 _pthread_mutex_destroy F +GLIBC_2.12 _pthread_mutex_init F +GLIBC_2.12 _pthread_mutex_lock F +GLIBC_2.12 _pthread_mutex_trylock F +GLIBC_2.12 _pthread_mutex_unlock F +GLIBC_2.12 _pthread_rwlock_destroy F +GLIBC_2.12 _pthread_rwlock_init F +GLIBC_2.12 _pthread_spin_lock F +GLIBC_2.12 cthread_detach F +GLIBC_2.12 cthread_fork F +GLIBC_2.12 cthread_getspecific F +GLIBC_2.12 cthread_keycreate F +GLIBC_2.12 cthread_setspecific F +GLIBC_2.12 flockfile F +GLIBC_2.12 ftrylockfile F +GLIBC_2.12 funlockfile F +GLIBC_2.12 pthread_atfork F +GLIBC_2.12 pthread_attr_destroy F +GLIBC_2.12 pthread_attr_getdetachstate F +GLIBC_2.12 pthread_attr_getguardsize F +GLIBC_2.12 pthread_attr_getinheritsched F +GLIBC_2.12 pthread_attr_getschedparam F +GLIBC_2.12 pthread_attr_getschedpolicy F +GLIBC_2.12 pthread_attr_getscope F +GLIBC_2.12 pthread_attr_getstack F +GLIBC_2.12 pthread_attr_getstackaddr F +GLIBC_2.12 pthread_attr_getstacksize F +GLIBC_2.12 pthread_attr_init F +GLIBC_2.12 pthread_attr_setdetachstate F +GLIBC_2.12 pthread_attr_setguardsize F +GLIBC_2.12 pthread_attr_setinheritsched F +GLIBC_2.12 pthread_attr_setschedparam F +GLIBC_2.12 pthread_attr_setschedpolicy F +GLIBC_2.12 pthread_attr_setscope F +GLIBC_2.12 pthread_attr_setstack F +GLIBC_2.12 pthread_attr_setstackaddr F +GLIBC_2.12 pthread_attr_setstacksize F +GLIBC_2.12 pthread_barrier_destroy F +GLIBC_2.12 pthread_barrier_init F +GLIBC_2.12 pthread_barrier_wait F +GLIBC_2.12 pthread_barrierattr_destroy F +GLIBC_2.12 pthread_barrierattr_getpshared F +GLIBC_2.12 pthread_barrierattr_init F +GLIBC_2.12 pthread_barrierattr_setpshared F +GLIBC_2.12 pthread_cancel F +GLIBC_2.12 pthread_cond_broadcast F +GLIBC_2.12 pthread_cond_destroy F +GLIBC_2.12 pthread_cond_init F +GLIBC_2.12 pthread_cond_signal F +GLIBC_2.12 pthread_cond_timedwait F +GLIBC_2.12 pthread_cond_wait F +GLIBC_2.12 pthread_condattr_destroy F +GLIBC_2.12 pthread_condattr_getclock F +GLIBC_2.12 pthread_condattr_getpshared F +GLIBC_2.12 pthread_condattr_init F +GLIBC_2.12 pthread_condattr_setclock F +GLIBC_2.12 pthread_condattr_setpshared F +GLIBC_2.12 pthread_create F +GLIBC_2.12 pthread_detach F +GLIBC_2.12 pthread_equal F +GLIBC_2.12 pthread_exit F +GLIBC_2.12 pthread_getattr_np F +GLIBC_2.12 pthread_getconcurrency F +GLIBC_2.12 pthread_getcpuclockid F +GLIBC_2.12 pthread_getschedparam F +GLIBC_2.12 pthread_getspecific F +GLIBC_2.12 pthread_join F +GLIBC_2.12 pthread_key_create F +GLIBC_2.12 pthread_key_delete F +GLIBC_2.12 pthread_kill F +GLIBC_2.12 pthread_mutex_destroy F +GLIBC_2.12 pthread_mutex_getprioceiling F +GLIBC_2.12 pthread_mutex_init F +GLIBC_2.12 pthread_mutex_lock F +GLIBC_2.12 pthread_mutex_setprioceiling F +GLIBC_2.12 pthread_mutex_timedlock F +GLIBC_2.12 pthread_mutex_transfer_np F +GLIBC_2.12 pthread_mutex_trylock F +GLIBC_2.12 pthread_mutex_unlock F +GLIBC_2.12 pthread_mutexattr_destroy F +GLIBC_2.12 pthread_mutexattr_getprioceiling F +GLIBC_2.12 pthread_mutexattr_getprotocol F +GLIBC_2.12 pthread_mutexattr_getpshared F +GLIBC_2.12 pthread_mutexattr_gettype F +GLIBC_2.12 pthread_mutexattr_init F +GLIBC_2.12 pthread_mutexattr_setprioceiling F +GLIBC_2.12 pthread_mutexattr_setprotocol F +GLIBC_2.12 pthread_mutexattr_setpshared F +GLIBC_2.12 pthread_mutexattr_settype F +GLIBC_2.12 pthread_once F +GLIBC_2.12 pthread_rwlock_destroy F +GLIBC_2.12 pthread_rwlock_init F +GLIBC_2.12 pthread_rwlock_rdlock F +GLIBC_2.12 pthread_rwlock_timedrdlock F +GLIBC_2.12 pthread_rwlock_timedwrlock F +GLIBC_2.12 pthread_rwlock_tryrdlock F +GLIBC_2.12 pthread_rwlock_trywrlock F +GLIBC_2.12 pthread_rwlock_unlock F +GLIBC_2.12 pthread_rwlock_wrlock F +GLIBC_2.12 pthread_rwlockattr_destroy F +GLIBC_2.12 pthread_rwlockattr_getpshared F +GLIBC_2.12 pthread_rwlockattr_init F +GLIBC_2.12 pthread_rwlockattr_setpshared F +GLIBC_2.12 pthread_self F +GLIBC_2.12 pthread_setcancelstate F +GLIBC_2.12 pthread_setcanceltype F +GLIBC_2.12 pthread_setconcurrency F +GLIBC_2.12 pthread_setschedparam F +GLIBC_2.12 pthread_setschedprio F +GLIBC_2.12 pthread_setspecific F +GLIBC_2.12 pthread_sigmask F +GLIBC_2.12 pthread_spin_destroy F +GLIBC_2.12 pthread_spin_init F +GLIBC_2.12 pthread_spin_lock F +GLIBC_2.12 pthread_spin_trylock F +GLIBC_2.12 pthread_spin_unlock F +GLIBC_2.12 pthread_testcancel F +GLIBC_2.12 pthread_yield F +GLIBC_2.12 sem_close F +GLIBC_2.12 sem_destroy F +GLIBC_2.12 sem_getvalue F +GLIBC_2.12 sem_init F +GLIBC_2.12 sem_open F +GLIBC_2.12 sem_post F +GLIBC_2.12 sem_timedwait F +GLIBC_2.12 sem_trywait F +GLIBC_2.12 sem_unlink F +GLIBC_2.12 sem_wait F +GLIBC_2.2.6 GLIBC_2.2.6 A +GLIBC_2.2.6 _IO_flockfile F +GLIBC_2.2.6 _IO_ftrylockfile F +GLIBC_2.2.6 _IO_funlockfile F +GLIBC_2.21 GLIBC_2.21 A +GLIBC_2.21 pthread_hurd_cond_timedwait_np F +GLIBC_2.21 pthread_hurd_cond_wait_np F |