diff options
Diffstat (limited to 'libpthread/sysdeps/l4')
33 files changed, 1829 insertions, 0 deletions
diff --git a/libpthread/sysdeps/l4/bits/pthread-np.h b/libpthread/sysdeps/l4/bits/pthread-np.h new file mode 100644 index 00000000..6a02bdc0 --- /dev/null +++ b/libpthread/sysdeps/l4/bits/pthread-np.h @@ -0,0 +1,35 @@ +/* Non-portable functions. L4 version. + Copyright (C) 2003, 2007 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include <l4.h> + +/* Add the thread TID to the internal kernel thread pool. */ +extern int pthread_pool_add_np (l4_thread_id_t tid); + +/* Get the first thread from the pool. */ +extern l4_thread_id_t pthread_pool_get_np (void); + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/l4/hurd/bits/pthread-np.h b/libpthread/sysdeps/l4/hurd/bits/pthread-np.h new file mode 100644 index 00000000..a90793df --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/bits/pthread-np.h @@ -0,0 +1,31 @@ +/* Non-portable functions. Viengoos version. + Copyright (C) 2008 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. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +#include <hurd/addr.h> + +int pthread_setactivity_np (addr_t activity); + +#endif /* bits/pthread-np.h */ diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c b/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c new file mode 100644 index 00000000..dbf5cd7e --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. 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. */ + +/* Nothing to do. */ diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c new file mode 100644 index 00000000..579905c9 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c @@ -0,0 +1,117 @@ +/* Setup thread stack. Viengoos/i386 version. + Copyright (C) 2000, 2002, 2008 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 <l4.h> + +#include <pt-internal.h> +#include <hurd/thread.h> +#include <hurd/exceptions.h> + +/* The stack layout used on the i386 is: + + ----------------- + | ARG | + ----------------- + | START_ROUTINE | + ----------------- + | Return address | + ----------------- <- %ebp + | Frame pointer | + ----------------- + + We do the following: setup the stack to return to the entry routine. + + +*/ + +/* The stack contains: + + arg + start_routine + 0 <- fake return address + C entry_point +*/ +extern uintptr_t _pthread_entry_point; +__asm__ ("\n\ + .globl _pthread_entry_point, __pthread_entry_point\n\ +_pthread_entry_point:\n\ +__pthread_entry_point:\n\ + pushl $0\n\ + popf\n\ +\n\ + xor %ebp, %ebp\n\ + ret\n"); + +/* 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. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void *(*start_routine)(void *), void *arg, + void (*entry_point)(void *(*)(void *), void *)) +{ + uintptr_t *top; + + /* Calculate top of the new stack. */ + top = (uintptr_t *) ((uintptr_t) thread->stackaddr + thread->stacksize); + + /* Align on 0x10 for MMX operations. */ + top = (uintptr_t) top & ~0xf; + + if (start_routine) + { + /* Set up call frame. */ + *--top = (uintptr_t) arg; /* Argument to START_ROUTINE. */ + *--top = (uintptr_t) start_routine; + *--top = 0; /* Fake return address. */ + *--top = (uintptr_t) entry_point; + } + + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = (void *) &_pthread_entry_point; + thread->mcontext.sp = (void *) stack_setup (thread, start_routine, arg, + entry_point); + + if (__pthread_num_threads == 1) + return 0; + + assert (! ADDR_IS_VOID (thread->exception_area[0])); + + struct exception_page *exception_page = thread->exception_area_va; + + /* SP is set to the end of the exception area minus one word, which + is the location of the exception page. */ + exception_page->exception_handler_sp + = (uintptr_t) thread->exception_area_va + EXCEPTION_AREA_SIZE; + exception_page->exception_handler_sp -= sizeof (void *); + * (void **) exception_page->exception_handler_sp = thread->exception_area_va; + + exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; + exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c new file mode 100644 index 00000000..37ef8215 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c @@ -0,0 +1,213 @@ +/* signal-dispatch-lowlevel.c - ia32 specific signal handling functions. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <pt-internal.h> +#include <sig-internal.h> + +#include <hurd/thread.h> +#include <pthread.h> +#include <stdint.h> +#include <atomic.h> + +extern char _signal_dispatch_entry; +/* - 0(%esp) a pointer to the thread's struct signal_state. + - 4(%esp) a pointer to a siginfo_t. + - 8(%esp) is a pointer to the ss_flags field (or NULL). + - 12(%esp)+4 is the value of the sp when the thread was interrupted (intr_sp) + - 0(intr_sp) is the value of the ip when the thread was interrupted. + - 16(%esp) - 16 byte register save area +*/ +__asm__ ("\n\ + .globl _signal_dispatch_entry\n\ +_signal_dispatch_entry:\n\ + /* Save caller saved registers (16 bytes). */\n\ + mov %eax, 16(%esp)\n\ + mov %ecx, 16+4(%esp)\n\ + mov %edx, 16+8(%esp)\n\ + pushf\n\ + popl %eax\n\ + mov %eax, 16+12(%esp)\n\ +\n\ + /* Reset EFLAGS. */\n\ + cld\n\ + call signal_dispatch\n\ +\n\ + /* Get the original stack and begin restoration. */\n\ + mov 12(%esp), %edx\n\ +\n\ + /* Move the saved registers to the user stack. */\n\ + sub $16, %edx\n\ + /* eax. */\n\ + mov 16+0(%esp), %ecx\n\ + mov %ecx, 0(%edx)\n\ + /* ecx. */\n\ + mov 16+4(%esp), %ecx\n\ + mov %ecx, 4(%edx)\n\ + /* edx. */\n\ + mov 16+8(%esp), %ecx\n\ + mov %ecx, 8(%edx)\n\ + /* eflags. */\n\ + mov 16+12(%esp), %ecx\n\ + mov %ecx, 12(%edx)\n\ +\n\ + /* Get the pointer to the sigaltstack flags. */\n\ + mov 8(%esp), %ecx\n\ +\n\ + /* Restore the user stack. */\n\ + mov %edx, %esp\n\ +\n\ + /* Clear the SA_ONSTACK flag. */\n\ + and %ecx, %ecx\n\ + jz after_clear\n\ + lock; and $~1, 0(%ecx)\n\ +after_clear:\n\ +\n\ + /* Restore eflags, the scratch regs and the original sp and ip. */\n\ + popl %eax\n\ + popl %ecx\n\ + popl %edx\n\ + popf\n\ + ret\n"); + +extern char _signal_dispatch_entry_self; +/* - 0(%esp) is the return address (we ignore it) + - 4(%esp) is the sp to load + + Since we are returning to signal_dispatch_lowlevel's caller, we + also need to restore its frame pointer. */ +__asm__ ("\n\ + .globl _signal_dispatch_entry_self\n\ +_signal_dispatch_entry_self:\n\ + mov 0(%ebp), %ebp\n\ + mov 4(%esp), %esp\n\ + jmp _signal_dispatch_entry\n"); + +void +signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, + siginfo_t si) +{ + assert (pthread_mutex_trylock (&ss->lock) == EBUSY); + + struct __pthread *thread = __pthread_getid (tid); + + bool self = tid == pthread_self (); + + uintptr_t intr_sp; + + if (self) + { + /* The return address is just before the first argument. */ + intr_sp = (uintptr_t) &ss - 4; + assert (* (void **) intr_sp == __builtin_return_address (0)); + } + else + { + struct hurd_thread_exregs_in in; + memset (&in, 0, sizeof (in)); + struct hurd_thread_exregs_out out; + + error_t err; + err = rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC + | HURD_EXREGS_GET_REGS, + in, &out); + if (err) + panic ("Failed to modify thread " ADDR_FMT, + ADDR_PRINTF (thread->object)); + + intr_sp = out.sp; + + /* Push the ip on the user stack. */ + intr_sp -= 4; + * (uintptr_t *) intr_sp = out.ip; + } + + bool altstack = false; + uintptr_t sp; + if (! (ss->actions[si.si_signo - 1].sa_flags & SA_ONSTACK) + || (ss->stack.ss_flags & SS_DISABLE) + || (ss->stack.ss_flags & SS_ONSTACK)) + { + assert (! self); + sp = intr_sp; + } + else + { + /* The stack grows down. */ + sp = (uintptr_t) ss->stack.ss_sp + ss->stack.ss_size; + + /* We know intimately that SS_ONSTACK is the least significant + bit. */ + assert (SS_ONSTACK == 1); + atomic_bit_set (&ss->stack.ss_flags, 0); + + altstack = true; + } + + /* Set up the call frame for a call to signal_dispatch_entry. */ + + /* Allocate a siginfo structure on the stack. */ + sp = sp - sizeof (siginfo_t); + siginfo_t *sip = (void *) sp; + /* Copy the user supplied values. */ + *sip = si; + + /* Add space for the 4 caller saved registers. */ + sp -= 4 * sizeof (uintptr_t); + + /* Save the interrupted sp. */ + sp -= 4; + * (uintptr_t *) sp = intr_sp; + + /* Address of the ss_flags. */ + sp -= 4; + if (altstack) + * (uintptr_t *) sp = (uintptr_t) &ss->stack.ss_flags; + else + * (uintptr_t *) sp = 0; + + /* Push the parameters to signal_dispatch. */ + + /* signal info structure. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) sip; + + /* The ss. */ + sp -= 4; + * (uintptr_t *) sp = (uintptr_t) ss; + + pthread_mutex_transfer_np (&ss->lock, tid); + + if (self) + ((void (*) (uintptr_t)) &_signal_dispatch_entry_self) ((uintptr_t) sp); + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.sp = sp; + in.ip = (uintptr_t) &_signal_dispatch_entry; + + rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, + in, &out); + } +} diff --git a/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c b/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c new file mode 100644 index 00000000..754d203e --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/powerpc/pt-machdep.c @@ -0,0 +1,20 @@ +/* Machine dependent pthreads code. Hurd/PowerPC version. + Copyright (C) 2003 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. */ + +/* Nothing to do. */ diff --git a/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c b/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c new file mode 100644 index 00000000..d3cf4ec3 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/powerpc/pt-setup.c @@ -0,0 +1,93 @@ +/* Setup thread stack. Hurd/PowerPC version. + Copyright (C) 2003 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 <l4.h> + +#include <pt-internal.h> + +/* Arguments is passed in registers on the PowerPC. But the + exchange registers syscall only allows us to set the PC and the + stack pointer so we put the entry point and start function on + the stack. */ +struct start_info +{ + void (*entry_point) (void *(*)(void *), void *); + void *(*start_routine) (void *); + void *arg; +}; + +void first_entry_1 (void); + +/* Stage 1 entry function. The start_info structure is inlined on the + stack. Put values into registers and call entry function. */ +asm (" ;\ +first_entry_1: ;\ + lwz 0, 0(1) ;\ + lwz 3, 4(1) ;\ + lwz 4, 8(1) ;\ + mtctr 0 ;\ + bctrl ;\ +"); + +/* 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. We also take the + opportunity to install THREAD in our utcb. */ +static void * +stack_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + l4_word_t *top; + + /* Calculate top of the new stack. */ + top = (l4_word_t *) ((l4_word_t) thread->stackaddr + thread->stacksize); + + /* Initial stack frame. */ + top[-4] = 0; + top = top - 4; + + if (start_routine) + { + struct start_info *info = ((struct start_info *) top) - 1; + + info->entry_point = entry_point; + info->start_routine = start_routine; + info->arg = arg; + return (void *) info; + } + return top; +} + +int +__pthread_setup (struct __pthread *thread, + void (*entry_point)(void *(*)(void *), void *), + void *(*start_routine)(void *), void *arg) +{ + thread->mcontext.pc = first_entry_1; + thread->mcontext.sp = stack_setup (thread, entry_point, + start_routine, arg); + + if (l4_same_threads (thread->threadid, l4_myself ())) + l4_set_user_defined_handle ((l4_word_t) thread); + else + l4_set_user_defined_handle_of (thread->threadid, + (l4_word_t) thread); + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-block.c b/libpthread/sysdeps/l4/hurd/pt-block.c new file mode 100644 index 00000000..2315b1c4 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-block.c @@ -0,0 +1,30 @@ +/* Block a thread. Viengoos version. + Copyright (C) 2008 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 <pt-internal.h> + +#include <hurd/stddef.h> +#include <hurd/futex.h> + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + futex_wait (&thread->threadid, thread->threadid); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-kill.c b/libpthread/sysdeps/l4/hurd/pt-kill.c new file mode 100644 index 00000000..c72e82f4 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-kill.c @@ -0,0 +1,3 @@ +/* The generic version is good enough for us, however, the generic + Hurd on Mach version supplies a specialized version */ +#include "../generic/pt-kill.c" diff --git a/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c new file mode 100644 index 00000000..f2f07233 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c @@ -0,0 +1,39 @@ +/* Set a thread's activity activity. Viengoos version. + Copyright (C) 2008 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 <pt-internal.h> + +#include <hurd/addr.h> +#include <hurd/thread.h> + +int +pthread_setactivity_np (addr_t activity) +{ + struct __pthread *self = _pthread_self (); + + struct hurd_thread_exregs_in in; + in.activity = activity; + + struct hurd_thread_exregs_out out; + int err = rm_thread_exregs (ADDR_VOID, self->object, + HURD_EXREGS_SET_ACTIVITY, + in, &out); + + return err; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c b/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c new file mode 100644 index 00000000..997a0369 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate-destroy.c @@ -0,0 +1,28 @@ +/* Destroy the signal state. Hurd on L4 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/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c b/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c new file mode 100644 index 00000000..4c40fdb3 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate-init.c @@ -0,0 +1,44 @@ +/* Initialize the signal state. Hurd on L4 version. + Copyright (C) 2003, 2008 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> +#include <sig-internal.h> + +error_t +__pthread_sigstate_init (struct __pthread *thread) +{ + struct signal_state *ss = &thread->ss; + + memset (ss, 0, sizeof (*ss)); + + ss->stack.ss_flags = SS_DISABLE; + + int signo; + for (signo = 1; signo < NSIG; ++signo) + { + sigemptyset (&ss->actions[signo - 1].sa_mask); + ss->actions[signo - 1].sa_flags = SA_RESTART; + ss->actions[signo - 1].sa_handler = SIG_DFL; + ss->lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + } + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sigstate.c b/libpthread/sysdeps/l4/hurd/pt-sigstate.c new file mode 100644 index 00000000..66dd08cf --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sigstate.c @@ -0,0 +1,81 @@ +/* Set a thread's signal state. Hurd on L4 version. + Copyright (C) 2002, 2005, 2008 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 <pt-internal.h> + +error_t +__pthread_sigstate (struct __pthread *thread, int how, + const sigset_t *set, sigset_t *oset, + int clear_pending) +{ + struct signal_state *ss = &thread->ss; + pthread_mutex_lock (&ss->lock); + + if (oset) + *oset = ss->blocked; + + if (set) + { + /* Mask out SIGKILL and SIGSTOP. */ + sigset_t s = *set; + sigdelset (&s, SIGKILL); + sigdelset (&s, SIGSTOP); + + switch (how) + { + case SIG_BLOCK: + ss->blocked |= s; + break; + case SIG_UNBLOCK: + ss->blocked &= ~s; + break; + case SIG_SETMASK: + ss->blocked = s; + break; + default: + errno = EINVAL; + pthread_mutex_unlock (&ss->lock); + return -1; + } + } + + if (clear_pending) + sigemptyset (&ss->pending); + + /* A "signal shall remain pending until it is unblocked" (2.4.1). + + "If there are any pending unblocked signals after the call to + sigprocmask(), at least one of those signals shall be delivered + before the call to sigprocmask() returns." + (pthread_sigmask). */ + sigset_t extant = ~ss->blocked & ss->pending; + if (! extant) + extant = ~ss->blocked & process_pending; + + pthread_mutex_unlock (&ss->lock); + + if (extant) + raise (l4_lsb64 (extant)); + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-startup.c b/libpthread/sysdeps/l4/hurd/pt-startup.c new file mode 100644 index 00000000..b6461de7 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-startup.c @@ -0,0 +1,30 @@ +/* Thread initialization. Hurd/L4 version. + Copyright (C) 2007 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 <l4.h> +#include <pt-internal.h> + +#include <hurd/exceptions.h> + +void +__pthread_startup (void) +{ + struct __pthread *pthread = _pthread_self (); + pthread->threadid = l4_myself (); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.c b/libpthread/sysdeps/l4/hurd/pt-sysdep.c new file mode 100644 index 00000000..c23364c7 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.c @@ -0,0 +1,61 @@ +/* System dependent pthreads code. Hurd version. + Copyright (C) 2000, 2008 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 <pt-internal.h> + +int +sched_yield (void) +{ + l4_yield (); + return 0; +} + +/* Forward. */ +static void init_routine (void (*) (void *), void *) + __attribute__ ((noreturn)); + +/* OK, the name of this variable isn't really appropriate, but I don't + want to change it yet. */ +void (*_pthread_init_routine)(void (*) (void *), 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 (*entry) (void *), void *arg) +{ + /* Initialize the library. */ + __pthread_initialize (); + + struct __pthread *thread; + int err; + + /* Create the pthread structure for the main thread (i.e. us). */ + err = __pthread_create_internal (&thread, 0, + (void *(*)(void *)) entry, arg); + assert_perror (err); + + /* Switch stacks. */ + l4_start_sp_ip (l4_myself (), thread->mcontext.sp, + thread->mcontext.pc); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.h b/libpthread/sysdeps/l4/hurd/pt-sysdep.h new file mode 100644 index 00000000..08bcd143 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.h @@ -0,0 +1,61 @@ +/* Internal definitions for pthreads library. + Copyright (C) 2000, 2002, 2005, 2007, 2008 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 <l4.h> +#include <hurd/storage.h> +#include <sys/mman.h> + +/* XXX */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* The default stack size: 2MB. */ +#define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) + +#include <hurd/exceptions.h> + +#define EXCEPTION_AREA_SIZE EXCEPTION_STACK_SIZE +#define EXCEPTION_AREA_SIZE_LOG2 EXCEPTION_STACK_SIZE_LOG2 +/* The exception page is the first object. */ +#define EXCEPTION_PAGE 0 + +#define PTHREAD_SYSDEP_MEMBERS \ + addr_t object; \ + l4_thread_id_t threadid; \ + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; \ + void *exception_area_va; \ + l4_word_t my_errno; + +extern inline struct __pthread * +__attribute__((__always_inline__)) +_pthread_self (void) +{ + return (struct __pthread *) l4_user_defined_handle (); +} + +extern inline void +__attribute__((__always_inline__)) +__pthread_stack_dealloc (void *stackaddr, size_t stacksize) +{ + munmap (stackaddr, stacksize); +} + +#endif /* pt-sysdep.h */ diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c new file mode 100644 index 00000000..ada7b3b8 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c @@ -0,0 +1,95 @@ +/* Allocate kernel thread. Viengoos version. + Copyright (C) 2007, 2008 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 <hurd/startup.h> +#include <hurd/storage.h> +#include <hurd/as.h> +#include <hurd/addr.h> + +#include <pt-internal.h> + +extern struct hurd_startup_data *__hurd_startup_data; + +extern addr_t meta_data_activity; + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + { + thread->object = __hurd_startup_data->thread; + thread->threadid = l4_myself (); + return 0; + } + else + { + addr_t exception_area = as_alloc (EXCEPTION_AREA_SIZE_LOG2, 1, true); + + thread->exception_area_va + = ADDR_TO_PTR (addr_extend (exception_area, + 0, EXCEPTION_AREA_SIZE_LOG2)); + + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va + + i * PAGESIZE), + PAGESIZE_LOG2); + as_ensure (slot); + + struct storage storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_LONG_LIVED, + OBJECT_POLICY_DEFAULT, + slot); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < i; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + + thread->exception_area[i] = storage.addr; + } + + struct storage storage; + storage = storage_alloc (meta_data_activity, cap_thread, + /* Threads are rarely shortly lived. */ + STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, + ADDR_VOID); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < EXCEPTION_AREA_SIZE / PAGESIZE; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + + thread->object = storage.addr; + } + + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c new file mode 100644 index 00000000..98fefaab --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c @@ -0,0 +1,104 @@ +/* Deallocate the kernel thread resources. Viengoos version. + Copyright (C) 2007, 2008 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 <pt-internal.h> + +#include <hurd/exceptions.h> +#include <hurd/mutex.h> +#include <hurd/as.h> +#include <hurd/addr.h> + +/* If we try to deallocate our self, we will end up causing a + deadlock. Thus, when a thread tries to free itself, we add it + here. The next thread to free a thread will free it. */ +ss_mutex_t saved_object_lock; +static addr_t saved_object; + +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + /* We may deallocate THREAD. First save any data we need. */ + + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; + memcpy (exception_area, thread->exception_area, + sizeof (thread->exception_area)); + memset (thread->exception_area, 0, sizeof (thread->exception_area)); + + void *va = thread->exception_area_va; + + addr_t object = thread->object; + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + /* The THREAD data structure is no longer valid. */ + thread = NULL; + + /* Deallocate any saved object. */ + ss_mutex_lock (&saved_object_lock); + if (! ADDR_IS_VOID (saved_object)) + { + storage_free (saved_object, false); + saved_object = ADDR_VOID; + } + ss_mutex_unlock (&saved_object_lock); + + /* Free the exception area. */ + + /* Clean up the exception page. */ + exception_page_cleanup + (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE], + 0, PAGESIZE_LOG2))); + + /* Free the storage. */ + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + assert (! ADDR_IS_VOID (exception_area[i])); + storage_free (exception_area[i], false); + } + + /* And the address space. */ + as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false); + + if (tid == l4_myself ()) + /* If we try to storage_free (storage.addr), we will freeze in the + middle. That's no good. We set SAVED_OBJECT to our thread + object and the next thread in will free us. */ + { + ss_mutex_lock (&saved_object_lock); + saved_object = object; + ss_mutex_unlock (&saved_object_lock); + } + else + storage_free (object, false); + + if (tid == l4_myself ()) + { + l4_send_timeout (l4_myself (), L4_NEVER); + panic ("Failed to stop thread %x.%x!", + l4_thread_no (l4_myself ()), l4_version (l4_myself ())); + } + else + thread_stop (object); +} diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-start.c b/libpthread/sysdeps/l4/hurd/pt-thread-start.c new file mode 100644 index 00000000..9db399ce --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-thread-start.c @@ -0,0 +1,70 @@ +/* Start thread. L4 version. + Copyright (C) 2007 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 <hurd/thread.h> +#include <hurd/exceptions.h> + +#include <pt-internal.h> + +int +__pthread_thread_start (struct __pthread *thread) +{ + error_t err; + + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + l4_set_user_defined_handle ((l4_word_t) thread); + } + else + { + struct hurd_thread_exregs_in in; + struct hurd_thread_exregs_out out; + + in.aspace = ADDR (0, 0); + in.aspace_cap_properties = CAP_PROPERTIES_VOID; + in.aspace_cap_properties_flags = CAP_COPY_COPY_SOURCE_GUARD; + + in.activity = ADDR_VOID; + + in.exception_page = addr_chop (PTR_TO_ADDR (thread->exception_area_va), + PAGESIZE_LOG2); + + in.sp = (l4_word_t) thread->mcontext.sp; + in.ip = (l4_word_t) thread->mcontext.pc; + + in.user_handle = (l4_word_t) thread; + err = rm_thread_exregs (ADDR_VOID, thread->object, + HURD_EXREGS_SET_ASPACE + | HURD_EXREGS_SET_ACTIVITY + | HURD_EXREGS_SET_EXCEPTION_PAGE + | HURD_EXREGS_SET_SP_IP + | HURD_EXREGS_SET_USER_HANDLE + | HURD_EXREGS_START + | HURD_EXREGS_ABORT_IPC, + in, &out); + assert (err == 0); + } + return 0; +} diff --git a/libpthread/sysdeps/l4/hurd/pt-wakeup.c b/libpthread/sysdeps/l4/hurd/pt-wakeup.c new file mode 100644 index 00000000..e568a6f9 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/pt-wakeup.c @@ -0,0 +1,46 @@ +/* Wakeup a thread. Viengoos version. + Copyright (C) 2008 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 <pt-internal.h> + +#include <hurd/stddef.h> +#include <hurd/futex.h> +#include <stdint.h> + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + /* We need to loop here as the blocked thread may not yet be + blocked! Here's what happens when a thread blocks: it registers + itself as blocked, drops the relevant lock and then actually + blocks (via __pthread_block). This means that after dropping the + lock and before blocking, it may be interrupted and another + thread may try to wake it. */ + long ret; + do + { + ret = futex_wake (&thread->threadid, INT_MAX); + assertx (ret <= 1, "tid: %x, ret: %d", thread->threadid, ret); + + if (ret == 0) + l4_thread_switch (thread->threadid); + } + while (ret == 0); +} diff --git a/libpthread/sysdeps/l4/hurd/sig-sysdep.h b/libpthread/sysdeps/l4/hurd/sig-sysdep.h new file mode 100644 index 00000000..33e13857 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/sig-sysdep.h @@ -0,0 +1,69 @@ +/* sig-sysdep.h - Hurd system specific header file. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <l4.h> +#include <string.h> + +struct utcb +{ + l4_word_t saved_sender; + l4_word_t saved_receiver; + l4_word_t saved_timeout; + l4_word_t saved_error_code; + l4_word_t saved_flags; + l4_word_t saved_br0; + l4_msg_t saved_message; +}; + +static inline void +utcb_state_save (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + buffer->saved_sender = utcb[_L4_UTCB_SENDER]; + buffer->saved_receiver = utcb[_L4_UTCB_RECEIVER]; + buffer->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; + buffer->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; + buffer->saved_flags = utcb[_L4_UTCB_FLAGS]; + buffer->saved_br0 = utcb[_L4_UTCB_BR0]; + memcpy (&buffer->saved_message, + utcb, L4_NUM_MRS * sizeof (l4_word_t)); +} + +static inline void +utcb_state_restore (struct utcb *buffer) +{ + l4_word_t *utcb = _L4_utcb (); + + utcb[_L4_UTCB_SENDER] = buffer->saved_sender; + utcb[_L4_UTCB_RECEIVER] = buffer->saved_receiver; + utcb[_L4_UTCB_TIMEOUT] = buffer->saved_timeout; + utcb[_L4_UTCB_ERROR_CODE] = buffer->saved_error_code; + utcb[_L4_UTCB_FLAGS] = buffer->saved_flags; + utcb[_L4_UTCB_BR0] = buffer->saved_br0; + memcpy (utcb, &buffer->saved_message, + L4_NUM_MRS * sizeof (l4_word_t)); +} + +#define SIGNAL_DISPATCH_ENTRY \ + struct utcb buffer; utcb_state_save (&buffer); + +#define SIGNAL_DISPATCH_EXIT \ + utcb_state_restore (&buffer); diff --git a/libpthread/sysdeps/l4/hurd/sigprocmask.c b/libpthread/sysdeps/l4/hurd/sigprocmask.c new file mode 100644 index 00000000..a38b3795 --- /dev/null +++ b/libpthread/sysdeps/l4/hurd/sigprocmask.c @@ -0,0 +1,41 @@ +/* sigprocmask.c - Generic sigprocmask implementation. + Copyright (C) 2008 Free Software Foundation, Inc. + Written by Neal H. Walfield <neal@gnu.org>. + + This file is part of the GNU Hurd. + + The GNU Hurd 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 3 of + the License, or (at your option) any later version. + + The GNU Hurd 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 this program. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <pt-internal.h> +#include <sig-internal.h> + +int +sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict old) +{ + struct __pthread *thread = _pthread_self (); + if (! thread) + /* Library is initializing. */ + { + assert (__pthread_num_threads == 1); + + /* We should get the default mask from the startup data structure. */ + if (old) + *old = 0; + + return 0; + } + + return pthread_sigmask (how, set, old); +} diff --git a/libpthread/sysdeps/l4/pt-block.c b/libpthread/sysdeps/l4/pt-block.c new file mode 100644 index 00000000..69e1d358 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-block.c @@ -0,0 +1,47 @@ +/* Block a thread. L4 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 <l4.h> + +#include <pt-internal.h> + +#include <hurd/stddef.h> + +/* Block THREAD. */ +void +__pthread_block (struct __pthread *thread) +{ + debug (5, "%x.%x/%x blocking", + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); + l4_msg_tag_t tag = l4_receive (l4_anythread); + if (l4_ipc_failed (tag)) + { + debug (1, "%x.%x failed to block: %d, offset: %x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + (l4_error_code () >> 1) & 0x7, + l4_error_code () >> 4); + assert (! l4_ipc_failed (tag)); + } + else + debug (5, "%x.%x unblocked", + l4_thread_no (thread->threadid), l4_version (thread->threadid)); +} diff --git a/libpthread/sysdeps/l4/pt-docancel.c b/libpthread/sysdeps/l4/pt-docancel.c new file mode 100644 index 00000000..a3965d0d --- /dev/null +++ b/libpthread/sysdeps/l4/pt-docancel.c @@ -0,0 +1,42 @@ +/* Cancel a thread. + Copyright (C) 2002, 2007 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 (l4_is_thread_equal (l4_myself (), p->threadid)) + call_exit (); + else + l4_start_sp_ip (p->threadid, (l4_word_t) p->mcontext.sp, + (l4_word_t) call_exit); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-pool-np.c b/libpthread/sysdeps/l4/pt-pool-np.c new file mode 100644 index 00000000..e83022ba --- /dev/null +++ b/libpthread/sysdeps/l4/pt-pool-np.c @@ -0,0 +1,54 @@ +/* Thread pool for L4 threads. + Copyright (C) 2004, 2007 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 <pt-internal.h> +#include <l4/thread.h> + +static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; + +_L4_thread_id_t pool_list = l4_nilthread; + +/* Add the thread TID to the pthread kernel thread pool. */ +int +pthread_pool_add_np (l4_thread_id_t tid) +{ + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + l4_set_user_defined_handle_of (tid, pool_list); + pool_list = tid; + __pthread_mutex_unlock (&pool_lock); + + return 0; +} + + +/* Get the first thread from the pool. */ +l4_thread_id_t +pthread_pool_get_np (void) +{ + _L4_thread_id_t tid; + + __pthread_mutex_lock (&pool_lock); + /* FIXME: Do error checking. */ + tid = pool_list; + if (tid != l4_nilthread) + pool_list = l4_user_defined_handle_of (tid); + __pthread_mutex_unlock (&pool_lock); + return tid; +} diff --git a/libpthread/sysdeps/l4/pt-spin.c b/libpthread/sysdeps/l4/pt-spin.c new file mode 100644 index 00000000..b6978b0c --- /dev/null +++ b/libpthread/sysdeps/l4/pt-spin.c @@ -0,0 +1,63 @@ +/* Spin locks. L4 version. + Copyright (C) 2000, 2004 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 <l4.h> + +#include <pthread.h> +#include <sched.h> + +/* The default for single processor machines; don't spin, it's + pointless. */ +#ifndef __PTHREAD_SPIN_COUNT +# define __PTHREAD_SPIN_COUNT 1 +#endif + +/* The number of times to spin while trying to lock a spin lock object + before yielding the processor. */ +int __pthread_spin_count = __PTHREAD_SPIN_COUNT; + + +/* 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) +{ + l4_time_t timeout; + int i; + + /* Start with a small timeout of 2 microseconds, then back off + exponentially. */ + timeout = l4_time_period (2); + + while (1) + { + for (i = 0; i < __pthread_spin_count; i++) + { + if (__pthread_spin_trylock (lock) == 0) + return 0; + } + l4_sleep (timeout); + + timeout = l4_time_mul2 (timeout); + if (timeout == L4_NEVER) + timeout = L4_TIME_PERIOD_MAX; + } +} + +weak_alias (_pthread_spin_lock, pthread_spin_lock); diff --git a/libpthread/sysdeps/l4/pt-stack-alloc.c b/libpthread/sysdeps/l4/pt-stack-alloc.c new file mode 100644 index 00000000..b7ec12b4 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-stack-alloc.c @@ -0,0 +1,43 @@ +/* Allocate a new stack. L4 Hurd version. + Copyright (C) 2000, 2007 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 <l4.h> +#include <errno.h> + +#include <pt-internal.h> + +#include <sys/mman.h> + +/* 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) +{ + void *buffer = mmap (0, stacksize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buffer == MAP_FAILED) + return EAGAIN; + + *stackaddr = buffer; + + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-thread-alloc.c b/libpthread/sysdeps/l4/pt-thread-alloc.c new file mode 100644 index 00000000..ec69afb5 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-alloc.c @@ -0,0 +1,43 @@ +/* Allocate kernel thread. L4 version. + Copyright (C) 2003, 2005 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 <pt-internal.h> + +int +__pthread_thread_alloc (struct __pthread *thread) +{ + error_t err; + + /* The main thread is already running of course. */ + if (__pthread_num_threads == 1) + thread->threadid = l4_myself (); + else + { + thread->threadid = pthread_pool_get_np (); + if (thread->threadid != l4_nilthread) + return 0; + + return EAGAIN; + } + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-thread-dealloc.c b/libpthread/sysdeps/l4/pt-thread-dealloc.c new file mode 100644 index 00000000..c09e4860 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-dealloc.c @@ -0,0 +1,32 @@ +/* Deallocate the kernel thread resources. L4 version. + Copyright (C) 2005 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 <l4.h> + +#include <pt-internal.h> + +/* Deallocate any kernel resources associated with THREAD except don't + halt the thread itself. On return, the thread will be marked as + dead and __pthread_halt will be called. */ +void +__pthread_thread_dealloc (struct __pthread *thread) +{ +} diff --git a/libpthread/sysdeps/l4/pt-thread-halt.c b/libpthread/sysdeps/l4/pt-thread-halt.c new file mode 100644 index 00000000..aa2bf43d --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-halt.c @@ -0,0 +1,45 @@ +/* Deallocate the kernel thread resources. L4version. + Copyright (C) 2000, 2002, 2004 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 <pt-internal.h> + +/* Deallocate the kernel thread resources associated with THREAD. */ +void +__pthread_thread_halt (struct __pthread *thread, int need_dealloc) +{ + l4_thread_id_t tid = thread->threadid; + + if (need_dealloc) + __pthread_dealloc (thread); + + /* There is potential race here: once if TID is the current thread, + then once we add TID to the pool, someone can reallocate it + before we call stop. However, to start the thread, the caller + atomically starts and sets the sp and ip, thus, if the stop has + not yet executed at that point, it won't. */ + + if (tid != l4_myself ()) + l4_stop (tid); + pthread_pool_add_np (tid); + if (tid == l4_myself ()) + l4_stop (tid); +} diff --git a/libpthread/sysdeps/l4/pt-thread-start.c b/libpthread/sysdeps/l4/pt-thread-start.c new file mode 100644 index 00000000..144c58bb --- /dev/null +++ b/libpthread/sysdeps/l4/pt-thread-start.c @@ -0,0 +1,40 @@ +/* Start thread. L4 version. + Copyright (C) 2003, 2004, 2007 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 <pt-internal.h> + +/* Start THREAD. Get the kernel thread scheduled and running. */ +int +__pthread_thread_start (struct __pthread *thread) +{ + if (__pthread_num_threads == 1) + /* The main thread is already running of course. */ + { + assert (__pthread_total == 1); + assert (l4_is_thread_equal (l4_myself (), thread->threadid)); + } + else + l4_start_sp_ip (thread->threadid, (l4_word_t) thread->mcontext.sp, + (l4_word_t) thread->mcontext.pc); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-timedblock.c b/libpthread/sysdeps/l4/pt-timedblock.c new file mode 100644 index 00000000..ce7972bd --- /dev/null +++ b/libpthread/sysdeps/l4/pt-timedblock.c @@ -0,0 +1,35 @@ +/* Block a thread with a timeout. L4 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 <pt-internal.h> + +/* Block THREAD. */ +error_t +__pthread_timedblock (struct __pthread *thread, + const struct timespec *abstime) +{ +#warning Need gettimeofday to implement properly. + __pthread_block (thread); + return 0; +} diff --git a/libpthread/sysdeps/l4/pt-wakeup.c b/libpthread/sysdeps/l4/pt-wakeup.c new file mode 100644 index 00000000..de378465 --- /dev/null +++ b/libpthread/sysdeps/l4/pt-wakeup.c @@ -0,0 +1,54 @@ +/* Wakeup a thread. L4 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 <l4.h> + +#include <pt-internal.h> + +#include <hurd/stddef.h> + +/* Wakeup THREAD. */ +void +__pthread_wakeup (struct __pthread *thread) +{ + debug (5, "%x.%x/%x waking %x.%x/%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), l4_myself (), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + thread->threadid); + + /* Signal the waiter. */ + l4_msg_t msg; + l4_msg_clear (msg); + l4_msg_set_untyped_words (msg, 0); + l4_msg_load (msg); + + l4_msg_tag_t tag = l4_send (thread->threadid); + if (l4_ipc_failed (tag)) + { + int err = l4_error_code (); + debug (1, "%x.%x failed to wake %x.%x: %s (%d)", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid), + l4_strerror (err), err); + } + else + debug (5, "%x.%x woke %x.%x", + l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + l4_thread_no (thread->threadid), l4_version (thread->threadid)); +} |