diff options
author | Neal H. Walfield <neal@gnu.org> | 2002-10-10 23:05:06 +0000 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2002-10-10 23:05:06 +0000 |
commit | 51c55d85632d43aa362b625ae519d00d559f9e5c (patch) | |
tree | 2efb73388ae81c46c1475bcb3133b879a0176bf1 /sysdeps/mach |
Import libpthread.
Diffstat (limited to 'sysdeps/mach')
-rw-r--r-- | sysdeps/mach/bits/spin-lock.h | 97 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/pt-machdep.c | 54 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/pt-setup.c | 99 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-attr-setstackaddr.c | 35 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-attr-setstacksize.c | 35 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-docancel.c | 57 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sigstate-destroy.c | 28 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sigstate-init.c | 37 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sigstate.c | 69 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sysdep.c | 72 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-sysdep.h | 65 | ||||
-rw-r--r-- | sysdeps/mach/pt-block.c | 39 | ||||
-rw-r--r-- | sysdeps/mach/pt-spin.c | 35 | ||||
-rw-r--r-- | sysdeps/mach/pt-stack-alloc.c | 74 | ||||
-rw-r--r-- | sysdeps/mach/pt-start.c | 106 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-alloc.c | 98 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-halt.c | 39 | ||||
-rw-r--r-- | sysdeps/mach/pt-thread-start.c | 45 | ||||
-rw-r--r-- | sysdeps/mach/pt-timedblock.c | 60 | ||||
-rw-r--r-- | sysdeps/mach/pt-wakeup.c | 38 |
20 files changed, 1182 insertions, 0 deletions
diff --git a/sysdeps/mach/bits/spin-lock.h b/sysdeps/mach/bits/spin-lock.h new file mode 100644 index 0000000..f295df7 --- /dev/null +++ b/sysdeps/mach/bits/spin-lock.h @@ -0,0 +1,97 @@ +/* Definitions of user-visible names for spin locks. + Copyright (C) 1994, 1997, 2002 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SPIN_LOCK_H +#define _BITS_SPIN_LOCK_H 1 + +#include <features.h> +#include <machine-lock.h> /* This does all the work. */ + +__BEGIN_DECLS + +/* The type of a spin lock object. */ +typedef __spin_lock_t __pthread_spinlock_t; + +/* Initializer for a spin lock object. */ +#ifndef __SPIN_LOCK_INITIALIZER +#error __SPIN_LOCK_INITIALIZER undefined: should be defined by <lock-intern.h>. +#endif + +#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 = __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 (__lock) ? 0 : __EBUSY; +} + +extern inline int __pthread_spin_lock (__pthread_spinlock_t *__lock); +extern int _pthread_spin_lock (__pthread_spinlock_t *__lock); + +extern inline int +__pthread_spin_lock (__pthread_spinlock_t *__lock) +{ + if (__pthread_spin_trylock (__lock)) + return _pthread_spin_lock (__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 (__lock); + return 0; +} + +#endif /* Use extern inlines or force inlines. */ + +__END_DECLS + +#endif /* bits/spin-lock.h */ diff --git a/sysdeps/mach/hurd/i386/pt-machdep.c b/sysdeps/mach/hurd/i386/pt-machdep.c new file mode 100644 index 0000000..face46c --- /dev/null +++ b/sysdeps/mach/hurd/i386/pt-machdep.c @@ -0,0 +1,54 @@ +/* Machine dependent pthreads code. Hurd/i386 version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> + +#include <mach.h> +#include <mach/i386/thread_status.h> +#include <mach/thread_status.h> + +int +__thread_set_pcsp (thread_t thread, + int set_ip, void *ip, + int set_sp, void *sp) +{ + 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_THREAD_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; + + err = __thread_set_state (thread, i386_THREAD_STATE, + (thread_state_t) &state, + i386_THREAD_STATE_COUNT); + if (err) + return err; + + return 0; +} diff --git a/sysdeps/mach/hurd/i386/pt-setup.c b/sysdeps/mach/hurd/i386/pt-setup.c new file mode 100644 index 0000000..a249504 --- /dev/null +++ b/sysdeps/mach/hurd/i386/pt-setup.c @@ -0,0 +1,99 @@ +/* Setup thread stack. Hurd/i386 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdint.h> +#include <assert.h> + +#include <pt-internal.h> + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | 0 | + ----------------- + | | + | Fast TSD | + | | + ----------------- + + We need to reserve __hurd_threadvar_max `unsigned long int's' of + (fast) thread-specific data (TSD) for the Hurd. */ + +/* 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); + + /* Next, make room for the TSDs. */ + top -= __hurd_threadvar_max; + + /* Save the self pointer. */ + top[_HURD_THREADVAR_THREAD] = thread; + + if (start_routine) + { + /* And then the call frame. */ + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; + *--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)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + error_t err; + + thread->mcontext.pc = entry_point; + thread->mcontext.sp = stack_setup (thread, start_routine, arg); + + if (thread->kernel_thread != __mach_thread_self ()) + { + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/hurd/pt-attr-setstackaddr.c b/sysdeps/mach/hurd/pt-attr-setstackaddr.c new file mode 100644 index 0000000..1225ed5 --- /dev/null +++ b/sysdeps/mach/hurd/pt-attr-setstackaddr.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstackaddr. Hurd on Mach version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> +#include <pt-internal.h> + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstackaddr (pthread_attr_t *attr, + void *stackaddr) +{ + if ((long) stackaddr & (__pthread_stacksize - 1)) + return EINVAL; + + attr->stackaddr = stackaddr; + return 0; +} diff --git a/sysdeps/mach/hurd/pt-attr-setstacksize.c b/sysdeps/mach/hurd/pt-attr-setstacksize.c new file mode 100644 index 0000000..6471c0a --- /dev/null +++ b/sysdeps/mach/hurd/pt-attr-setstacksize.c @@ -0,0 +1,35 @@ +/* pthread_attr_setstacksize. Hurd on Mach version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> +#include <pt-internal.h> + +/* We use fixed sized stacks which require proper alignment. */ +#define __pthread_stacksize __pthread_default_attr.stacksize + +int +pthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize) +{ + if (stacksize != __pthread_stacksize) + return EINVAL; + + attr->stacksize = stacksize; + return 0; +} diff --git a/sysdeps/mach/hurd/pt-docancel.c b/sysdeps/mach/hurd/pt-docancel.c new file mode 100644 index 0000000..58524ff --- /dev/null +++ b/sysdeps/mach/hurd/pt-docancel.c @@ -0,0 +1,57 @@ +/* Cancel a thread. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> + +#include <pt-internal.h> + +static void +call_exit (void) +{ + pthread_exit (0); +} + +int +__pthread_do_cancel (struct __pthread *p) +{ + assert (p->cancel_pending = 1); + assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); + + if (__mach_thread_self () == p->kernel_thread) + 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_pcsp (p->kernel_thread, + 1, (void *) call_exit, 0, 0); + assert_perror (err); + + err = __thread_resume (p->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/hurd/pt-sigstate-destroy.c b/sysdeps/mach/hurd/pt-sigstate-destroy.c new file mode 100644 index 0000000..8e56c5c --- /dev/null +++ b/sysdeps/mach/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on Mach version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> + +#include <pt-internal.h> + +void +__pthread_sigstate_destroy (struct __pthread *thread) +{ + /* Nothing to do. */ +} diff --git a/sysdeps/mach/hurd/pt-sigstate-init.c b/sysdeps/mach/hurd/pt-sigstate-init.c new file mode 100644 index 0000000..da5a945 --- /dev/null +++ b/sysdeps/mach/hurd/pt-sigstate-init.c @@ -0,0 +1,37 @@ +/* Initialize the signal state. Hurd on Mach version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> +#include <hurd/threadvar.h> + +#include <pt-internal.h> + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + void **location = + (void *) __hurd_threadvar_location_from_sp (_HURD_THREADVAR_SIGSTATE, + thread->stackaddr); + + /* The real initialization happens internally in glibc the first + time that _hurd_thead_sigstate is called. */ + *location = 0; + + return 0; +} diff --git a/sysdeps/mach/hurd/pt-sigstate.c b/sysdeps/mach/hurd/pt-sigstate.c new file mode 100644 index 0000000..68c79c5 --- /dev/null +++ b/sysdeps/mach/hurd/pt-sigstate.c @@ -0,0 +1,69 @@ +/* Set a thread's signal state. Hurd on Mach version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <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); + + __pthread_spin_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + 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; + } + + if (! err && clear_pending) + __sigemptyset (&ss->pending); + + __pthread_spin_unlock (&ss->lock); + + return err; +} diff --git a/sysdeps/mach/hurd/pt-sysdep.c b/sysdeps/mach/hurd/pt-sysdep.c new file mode 100644 index 0000000..b42fe25 --- /dev/null +++ b/sysdeps/mach/hurd/pt-sysdep.c @@ -0,0 +1,72 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <stddef.h> +#include <stdint.h> + +#include <mach.h> +#include <mach/mig_support.h> + +#include <hurd/threadvar.h> + +#include <pt-internal.h> + +/* Forward. */ +static int init_routine (void); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +int (*_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 int +init_routine (void) +{ + struct __pthread *thread; + int err; + + /* Initialize the library. */ + __pthread_initialize (); + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, 0, 0); + assert_perror (err); + + ((void **) (__hurd_threadvar_stack_offset))[_HURD_THREADVAR_THREAD] + = 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); + + /* Make sure we can find the per-thread variables. */ + __hurd_threadvar_stack_mask = ~(__pthread_default_attr.stacksize - 1); + __hurd_threadvar_stack_offset + = (__pthread_default_attr.stacksize + - __hurd_threadvar_max * sizeof (uintptr_t)); + + return (int) thread->mcontext.sp; +} diff --git a/sysdeps/mach/hurd/pt-sysdep.h b/sysdeps/mach/hurd/pt-sysdep.h new file mode 100644 index 0000000..3addef7 --- /dev/null +++ b/sysdeps/mach/hurd/pt-sysdep.h @@ -0,0 +1,65 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_SYSDEP_H +#define _PT_SYSDEP_H 1 + +#include <mach.h> + +#include <hurd/threadvar.h> + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#define PTHREAD_SYSDEP_MEMBERS \ + thread_t kernel_thread; \ + mach_msg_header_t wakeupmsg; + +#define _HURD_THREADVAR_THREAD _HURD_THREADVAR_DYNAMIC_USER + +#define _pthread_self() \ + ({ \ + struct __pthread *thread; \ + \ + assert (__pthread_threads); \ + thread = *(struct __pthread **) \ + __hurd_threadvar_location (_HURD_THREADVAR_THREAD); \ + \ + assert (thread); \ + assert (thread->kernel_thread == __mach_thread_self ()); \ + thread; \ + }) + +extern inline void +__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 and + its stack pointer to SP if SET_IP is true. */ +extern int __thread_set_pcsp (thread_t thread, + int set_pc, void *pc, + int set_sp, void *sp); + + +#endif /* pt-sysdep.h */ diff --git a/sysdeps/mach/pt-block.c b/sysdeps/mach/pt-block.c new file mode 100644 index 0000000..a947b27 --- /dev/null +++ b/sysdeps/mach/pt-block.c @@ -0,0 +1,39 @@ +/* Block a thread. Mach version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> + +#include <mach.h> +#include <mach/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/pt-spin.c b/sysdeps/mach/pt-spin.c new file mode 100644 index 0000000..010faca --- /dev/null +++ b/sysdeps/mach/pt-spin.c @@ -0,0 +1,35 @@ +/* Spin locks. Mach version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> +#include <machine-lock.h> + +/* In glibc. */ +extern void __spin_lock_solid (__pthread_spinlock_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 (__pthread_spinlock_t *lock) +{ + __spin_lock_solid (lock); + return 0; +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/sysdeps/mach/pt-stack-alloc.c b/sysdeps/mach/pt-stack-alloc.c new file mode 100644 index 0000000..0956fc7 --- /dev/null +++ b/sysdeps/mach/pt-stack-alloc.c @@ -0,0 +1,74 @@ +/* Allocate a new stack. Mach version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> + +#include <mach.h> +#include <mach/machine/vm_param.h> + +#include <pt-internal.h> + +#define __pthread_stacksize __pthread_default_attr.stacksize + +/* 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; + + if (stacksize != __pthread_stacksize) + return EINVAL; + + get_stack: + i ++; + for (base = next_stack_base; + base < VM_MAX_ADDRESS + && __vm_allocate (__mach_task_self (), &base, + __pthread_stacksize, FALSE) != KERN_SUCCESS; + base += __pthread_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 + __pthread_stacksize; + + (*stackaddr) = (void *) base; + return 0; +} diff --git a/sysdeps/mach/pt-start.c b/sysdeps/mach/pt-start.c new file mode 100644 index 0000000..5e8cd5a --- /dev/null +++ b/sysdeps/mach/pt-start.c @@ -0,0 +1,106 @@ +/* Start thread. Mach version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> +#include <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_deallocate (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + return 0; +} + +/* Start THREAD. We allocate all system-specific resources, including + a kernel thread, set it up, and get it running. */ +int +__pthread_start (struct __pthread *thread) +{ + error_t err; + + err = create_wakeupmsg (thread); + if (err) + return err; + + /* If there are no pthreads in the system then the pthread library + is bootstrapping and the main thread must create initialize + itself. The thread itself is already running, it just has no + pthread context. We want to reuse what it already has (including + the kernel thread), however, we must determine which thread is + the main thread. + + We cannot test if __pthread_total is one as we later decrement it + before creating the signal thread. Currently, we check if + __pthread_num_threads--the number of allocated thread + structures--is one. __pthread_alloc has already been called in + __pthread_create_internal for us. This predicate could be + improved, however, it is sufficient for now. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 1); + thread->kernel_thread = __mach_thread_self (); + } + else + { + err = __thread_create (__mach_task_self (), &thread->kernel_thread); + if (err) + return EAGAIN; + + err = __thread_set_pcsp (thread->kernel_thread, + 1, thread->mcontext.pc, + 1, thread->mcontext.sp); + assert_perror (err); + + err = __thread_resume (thread->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/pt-thread-alloc.c b/sysdeps/mach/pt-thread-alloc.c new file mode 100644 index 0000000..af92953 --- /dev/null +++ b/sysdeps/mach/pt-thread-alloc.c @@ -0,0 +1,98 @@ +/* Start thread. Mach version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> +#include <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_deallocate (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + return EAGAIN; + } + + 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) +{ + error_t err; + + err = create_wakeupmsg (thread); + if (err) + return err; + + /* If there are no pthreads in the system then the pthread library + is bootstrapping and the main thread must create initialize + itself. The thread itself is already running, it just has not + pthread context. We want to reuse what it already has (including + the kernel thread), however, we must determine which thread is + the main thread. + + We cannot test if __pthread_total is one as we later decrement + before creating the signal thread. Currently, we check if + __pthread_num_threads--the number of allocated thread + structures--is one. __pthread_alloc has already been called in + __pthread_create_internal for us. This predicate could be improved, + however, it is sufficient for now. */ + if (__pthread_num_threads == 1) + { + assert (__pthread_total == 0); + thread->kernel_thread = __mach_thread_self (); + } + else + { + err = __thread_create (__mach_task_self (), &thread->kernel_thread); + if (err) + return EAGAIN; + } + + return 0; +} diff --git a/sysdeps/mach/pt-thread-halt.c b/sysdeps/mach/pt-thread-halt.c new file mode 100644 index 0000000..84e6ac8 --- /dev/null +++ b/sysdeps/mach/pt-thread-halt.c @@ -0,0 +1,39 @@ +/* Deallocate the kernel thread resources. Mach version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> +#include <mach.h> + +#include <pt-internal.h> + + +/* Deallocate the kernel thread resources associated with THREAD. */ +void +__pthread_thread_halt (struct __pthread *thread) +{ + error_t err; + + err = __mach_port_deallocate (__mach_task_self (), + thread->wakeupmsg.msgh_remote_port); + assert_perror (err); + + err = __thread_terminate (thread->kernel_thread); + assert_perror (err); +} diff --git a/sysdeps/mach/pt-thread-start.c b/sysdeps/mach/pt-thread-start.c new file mode 100644 index 0000000..eade509 --- /dev/null +++ b/sysdeps/mach/pt-thread-start.c @@ -0,0 +1,45 @@ +/* Start thread. Mach version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> +#include <mach.h> + +#include <pt-internal.h> + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + { + /* The main thread is already running: do nothing. */ + assert (__pthread_total == 1); + assert (thread->kernel_thread == __mach_thread_self ()); + } + else + { + err = __thread_resume (thread->kernel_thread); + assert_perror (err); + } + + return 0; +} diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c new file mode 100644 index 0000000..6324ae7 --- /dev/null +++ b/sysdeps/mach/pt-timedblock.c @@ -0,0 +1,60 @@ +/* Block a thread with a timeout. Mach version. + Copyright (C) 2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> +#include <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) +{ + error_t err; + mach_msg_header_t msg; + mach_msg_timeout_t ms; + struct timeval now; + + /* We have an absolute time and now we have to convert it to a + relative time. Arg. */ + + err = gettimeofday(&now, NULL); + assert (! err); + + ms = abstime->tv_sec * 1000 + (abstime->tv_nsec + 999999) / 1000000 + - now.tv_sec * 1000 - (now.tv_usec + 999) / 1000; + + if (ms <= 0) + return ETIMEDOUT; + + err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, + sizeof msg, thread->wakeupmsg.msgh_remote_port, + ms, MACH_PORT_NULL); + if (err == EMACH_RCV_TIMED_OUT) + return ETIMEDOUT; + + assert_perror (err); + return 0; +} diff --git a/sysdeps/mach/pt-wakeup.c b/sysdeps/mach/pt-wakeup.c new file mode 100644 index 0000000..8ab10fb --- /dev/null +++ b/sysdeps/mach/pt-wakeup.c @@ -0,0 +1,38 @@ +/* Wakeup a thread. Mach version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <assert.h> +#include <errno.h> + +#include <mach.h> +#include <mach/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, + sizeof (mach_msg_header_t), 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + assert_perror (err); +} |