diff options
Diffstat (limited to 'linuxthreads/sysdeps')
180 files changed, 14801 insertions, 0 deletions
diff --git a/linuxthreads/sysdeps/alpha/elf/pt-initfini.c b/linuxthreads/sysdeps/alpha/elf/pt-initfini.c new file mode 100644 index 0000000000..ee25582101 --- /dev/null +++ b/linuxthreads/sysdeps/alpha/elf/pt-initfini.c @@ -0,0 +1,90 @@ +/* Special .init and .fini section support for Alpha. Linuxthreads version. + Copyright (C) 2002, 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 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. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the .init and .fini + sections and defines global symbols for those addresses, so they can be + called as functions. + + * crtn.s puts the corresponding function epilogues in the .init and .fini + sections. + + This differs from what would be generated by the generic code in that + we save and restore the GP within the function. In order for linker + relaxation to work, the value in the GP register on exit from a function + must be valid for the function entry point. Normally, a function is + contained within one object file and this is not an issue, provided + that the function reloads the gp after making any function calls. + However, _init and _fini are constructed from pieces of many object + files, all of which may have different GP values. So we must reload + the GP value from crti.o in crtn.o. */ + +__asm__ (" \n\ +#include \"defs.h\" \n\ + \n\ +/*@HEADER_ENDS*/ \n\ + \n\ +/*@_init_PROLOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + .globl _init \n\ + .type _init,@function \n\ + .usepv _init,std \n\ +_init: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + jsr $26, __pthread_initialize_minimal \n\ + ldq $29, 8($30) \n\ + .align 3 \n\ +/*@_init_PROLOG_ENDS*/ \n\ + \n\ +/*@_init_EPILOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_init_EPILOG_ENDS*/ \n\ + \n\ +/*@_fini_PROLOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + .globl _fini \n\ + .type _fini,@function \n\ + .usepv _fini,std \n\ +_fini: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + .align 3 \n\ +/*@_fini_PROLOG_ENDS*/ \n\ + \n\ +/*@_fini_EPILOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_fini_EPILOG_ENDS*/ \n\ + \n\ +/*@TRAILER_BEGINS*/ \n\ +"); diff --git a/linuxthreads/sysdeps/alpha/pspinlock.c b/linuxthreads/sysdeps/alpha/pspinlock.c new file mode 100644 index 0000000000..79b7836293 --- /dev/null +++ b/linuxthreads/sysdeps/alpha/pspinlock.c @@ -0,0 +1,110 @@ +/* POSIX spinlock implementation. Alpha 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 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; 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 <pthread.h> +#include "internals.h" + + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int tmp; + asm volatile + ("1: ldl_l %0,%1\n" + " blbs %0,2f\n" + " or %0,1,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + " mb\n" + ".subsection 2\n" + "2: ldl %0,%1\n" + " blbs %0,2b\n" + " br 1b\n" + ".previous" + : "=r" (tmp), "=m" (lock) + : "m" (lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned long int oldval; + unsigned long int temp; + + asm volatile + ("1: ldl_l %0,%1\n" + " and %0,%3,%2\n" + " bne %2,2f\n" + " xor %0,%3,%0\n" + " stl_c %0,%1\n" + " beq %0,3f\n" + " mb\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r" (temp), "=m" (*lock), "=&r" (oldval) + : "Ir" (1UL), "m" (*lock)); + + return oldval == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile ("mb"); + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/alpha/pt-machine.h b/linuxthreads/sysdeps/alpha/pt-machine.h new file mode 100644 index 0000000000..853ac6f04a --- /dev/null +++ b/linuxthreads/sysdeps/alpha/pt-machine.h @@ -0,0 +1,128 @@ +/* Machine-dependent pthreads configuration and inline functions. + Alpha version. + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +#ifdef __linux__ +# include <asm/pal.h> +#else +# include <machine/pal.h> +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__("$30"); + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory") + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret, temp; + + __asm__ __volatile__( + "/* Inline spinlock test & set */\n" + "1:\t" + "ldl_l %0,%3\n\t" + "bne %0,2f\n\t" + "or $31,1,%1\n\t" + "stl_c %1,%2\n\t" + "beq %1,1b\n" + "2:\tmb\n" + "/* End spinlock test & set */" + : "=&r"(ret), "=&r"(temp), "=m"(*spinlock) + : "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Begin allocating thread stacks at this address. Default is to allocate + them just below the initial program stack. */ +#define THREAD_STACK_START_ADDRESS 0x40000000000 + + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self __asm__("$0"); \ + __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ +{ \ + register pthread_descr __self __asm__("$16") = (descr); \ + __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \ +} + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "/* Inline compare & swap */\n" + "1:\t" + "ldq_l %0,%4\n\t" + "cmpeq %0,%2,%0\n\t" + "beq %0,2f\n\t" + "mov %3,%0\n\t" + "stq_c %0,%1\n\t" + "beq %0,1b\n\t" + "2:\tmb\n" + "/* End compare & swap */" + : "=&r"(ret), "=m"(*p) + : "r"(oldval), "r"(newval), "m"(*p) + : "memory"); + + return ret; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/alpha/tls.h b/linuxthreads/sysdeps/alpha/tls.h new file mode 100644 index 0000000000..261d333eb4 --- /dev/null +++ b/linuxthreads/sysdeps/alpha/tls.h @@ -0,0 +1,129 @@ +/* Definitions for thread-local data handling. linuxthreads/Alpha version. + Copyright (C) 2002, 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 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 _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include <pt-machine.h> +# include <stddef.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + dtv_t *dtv; + + /* Reserved for the thread implementation. Unused in LinuxThreads. */ + void *private; +} tcbhead_t; +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) \ + (((tcbhead_t *) (TCBP))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + (__builtin_set_thread_pointer (TCBP), 0) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr)__builtin_thread_pointer () - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + __builtin_set_thread_pointer ((struct _pthread_descr_struct *)(DESCR) + 1) + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +/* ??? Generic bits of LinuxThreads may call these macros with + DESCR set to NULL. We are expected to be able to reference + the "current" value. + + In our case, we'd really prefer to use DESCR, since lots of + PAL_code calls would be expensive. We can only trust that + the compiler does its job and unifies the multiple + __builtin_thread_pointer instances. */ + +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/arm/pspinlock.c b/linuxthreads/sysdeps/arm/pspinlock.c new file mode 100644 index 0000000000..665e270b69 --- /dev/null +++ b/linuxthreads/sysdeps/arm/pspinlock.c @@ -0,0 +1,82 @@ +/* POSIX spinlock implementation. Arm 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 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; 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 <pthread.h> +#include "internals.h" + + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + asm volatile ("swp %0, %1, [%2]" + : "=r" (val) + : "0" (1), "r" (lock) + : "memory"); + while (val != 0); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + asm volatile ("swp %0, %1, [%2]" + : "=r" (val) + : "0" (1), "r" (lock) + : "memory"); + + return val ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/arm/pt-machine.h b/linuxthreads/sysdeps/arm/pt-machine.h new file mode 100644 index 0000000000..a4c2f314cb --- /dev/null +++ b/linuxthreads/sysdeps/arm/pt-machine.h @@ -0,0 +1,55 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <philb@gnu.org>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* This will not work on ARM1 or ARM2 because SWP is lacking on those + machines. Unfortunately we have no way to detect this at compile + time; let's hope nobody tries to use one. */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + register unsigned int ret; + + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/cris/pspinlock.c b/linuxthreads/sysdeps/cris/pspinlock.c new file mode 100644 index 0000000000..402e838c00 --- /dev/null +++ b/linuxthreads/sysdeps/cris/pspinlock.c @@ -0,0 +1,72 @@ +/* POSIX spinlock implementation. CRIS version. + Copyright (C) 2000, 2001 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; 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 <pthread.h> +#include "internals.h" + +/* FIXME: These are just dummies. I don't know why or if they're needed; + configury should default to these definitions. We just follow the + crowd here. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (testandset (lock) != 0) + ; + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return testandset (lock) != 0 ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/cris/pt-machine.h b/linuxthreads/sysdeps/cris/pt-machine.h new file mode 100644 index 0000000000..431da7101d --- /dev/null +++ b/linuxthreads/sysdeps/cris/pt-machine.h @@ -0,0 +1,58 @@ +/* Machine-dependent pthreads configuration and inline functions. + CRIS version. + Copyright (C) 2001, 2002, 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 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +PT_EI long int +testandset (int *spinlock) +{ + register unsigned long int ret; + + /* Note the use of a dummy output of *spinlock to expose the write. The + memory barrier is to stop *other* writes being moved past this code. */ + __asm__ __volatile__("clearf\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bwf 0b\n\t" + "clearf" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1) + : "memory"); + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + I don't trust register variables, so let's do this the safe way. */ +#define CURRENT_STACK_FRAME \ + ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/hppa/pspinlock.c b/linuxthreads/sysdeps/hppa/pspinlock.c new file mode 100644 index 0000000000..7f481fa4b6 --- /dev/null +++ b/linuxthreads/sysdeps/hppa/pspinlock.c @@ -0,0 +1,81 @@ +/* POSIX spinlock implementation. hppa 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 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; 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 <pthread.h> +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + asm volatile ("ldcw %1,%0" + : "=r" (val), "=m" (*lock) + : "m" (*lock)); + while (!val); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + asm volatile ("ldcw %1,%0" + : "=r" (val), "=m" (*lock) + : "m" (*lock)); + + return val ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/hppa/pt-machine.h b/linuxthreads/sysdeps/hppa/pt-machine.h new file mode 100644 index 0000000000..abc25c4ca4 --- /dev/null +++ b/linuxthreads/sysdeps/hppa/pt-machine.h @@ -0,0 +1,62 @@ +/* Machine-dependent pthreads configuration and inline functions. + hppa version. + Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#include <bits/initspin.h> + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%r30"); + + +/* The hppa only has one atomic read and modify memory operation, + load and clear, so hppa spinlocks must use zero to signify that + someone is holding the lock. */ + +#define xstr(s) str(s) +#define str(s) #s +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "ldcw 0(%2),%0" + : "=r"(ret), "=m"(*spinlock) + : "r"(spinlock)); + + return ret == 0; +} +#undef str +#undef xstr + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/i386/Makefile b/linuxthreads/sysdeps/i386/Makefile new file mode 100644 index 0000000000..418fa5c6ef --- /dev/null +++ b/linuxthreads/sysdeps/i386/Makefile @@ -0,0 +1,23 @@ +ifeq ($(subdir),linuxthreads) +# On i686 we must avoid generating the trampoline functions generated +# to get the GOT pointer. +CFLAGS-pt-initfini.s += -march=i386 -mcpu=i386 + +# Most files must not be compiled without frame pointer since we need +# the frame base address which is stored in %ebp unless the frame pointer +# is optimized out. +CFLAGS-cancel.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4 +CFLAGS-condvar.c += -fno-omit-frame-pointer +CFLAGS-join.c += -fno-omit-frame-pointer +CFLAGS-manager.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4 +CFLAGS-oldsemaphore.c += -fno-omit-frame-pointer +CFLAGS-pthread.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4 +CFLAGS-ptlongjmp.c += -fno-omit-frame-pointer +CFLAGS-semaphore.c += -fno-omit-frame-pointer +CFLAGS-sighandler.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4 +CFLAGS-tst-align.c += -mpreferred-stack-boundary=4 +endif + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/linuxthreads/sysdeps/i386/i586/Versions b/linuxthreads/sysdeps/i386/i586/Versions new file mode 100644 index 0000000000..32da57080d --- /dev/null +++ b/linuxthreads/sysdeps/i386/i586/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_PRIVATE { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/i386/i686/Versions b/linuxthreads/sysdeps/i386/i686/Versions new file mode 100644 index 0000000000..32da57080d --- /dev/null +++ b/linuxthreads/sysdeps/i386/i686/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_PRIVATE { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/i386/i686/pt-machine.h b/linuxthreads/sysdeps/i386/i686/pt-machine.h new file mode 100644 index 0000000000..1c75bf9807 --- /dev/null +++ b/linuxthreads/sysdeps/i386/i686/pt-machine.h @@ -0,0 +1,79 @@ +/* Machine-dependent pthreads configuration and inline functions. + i686 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif +#include "kernel-features.h" + +#ifndef __ASSEMBLER__ +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %0, %1" + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} +#endif + +#if __ASSUME_LDT_WORKS > 0 +#include "../useldt.h" +#endif + +/* The P4 and above really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/i386/pspinlock.c b/linuxthreads/sysdeps/i386/pspinlock.c new file mode 100644 index 0000000000..6a70093957 --- /dev/null +++ b/linuxthreads/sysdeps/i386/pspinlock.c @@ -0,0 +1,103 @@ +/* POSIX spinlock implementation. x86 version. + Copyright (C) 2000, 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; 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 <pthread.h> +#include "internals.h" +#include "kernel-features.h" + + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + asm volatile + ("\n" + "1:\n\t" + "lock; decl %0\n\t" + "js 2f\n\t" + ".section .text.spinlock,\"ax\"\n" + "2:\n\t" + "cmpl $0,%0\n\t" + "rep; nop\n\t" + "jle 2b\n\t" + "jmp 1b\n\t" + ".previous" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + asm volatile + ("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0)); + return oldval > 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile + ("movl $1,%0" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) + +#ifndef __ASSUME_SET_THREAD_AREA_SYSCALL +int __have_no_set_thread_area; +#endif diff --git a/linuxthreads/sysdeps/i386/pt-machine.h b/linuxthreads/sysdeps/i386/pt-machine.h new file mode 100644 index 0000000000..0df096d152 --- /dev/null +++ b/linuxthreads/sysdeps/i386/pt-machine.h @@ -0,0 +1,108 @@ +/* Machine-dependent pthreads configuration and inline functions. + i386 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. + Available on the 486 and above, but not on the 386. + We test dynamically whether it's available or not. */ + +#define HAS_COMPARE_AND_SWAP +#define TEST_FOR_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + + +PT_EI int +get_eflags (void) +{ + int res; + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : ); + return res; +} + + +PT_EI void +set_eflags (int newflags) +{ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc"); +} + + +PT_EI int +compare_and_swap_is_available (void) +{ + int oldflags = get_eflags (); + int changed; + /* Flip AC bit in EFLAGS. */ + set_eflags (oldflags ^ 0x40000); + /* See if bit changed. */ + changed = (get_eflags () ^ oldflags) & 0x40000; + /* Restore EFLAGS. */ + set_eflags (oldflags); + /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. + Otherwise, it's a 486 or above and it has cmpxchg. */ + return changed != 0; +} +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/i386/tcb-offsets.sym b/linuxthreads/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 0000000000..69a5018d88 --- /dev/null +++ b/linuxthreads/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,7 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#ifdef NEED_DL_SYSINFO +SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo) +#endif diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h new file mode 100644 index 0000000000..5306d082bb --- /dev/null +++ b/linuxthreads/sysdeps/i386/tls.h @@ -0,0 +1,225 @@ +/* Definition for thread-local data handling. linuxthreads/i386 version. + Copyright (C) 2002, 2003, 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 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 _TLS_H +#define _TLS_H + +# include <dl-sysdep.h> +# include <pt-machine.h> + +#ifndef __ASSEMBLER__ +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +#ifdef NEED_DL_SYSINFO + uintptr_t sysinfo; +#endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + +/* We can support TLS only if the floating-stack support is available. + However, we want to compile in the support and test at runtime whether + the running kernel can support it or not. To avoid bothering with the + TLS support code at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h conditionals. + But some of the code below can cause problems in building libpthread + (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't). */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +# if !defined IS_IN_linuxthreads && !defined DO_MODIFY_LDT +# include "useldt.h" /* For the structure. */ +# endif +# if __ASSUME_LDT_WORKS > 0 +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) (doit) /* Nothing to check. */ +# else +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) \ + (__builtin_expect (GLRO(dl_osversion) < 131939, 0) \ + ? "kernel too old for thread-local storage support\n" \ + : (doit)) +# endif + +# define TLS_DO_MODIFY_LDT(descr, nr) \ +TLS_DO_MODIFY_LDT_KERNEL_CHECK( \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + asm volatile (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result) \ + : "0" (__NR_modify_ldt), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ + "d" (sizeof (ldt_entry))); \ + __builtin_expect (result, 0) == 0 \ + ? ({ asm ("movw %w0, %%gs" : : "q" ((nr) * 8 + 7)); NULL; }) \ + : "cannot set up LDT for thread-local storage\n"; \ +})) + +# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + if (secondcall) \ + ldt_entry.entry_number = ({ int _gs; \ + asm ("movw %%gs, %w0" : "=q" (_gs)); \ + (_gs & 0xffff) >> 3; }); \ + asm volatile (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result), "=m" (ldt_entry.entry_number) \ + : "0" (__NR_set_thread_area), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ + if (__builtin_expect (result, 0) == 0) \ + asm ("movw %w0, %%gs" : : "q" (ldt_entry.entry_number * 8 + 3)); \ + result; \ +}) + +# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + (TLS_DO_SET_THREAD_AREA (descr, secondcall) \ + ? "set_thread_area failed when setting up thread-local storage\n" : NULL) +# elif defined __NR_set_thread_area +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + (TLS_DO_SET_THREAD_AREA (descr, secondcall) \ + ? TLS_DO_MODIFY_LDT (descr, 0) : NULL) +# else +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_MODIFY_LDT ((descr), 0) +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The value of this macro is null if successful, or an error string. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + INIT_SYSINFO; \ + TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/i386/useldt.h b/linuxthreads/sysdeps/i386/useldt.h new file mode 100644 index 0000000000..4ac82f1ab0 --- /dev/null +++ b/linuxthreads/sysdeps/i386/useldt.h @@ -0,0 +1,314 @@ +/* Special definitions for ix86 machine using segment register based + thread descriptor. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>. + + 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; 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 __ASSEMBLER__ +#include <stddef.h> /* For offsetof. */ +#include <stdlib.h> /* For abort(). */ +#include <sysdep.h> + + +/* We don't want to include the kernel header. So duplicate the + information. */ + +/* Structure passed on `modify_ldt' call. */ +struct modify_ldt_ldt_s +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* System call to set LDT entry. */ +extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + + +/* Initialize the thread-unique value. Two possible ways to do it. */ + +#define DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ + abort (); \ + asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ +}) + +#ifdef __PIC__ +# define USETLS_EBX_ARG "r" +# define USETLS_LOAD_EBX "xchgl %1, %%ebx\n\t" +#else +# define USETLS_EBX_ARG "b" +# define USETLS_LOAD_EBX +#endif + +/* When using the new set_thread_area call, we don't need to change %gs + because we inherited the value set up in the main thread by TLS setup. + We need to extract that value and set up the same segment in this + thread. */ +#if USE_TLS +# define DO_SET_THREAD_AREA_REUSE(nr) 1 +#else +/* Without TLS, we do the initialization of the main thread, where NR == 0. */ +# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr)) +#endif +#define DO_SET_THREAD_AREA(descr, nr) \ +({ \ + int __gs; \ + if (DO_SET_THREAD_AREA_REUSE (nr)) \ + { \ + asm ("movw %%gs, %w0" : "=q" (__gs)); \ + struct modify_ldt_ldt_s ldt_entry = \ + { (__gs & 0xffff) >> 3, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + \ + int __result; \ + __asm (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "=&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area), \ + "m" (ldt_entry) \ + : "memory"); \ + if (__result == 0) \ + asm ("movw %w0, %%gs" :: "q" (__gs)); \ + else \ + __gs = -1; \ + } \ + else \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int __result; \ + __asm (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "=&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area), \ + "m" (ldt_entry) \ + : "memory"); \ + if (__result == 0) \ + { \ + __gs = (ldt_entry.entry_number << 3) + 3; \ + asm ("movw %w0, %%gs" : : "q" (__gs)); \ + } \ + else \ + __gs = -1; \ + } \ + __gs; \ +}) + +#if defined __ASSUME_SET_THREAD_AREA_SYSCALL +# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr) +#elif defined __NR_set_thread_area +# define INIT_THREAD_SELF(descr, nr) \ +({ \ + if (__builtin_expect (__have_no_set_thread_area, 0) \ + || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \ + && (__have_no_set_thread_area = 1))) \ + DO_MODIFY_LDT (descr, nr); \ +}) +/* Defined in pspinlock.c. */ +extern int __have_no_set_thread_area; +#else +# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr) +#endif + +/* Free resources associated with thread descriptor. */ +#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +#define FREE_THREAD(descr, nr) do { } while (0) +#elif defined __NR_set_thread_area +#define FREE_THREAD(descr, nr) \ +{ \ + int __gs; \ + __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \ + if (__builtin_expect (__gs & 4, 0)) \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ + } \ +} +#else +#define FREE_THREAD(descr, nr) \ +{ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ +} +#endif + +/* Read member of the thread descriptor directly. */ +#define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +#define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +#define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ +}) + +/* Set member of the thread descriptor directly. */ +#define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) +#endif + +#if __ASSUME_LDT_WORKS > 0 +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 +#endif diff --git a/linuxthreads/sysdeps/ia64/Makefile b/linuxthreads/sysdeps/ia64/Makefile new file mode 100644 index 0000000000..81bddf688c --- /dev/null +++ b/linuxthreads/sysdeps/ia64/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/linuxthreads/sysdeps/ia64/Versions b/linuxthreads/sysdeps/ia64/Versions new file mode 100644 index 0000000000..32da57080d --- /dev/null +++ b/linuxthreads/sysdeps/ia64/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_PRIVATE { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/ia64/pspinlock.c b/linuxthreads/sysdeps/ia64/pspinlock.c new file mode 100644 index 0000000000..14c7f3a181 --- /dev/null +++ b/linuxthreads/sysdeps/ia64/pspinlock.c @@ -0,0 +1,79 @@ +/* POSIX spinlock implementation. ia64 version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen <jes@linuxcare.com> + + 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; 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 <pthread.h> +#include "internals.h" +#include <ia64intrin.h> + +/* This implementation is inspired by the implementation used in the + Linux kernel. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + int *p = (int *) lock; + + while (__builtin_expect (__sync_val_compare_and_swap_si (p, 0, 1), 0)) + { + /* Spin without using the atomic instruction. */ + do + __asm __volatile ("" : : : "memory"); + while (*p); + } + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __sync_val_compare_and_swap_si ((int *) lock, 0, 1) == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/ia64/pt-machine.h b/linuxthreads/sysdeps/ia64/pt-machine.h new file mode 100644 index 0000000000..6c5dfe93bb --- /dev/null +++ b/linuxthreads/sysdeps/ia64/pt-machine.h @@ -0,0 +1,133 @@ +/* Machine-dependent pthreads configuration and inline functions. + IA-64 version. + Copyright (C) 1999, 2000, 2002, 2003, 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 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#include <ia64intrin.h> + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Make sure gcc doesn't try to be clever and move things around on + us. We need to use _exactly_ the address the user gave us, not some + alias that contains the same information. */ +#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) + +#ifndef ELF_MACHINE_NAME + +#define NEED_SEPARATE_REGISTER_STACK + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + r12 (sp) is the stack pointer. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__ ("sp"); + + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + + +/* Memory barrier */ +#define MEMORY_BARRIER() __sync_synchronize () + + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.acq %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, + long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.rel %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +#endif /* ELF_MACHINE_NAME */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchg4 %0=%1,%2" + : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock)) + : "r"(1), "m"(__atomic_fool_gcc (spinlock)) + : "memory"); + + return ret; +} + +/* Indicate that we are looping. */ +#define BUSY_WAIT_NOP __asm__ ("hint @pause") + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/ia64/tcb-offsets.sym b/linuxthreads/sysdeps/ia64/tcb-offsets.sym new file mode 100644 index 0000000000..f7793f7665 --- /dev/null +++ b/linuxthreads/sysdeps/ia64/tcb-offsets.sym @@ -0,0 +1,9 @@ +#include <sysdep.h> +#include <tls.h> + +-- +#ifdef USE_TLS +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) - sizeof (struct _pthread_descr_struct) +#else +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#endif diff --git a/linuxthreads/sysdeps/ia64/tls.h b/linuxthreads/sysdeps/ia64/tls.h new file mode 100644 index 0000000000..3ec2eda783 --- /dev/null +++ b/linuxthreads/sysdeps/ia64/tls.h @@ -0,0 +1,141 @@ +/* Definitions for thread-local data handling. linuxthreads/IA-64 version. + Copyright (C) 2002, 2003, 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 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 _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include <dl-sysdep.h> +# include <pt-machine.h> +# include <stddef.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo)) +#else +# define INIT_SYSINFO 0 +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF (__thread_self - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +# endif + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/m68k/Makefile b/linuxthreads/sysdeps/m68k/Makefile new file mode 100644 index 0000000000..1cd27d44ca --- /dev/null +++ b/linuxthreads/sysdeps/m68k/Makefile @@ -0,0 +1,7 @@ +ifeq ($(subdir), linuxthreads) +object-suffixes-left := $(libpthread-nonshared) +define o-iterator-doit +$(objpfx)$o.os: pic-ccflag = -fPIC +endef +include $(o-iterator) +endif diff --git a/linuxthreads/sysdeps/m68k/pspinlock.c b/linuxthreads/sysdeps/m68k/pspinlock.c new file mode 100644 index 0000000000..30b9b9e8b9 --- /dev/null +++ b/linuxthreads/sysdeps/m68k/pspinlock.c @@ -0,0 +1,82 @@ +/* POSIX spinlock implementation. M68k 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 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; 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 <pthread.h> +#include "internals.h" + + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + asm volatile ("tas %1; sne %0" + : "=dm" (val), "=m" (*lock) + : "m" (*lock) + : "cc"); + while (val); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + asm volatile ("tas %1; sne %0" + : "=dm" (val), "=m" (*lock) + : "m" (*lock) + : "cc"); + + return val ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/m68k/pt-machine.h b/linuxthreads/sysdeps/m68k/pt-machine.h new file mode 100644 index 0000000000..ad524d6d2e --- /dev/null +++ b/linuxthreads/sysdeps/m68k/pt-machine.h @@ -0,0 +1,69 @@ +/* Machine-dependent pthreads configuration and inline functions. + m68k version. + Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__("tas %1; sne %0" + : "=dm"(ret), "=m"(*spinlock) + : "m"(*spinlock) + : "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("casl %2, %3, %1; seq %0" + : "=dm" (ret), "=m" (*p), "=d" (readval) + : "d" (newval), "m" (*p), "2" (oldval)); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/mips/pspinlock.c b/linuxthreads/sysdeps/mips/pspinlock.c new file mode 100644 index 0000000000..350aa7553c --- /dev/null +++ b/linuxthreads/sysdeps/mips/pspinlock.c @@ -0,0 +1,98 @@ +/* POSIX spinlock implementation. MIPS version. + Copyright (C) 2000, 2002, 2003, 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 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; 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 <pthread.h> +#include <sgidefs.h> +#include <sys/tas.h> +#include "internals.h" + +#include <sgidefs.h> + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int tmp1, tmp2; + + asm volatile + ("\t\t\t# spin_lock\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif + "ll %1,%3\n\t" + "li %2,1\n\t" + "bnez %1,1b\n\t" + "sc %2,%0\n\t" + ".set pop\n\t" + "beqz %2,1b" + : "=m" (*lock), "=&r" (tmp1), "=&r" (tmp2) + : "m" (*lock) + : "memory"); + + return 0; +} + +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + /* To be done. */ + return 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile + ("\t\t\t# spin_unlock\n\t" + "sw $0,%0" + : "=m" (*lock) + : + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/mips/pt-machine.h b/linuxthreads/sysdeps/mips/pt-machine.h new file mode 100644 index 0000000000..96f7a7f8c6 --- /dev/null +++ b/linuxthreads/sysdeps/mips/pt-machine.h @@ -0,0 +1,92 @@ +/* Machine-dependent pthreads configuration and inline functions. + + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle <ralf@gnu.org>. + Based on the Alpha version by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#include <sgidefs.h> +#include <sys/tas.h> + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + + +/* Spinlock implementation; required. */ + +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set (spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("$29"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret, temp; + + __asm__ __volatile__ + ("/* Inline compare & swap */\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif +#if _MIPS_SIM == _ABI64 + "lld %1,%5\n\t" +#else + "ll %1,%5\n\t" +#endif + "move %0,$0\n\t" + "bne %1,%3,2f\n\t" + "move %0,%4\n\t" +#if _MIPS_SIM == _ABI64 + "scd %0,%2\n\t" +#else + "sc %0,%2\n\t" +#endif + ".set pop\n\t" + "beqz %0,1b\n" + "2:\n\t" + "/* End compare & swap */" + : "=&r" (ret), "=&r" (temp), "=m" (*p) + : "r" (oldval), "r" (newval), "m" (*p) + : "memory"); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/powerpc/Makefile b/linuxthreads/sysdeps/powerpc/Makefile new file mode 100644 index 0000000000..33e4aceb5b --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/Makefile @@ -0,0 +1,7 @@ +ifeq ($(subdir):$(elf),linuxthreads:yes) +# See CFLAGS-initfini.s above; this is the same code. +CFLAGS-pt-initfini.s = -g0 -fpic -O1 +endif +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c b/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c new file mode 100644 index 0000000000..15fd545c14 --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c @@ -0,0 +1,70 @@ +/* POSIX spinlock implementation. PowerPC version. + Copyright (C) 2000, 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 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; 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 <pthread.h> +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (! __compare_and_swap ((long int *)lock, 0, 1)) + ; + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __compare_and_swap ((long int *)lock, 0, 1) ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + MEMORY_BARRIER (); + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h b/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h new file mode 100644 index 0000000000..8363d16d08 --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h @@ -0,0 +1,120 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 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 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; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r2"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return ret == 0; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return ret == 0; +} + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c b/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c new file mode 100644 index 0000000000..19161c6e10 --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c @@ -0,0 +1,70 @@ +/* POSIX spinlock implementation. PowerPC version. + Copyright (C) 2000, 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 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; 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 <pthread.h> +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (! __compare_and_swap32 ((int *)lock, 0, 1)) + ; + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __compare_and_swap32 ((int *)lock, 0, 1) ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + MEMORY_BARRIER (); + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h b/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h new file mode 100644 index 0000000000..562e69fa18 --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h @@ -0,0 +1,185 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 2002, 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. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); +extern int __compare_and_swap32 (int *p, int oldval, int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define READ_MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__ ("eieio" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 16*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32 (int *p, int oldval, int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI long int +testandset (int *p) +{ + long int ret, val = 1; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " cmpwi 0,%0,0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r" (val) + : "cr0", "memory"); + MEMORY_BARRIER (); + return ret != 0; +} + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/powerpc/tcb-offsets.sym b/linuxthreads/sysdeps/powerpc/tcb-offsets.sym new file mode 100644 index 0000000000..b526b62336 --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/tcb-offsets.sym @@ -0,0 +1,19 @@ +#include <sysdep.h> +#include <tls.h> + +-- This line separates the #include lines from conditionals. + +# ifdef USE_TLS + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register ((void *) 0) +# define thread_offsetof(mem) ((void *) &THREAD_SELF->p_##mem - (void *) 0) + +# else + +# define thread_offsetof(mem) offsetof (tcbhead_t, mem) + +# endif + +MULTIPLE_THREADS_OFFSET thread_offsetof (multiple_threads) diff --git a/linuxthreads/sysdeps/powerpc/tls.h b/linuxthreads/sysdeps/powerpc/tls.h new file mode 100644 index 0000000000..f6eb48b434 --- /dev/null +++ b/linuxthreads/sysdeps/powerpc/tls.h @@ -0,0 +1,160 @@ +/* Definitions for thread-local data handling. linuxthreads/PPC 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 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 _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include <pt-machine.h> +# include <stddef.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +/* This layout is actually wholly private and not affected by the ABI. + Nor does it overlap the pthread data structure, so we need nothing + extra here at all. */ +typedef struct +{ + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct _pthread_descr_struct) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The following assumes that TP (R2 or R13) is points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread_descr is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +#define TLS_TCB_OFFSET 0x7000 + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +/* This is not really true for powerpc64. We are following alpha + where the DTV pointer is first doubleword in the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) (THREAD_DTV() = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) (((tcbhead_t *) (TCBP))[-1].dtv) + +/* We still need this define so that tcb-offsets.sym can override it and + use THREAD_SELF to generate MULTIPLE_THREADS_OFFSET. */ +# define __thread_register ((void *) __thread_self) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The global register variable is declared in pt-machine.h with the + wrong type, so we need some extra casts to get the desired result. + This avoids a lvalue cast that gcc-3.4 does not like. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + (__thread_self = (struct _pthread_descr_struct *) \ + ((void *) (TCBP) + TLS_TCB_OFFSET), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) ((void *) __thread_self - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + (__thread_self = (struct _pthread_descr_struct *)((void *) (DESCR) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)) + +/* Make sure we have the p_multiple_threads member in the thread structure. + See below. */ +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +# endif /* __ASSEMBLER__ */ + +#elif !defined __ASSEMBLER__ + +/* This overlaps the start of the pthread_descr. System calls + and such use this to find the multiple_threads flag and need + to use the same offset relative to the thread register in both + single-threaded and multi-threaded code. */ +typedef struct +{ + void *tcb; /* Never used. */ + dtv_t *dtv; /* Never used. */ + void *self; /* Used only if multithreaded, and rarely. */ + int multiple_threads; /* Only this member is really used. */ +} tcbhead_t; + +#define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif /* HAVE_TLS_SUPPORT */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/pthread/Makefile b/linuxthreads/sysdeps/pthread/Makefile new file mode 100644 index 0000000000..f73f40e9d9 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/Makefile @@ -0,0 +1,14 @@ +ifeq ($(subdir),rt) +librt-sysdep_routines += timer_routines +CPPFLAGS += -DBROKEN_THREAD_SIGNALS + +ifeq (yes,$(build-shared)) +$(objpfx)tst-timer: $(objpfx)librt.so $(shared-thread-library) +else +$(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library) +endif +endif + +ifeq ($(subdir),posix) +CFLAGS-confstr.c += -DLIBPTHREAD_VERSION="\"$(shell sed 's/\(.*\) by .*/\1/' ../linuxthreads/Banner)\"" +endif diff --git a/linuxthreads/sysdeps/pthread/Subdirs b/linuxthreads/sysdeps/pthread/Subdirs new file mode 100644 index 0000000000..2c56497842 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/Subdirs @@ -0,0 +1 @@ +linuxthreads_db diff --git a/linuxthreads/sysdeps/pthread/bits/initspin.h b/linuxthreads/sysdeps/pthread/bits/initspin.h new file mode 100644 index 0000000000..a19ec077e8 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/bits/initspin.h @@ -0,0 +1,28 @@ +/* Generic definitions for spinlock initializers. + Copyright (C) 2000, 2001 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. Most platforms should use zero, + unless they only implement a "test and clear" operation instead of + the usual "test and set". */ +#define __LT_SPINLOCK_INIT 0 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/linuxthreads/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 0000000000..7e22166862 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,413 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,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 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; 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 _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include <pthread.h> + +#if defined _LIBC && !defined NOT_IN_libc +#include <linuxthreads/internals.h> +#endif + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# if defined __PIC__ || (defined _LIBC && defined SHARED) +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) +#endif + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#endif +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_recursive(NAME) \ + ({ \ + (NAME).mutex.__m_count = 0; \ + (NAME).mutex.__m_owner = NULL; \ + (NAME).mutex.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ + (NAME).mutex.__m_lock.__status = 0; \ + (NAME).mutex.__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ + ++((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_default_unlock_recursive(lock) \ + --((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_lock_recursive(NAME) \ + GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ + GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME) +#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME) +#endif + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = 2; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# if _LIBC +# include <bp-sym.h> +# else +# define BP_SYM (sym) sym +# endif +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push)) +weak_extern (BP_SYM (_pthread_cleanup_pop)) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +# endif +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/linuxthreads/sysdeps/pthread/bits/libc-tsd.h b/linuxthreads/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 0000000000..fa6eb4be28 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,59 @@ +/* libc-internal interface for thread-specific data. LinuxThreads version. + Copyright (C) 1997-2002, 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 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; 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 _BITS_LIBC_TSD_H +#define _BITS_LIBC_TSD_H 1 + +#include <linuxthreads/descr.h> +#include <tls.h> + +#if USE_TLS && HAVE___THREAD + +/* When __thread works, the generic definition is what we want. */ +# include <sysdeps/generic/bits/libc-tsd.h> + +#else + +# include <bits/libc-lock.h> + +# ifndef SHARED +extern void ** __pthread_internal_tsd_address (int); +extern void *__pthread_internal_tsd_get (int); +extern int __pthread_internal_tsd_set (int, const void *); + +weak_extern (__pthread_internal_tsd_address) +weak_extern (__pthread_internal_tsd_get) +weak_extern (__pthread_internal_tsd_set) +# endif + +#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; +#define __libc_tsd_address(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_address, \ + (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data) +#define __libc_tsd_get(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_get, \ + (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data) +#define __libc_tsd_set(KEY, VALUE) \ + __libc_maybe_call2 (pthread_internal_tsd_set, \ + (_LIBC_TSD_KEY_##KEY, (VALUE)), \ + (__libc_tsd_##KEY##_data = (VALUE), 0)) + +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h new file mode 100644 index 0000000000..d1daef07aa --- /dev/null +++ b/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h @@ -0,0 +1,152 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include <bits/pthreadtypes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __need_schedparam +#include <bits/sched.h> + +/* Fast locks (not abstract because mutexes and conditions aren't abstract). */ +struct _pthread_fastlock +{ + long int __status; /* "Free" or "taken" or head of waiting list */ + int __spinlock; /* Used by compare_and_swap emulation. Also, + adaptive SMP lock stores spin count here. */ +}; + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + + +/* Attributes for threads. */ +typedef struct __pthread_attr_s +{ + int __detachstate; + int __schedpolicy; + struct __sched_param __schedparam; + int __inheritsched; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void *__stackaddr; + size_t __stacksize; +} pthread_attr_t; + + +/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ + +#ifdef __GLIBC_HAVE_LONG_LONG +__extension__ typedef long long __pthread_cond_align_t; +#else +typedef long __pthread_cond_align_t; +#endif + +typedef struct +{ + struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ + _pthread_descr __c_waiting; /* Threads waiting on this condition */ + char __padding[48 - sizeof (struct _pthread_fastlock) + - sizeof (_pthread_descr) - sizeof (__pthread_cond_align_t)]; + __pthread_cond_align_t __align; +} pthread_cond_t; + + +/* Attribute for conditionally variables. */ +typedef struct +{ + int __dummy; +} pthread_condattr_t; + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ +/* (The layout is unnatural to maintain binary compatibility + with earlier releases of LinuxThreads.) */ +typedef struct +{ + int __m_reserved; /* Reserved for future use */ + int __m_count; /* Depth of recursive locking */ + _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ + int __m_kind; /* Mutex kind: fast, recursive or errcheck */ + struct _pthread_fastlock __m_lock; /* Underlying fast lock */ +} pthread_mutex_t; + + +/* Attribute for mutex. */ +typedef struct +{ + int __mutexkind; +} pthread_mutexattr_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Read-write locks. */ +typedef struct _pthread_rwlock_t +{ + struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ + int __rw_readers; /* Number of readers */ + _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ + _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ + _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ + int __rw_kind; /* Reader/Writer preference selection */ + int __rw_pshared; /* Shared between processes or not */ +} pthread_rwlock_t; + + +/* Attribute for read-write locks. */ +typedef struct +{ + int __lockkind; + int __pshared; +} pthread_rwlockattr_t; +#endif + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barrier. */ +typedef struct { + struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ + int __ba_required; /* Threads needed for completion */ + int __ba_present; /* Threads waiting */ + _pthread_descr __ba_waiting; /* Queue of waiting threads */ +} pthread_barrier_t; + +/* barrier attribute */ +typedef struct { + int __pshared; +} pthread_barrierattr_t; + +#endif + + +/* Thread identifiers */ +typedef unsigned long int pthread_t; + +#endif /* bits/pthreadtypes.h */ diff --git a/linuxthreads/sysdeps/pthread/bits/typesizes.h b/linuxthreads/sysdeps/pthread/bits/typesizes.h new file mode 100644 index 0000000000..45264ac9cf --- /dev/null +++ b/linuxthreads/sysdeps/pthread/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 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 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_TYPES_H +# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See <bits/types.h> for the meaning of these macros. This file exists so + that <bits/types.h> need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/linuxthreads/sysdeps/pthread/errno-loc.c b/linuxthreads/sysdeps/pthread/errno-loc.c new file mode 100644 index 0000000000..0a8f0f9076 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/errno-loc.c @@ -0,0 +1,46 @@ +/* MT support function to get address of `errno' variable, linuxthreads + version. + Copyright (C) 1996, 1998, 2002, 2003, 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 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. */ + +#include <errno.h> +#include <tls.h> +#include <linuxthreads/internals.h> +#include <sysdep-cancel.h> + +#if ! USE___THREAD && !RTLD_PRIVATE_ERRNO +#undef errno +extern int errno; +#endif + +int * +#if ! USE___THREAD +weak_const_function +#endif +__errno_location (void) +{ +#if ! USE___THREAD && !defined NOT_IN_libc + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_errnop); + } +#endif + return &errno; +} +libc_hidden_def (__errno_location) diff --git a/linuxthreads/sysdeps/pthread/flockfile.c b/linuxthreads/sysdeps/pthread/flockfile.c new file mode 100644 index 0000000000..918cb84f61 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/flockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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. */ + +#include <pthread.h> +#include <stdio.h> +#include <libio.h> +#include <bits/stdio-lock.h> + + +void +__flockfile (stream) + FILE *stream; +{ + _IO_lock_lock (*stream->_lock); +} +strong_alias (__flockfile, _IO_flockfile) +weak_alias (__flockfile, flockfile) diff --git a/linuxthreads/sysdeps/pthread/ftrylockfile.c b/linuxthreads/sysdeps/pthread/ftrylockfile.c new file mode 100644 index 0000000000..21c1ea01ed --- /dev/null +++ b/linuxthreads/sysdeps/pthread/ftrylockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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. */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <bits/stdio-lock.h> + + +int +__ftrylockfile (stream) + FILE *stream; +{ + return _IO_lock_trylock (*stream->_lock); +} +strong_alias (__ftrylockfile, _IO_ftrylockfile) +weak_alias (__ftrylockfile, ftrylockfile) diff --git a/linuxthreads/sysdeps/pthread/funlockfile.c b/linuxthreads/sysdeps/pthread/funlockfile.c new file mode 100644 index 0000000000..f941fc9851 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/funlockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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. */ + +#include <pthread.h> +#include <stdio.h> +#include <libio.h> +#include <bits/stdio-lock.h> + + +void +__funlockfile (stream) + FILE *stream; +{ + _IO_lock_unlock (*stream->_lock); +} +strong_alias (__funlockfile, _IO_funlockfile) +weak_alias (__funlockfile, funlockfile) diff --git a/linuxthreads/sysdeps/pthread/getcpuclockid.c b/linuxthreads/sysdeps/pthread/getcpuclockid.c new file mode 100644 index 0000000000..032caeb081 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/getcpuclockid.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2000, 2001, 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 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; 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 <pthread.h> +#include <sys/time.h> +#include <time.h> +#include <internals.h> + +int +pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id) +{ +#ifdef CLOCK_THREAD_CPUTIME_ID + /* We need to store the thread ID in the CLOCKID variable together + with a number identifying the clock. We reserve the low 3 bits + for the clock ID and the rest for the thread ID. This is + problematic if the thread ID is too large. But 29 bits should be + fine. + + If some day more clock IDs are needed the ID part can be + enlarged. The IDs are entirely internal. */ + if (2 * PTHREAD_THREADS_MAX + >= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE)) + return ERANGE; + + /* Store the number. */ + *clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE); + + return 0; +#else + /* We don't have a timer for that. */ + return ENOENT; +#endif +} diff --git a/linuxthreads/sysdeps/pthread/herrno-loc.c b/linuxthreads/sysdeps/pthread/herrno-loc.c new file mode 100644 index 0000000000..fbc5576166 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/herrno-loc.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1996, 97, 98, 2002, 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 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. */ + +#include <netdb.h> +#include <tls.h> +#include <linuxthreads/internals.h> +#include <sysdep-cancel.h> + +#if ! USE___THREAD +# undef h_errno +extern int h_errno; +#endif + +/* When threaded, h_errno may be a per-thread variable. */ +int * +weak_const_function +__h_errno_location (void) +{ +#if ! USE___THREAD + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_h_errnop); + } +#endif + return &h_errno; +} +libc_hidden_def (__h_errno_location) diff --git a/linuxthreads/sysdeps/pthread/list.h b/linuxthreads/sysdeps/pthread/list.h new file mode 100644 index 0000000000..43186a2d51 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/list.h @@ -0,0 +1,114 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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 _LIST_H +#define _LIST_H 1 + +/* The definitions of this file are adopted from those which can be + found in the Linux kernel headers to enable people familiar with + the latter find their way in these sources as well. */ + + +/* Basic type for the double-link list. */ +typedef struct list_head +{ + struct list_head *next; + struct list_head *prev; +} list_t; + + +/* Define a variable with the head and tail of the list. */ +#define LIST_HEAD(name) \ + list_t name = { &(name), &(name) } + +/* Initialize a new list head. */ +#define INIT_LIST_HEAD(ptr) \ + (ptr)->next = (ptr)->prev = (ptr) + + +/* Add new element at the head of the list. */ +static inline void +list_add (list_t *newp, list_t *head) +{ + head->next->prev = newp; + newp->next = head->next; + newp->prev = head; + head->next = newp; +} + + +/* Add new element at the tail of the list. */ +static inline void +list_add_tail (list_t *newp, list_t *head) +{ + head->prev->next = newp; + newp->next = head; + newp->prev = head->prev; + head->prev = newp; +} + + +/* Remove element from list. */ +static inline void +list_del (list_t *elem) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + + +/* Join two lists. */ +static inline void +list_splice (list_t *add, list_t *head) +{ + /* Do nothing if the list which gets added is empty. */ + if (add != add->next) + { + add->next->prev = head; + add->prev->next = head->next; + head->next->prev = add->prev; + head->next = add->next; + } +} + + +/* Get typed element from list at a given position. */ +#define list_entry(ptr, type, member) \ + ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member))) + + + +/* Iterate forward over the elements of the list. */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/* Iterate forward over the elements of the list. */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + + +/* Iterate backwards over the elements list. The list elements can be + removed from the list while doing this. */ +#define list_for_each_prev_safe(pos, p, head) \ + for (pos = (head)->prev, p = pos->prev; \ + pos != (head); \ + pos = p, p = pos->prev) + +#endif /* list.h */ diff --git a/linuxthreads/sysdeps/pthread/malloc-machine.h b/linuxthreads/sysdeps/pthread/malloc-machine.h new file mode 100644 index 0000000000..5191f8c779 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/malloc-machine.h @@ -0,0 +1,67 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + 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 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 _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include <atomic.h> +#include <bits/libc-lock.h> + +__libc_lock_define (typedef, mutex_t) + +#define mutex_init(m) \ + __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0)) +#define mutex_lock(m) \ + __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0)) +#define mutex_trylock(m) \ + __libc_maybe_call2 (pthread_mutex_trylock, (m), \ + (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0))) +#define mutex_unlock(m) \ + __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0)) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include <fork.h> + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include <bits/libc-tsd.h> + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include <sysdeps/generic/malloc-machine.h> + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/linuxthreads/sysdeps/pthread/posix-timer.h b/linuxthreads/sysdeps/pthread/posix-timer.h new file mode 100644 index 0000000000..1b0a2b65e4 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/posix-timer.h @@ -0,0 +1,204 @@ +/* Definitions for POSIX timer implementation on top of LinuxThreads. + Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <limits.h> +#include <signal.h> + +/* Double linked list. */ +struct list_links +{ + struct list_links *next; + struct list_links *prev; +}; + + +/* Forward declaration. */ +struct timer_node; + + +/* Definitions for an internal thread of the POSIX timer implementation. */ +struct thread_node +{ + struct list_links links; + pthread_attr_t attr; + pthread_t id; + unsigned int exists; + struct list_links timer_queue; + pthread_cond_t cond; + struct timer_node *current_timer; + pthread_t captured; + clockid_t clock_id; +}; + + +/* Internal representation of a timer. */ +struct timer_node +{ + struct list_links links; + struct sigevent event; + clockid_t clock; + struct itimerspec value; + struct timespec expirytime; + pthread_attr_t attr; + unsigned int abstime; + unsigned int armed; + enum { + TIMER_FREE, TIMER_INUSE, TIMER_DELETED + } inuse; + struct thread_node *thread; + pid_t creator_pid; + int refcount; + int overrun_count; +}; + + +/* Static array with the structures for all the timers. */ +extern struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +extern pthread_mutex_t __timer_mutex; + +/* Variable to protext initialization. */ +extern pthread_once_t __timer_init_once_control; + +/* Nonzero if initialization of timer implementation failed. */ +extern int __timer_init_failed; + +/* Nodes for the threads used to deliver signals. */ +/* A distinct thread is used for each clock type. */ + +extern struct thread_node __timer_signal_thread_rclk; + + +/* Return pointer to timer structure corresponding to ID. */ +static inline struct timer_node * +timer_id2ptr (timer_t timerid) +{ + if (timerid >= 0 && timerid < TIMER_MAX) + return &__timer_array[timerid]; + + return NULL; +} + +/* Return ID of TIMER. */ +static inline int +timer_ptr2id (struct timer_node *timer) +{ + return timer - __timer_array; +} + +/* Check whether timer is valid; global mutex must be held. */ +static inline int +timer_valid (struct timer_node *timer) +{ + return timer && timer->inuse == TIMER_INUSE; +} + +/* Timer refcount functions; need global mutex. */ +extern void __timer_dealloc (struct timer_node *timer); + +static inline void +timer_addref (struct timer_node *timer) +{ + timer->refcount++; +} + +static inline void +timer_delref (struct timer_node *timer) +{ + if (--timer->refcount == 0) + __timer_dealloc (timer); +} + +/* Timespec helper routines. */ +static inline int +timespec_compare (const struct timespec *left, const struct timespec *right) +{ + if (left->tv_sec < right->tv_sec) + return -1; + if (left->tv_sec > right->tv_sec) + return 1; + + if (left->tv_nsec < right->tv_nsec) + return -1; + if (left->tv_nsec > right->tv_nsec) + return 1; + + return 0; +} + +static inline void +timespec_add (struct timespec *sum, const struct timespec *left, + const struct timespec *right) +{ + sum->tv_sec = left->tv_sec + right->tv_sec; + sum->tv_nsec = left->tv_nsec + right->tv_nsec; + + if (sum->tv_nsec >= 1000000000) + { + ++sum->tv_sec; + sum->tv_nsec -= 1000000000; + } +} + +static inline void +timespec_sub (struct timespec *diff, const struct timespec *left, + const struct timespec *right) +{ + diff->tv_sec = left->tv_sec - right->tv_sec; + diff->tv_nsec = left->tv_nsec - right->tv_nsec; + + if (diff->tv_nsec < 0) + { + --diff->tv_sec; + diff->tv_nsec += 1000000000; + } +} + + +/* We need one of the list functions in the other modules. */ +static inline void +list_unlink_ip (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; + + /* The suffix ip means idempotent; list_unlink_ip can be called + * two or more times on the same node. + */ + + list->next = list; + list->prev = list; +} + + +/* Functions in the helper file. */ +extern void __timer_mutex_cancel_handler (void *arg); +extern void __timer_init_once (void); +extern struct timer_node *__timer_alloc (void); +extern int __timer_thread_start (struct thread_node *thread); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); +extern void __timer_thread_dealloc (struct thread_node *thread); +extern int __timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert); +extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/linuxthreads/sysdeps/pthread/pt-initfini.c b/linuxthreads/sysdeps/pthread/pt-initfini.c new file mode 100644 index 0000000000..1ccac2f6ef --- /dev/null +++ b/linuxthreads/sysdeps/pthread/pt-initfini.c @@ -0,0 +1,124 @@ +/* Special .init and .fini section support. Linuxthread version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include <stdlib.h> + +/* We use embedded asm for .section unconditionally, as this makes it + easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) asm (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +asm ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +asm ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +asm ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ + if (foo) + (*foo) (); +} +asm ("\n/*@TESTS_END*/"); + +/* The beginning of _init: */ +asm ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ + extern void __pthread_initialize_minimal (void); + + __pthread_initialize_minimal (); +} + +SECTION (".init"); +extern void _init (void); +void +_init (void) +{ + /* The very first thing we must do is to set up the registers. */ + call_initialize_minimal (); + + asm ("ALIGN"); + asm("END_INIT"); + /* Now the epilog. */ + asm ("\n/*@_init_PROLOG_ENDS*/"); + asm ("\n/*@_init_EPILOG_BEGINS*/"); + SECTION(".init"); +} +asm ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +asm ("\n/*@_init_EPILOG_ENDS*/"); +asm ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void _fini (void); +void +_fini (void) +{ + + /* End of the _fini prolog. */ + asm ("ALIGN"); + asm ("END_FINI"); + asm ("\n/*@_fini_PROLOG_ENDS*/"); + + { + /* Let GCC know that _fini is not a leaf function by having a dummy + function call here. We arrange for this call to be omitted from + either crt file. */ + extern void i_am_not_a_leaf (void); + i_am_not_a_leaf (); + } + + /* Beginning of the _fini epilog. */ + asm ("\n/*@_fini_EPILOG_BEGINS*/"); + SECTION (".fini"); +} +asm ("END_FINI"); + +/* End of the _fini epilog. Any further generated assembly (e.g. .ident) + is shared between both crt files. */ +asm ("\n/*@_fini_EPILOG_ENDS*/"); +asm ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/linuxthreads/sysdeps/pthread/pthread-functions.h b/linuxthreads/sysdeps/pthread/pthread-functions.h new file mode 100644 index 0000000000..43a328ae9c --- /dev/null +++ b/linuxthreads/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,96 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + 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 _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include <pthread.h> +#include <setjmp.h> +#include <linuxthreads/descr.h> + +struct fork_block; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. Wine pokes directly into this structure, + so if possible avoid breaking it and append new hooks to the end. */ +struct pthread_functions +{ + pid_t (*ptr_pthread_fork) (struct fork_block *); + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); + int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr___pthread_cond_destroy) (pthread_cond_t *); + int (*ptr___pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr___pthread_cond_signal) (pthread_cond_t *); + int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + void (*ptr_pthread_cleanup_upto) (__jmp_buf target, + char *targetframe); + pthread_descr (*ptr_pthread_thread_self) (void); + int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); + void * (*ptr_pthread_internal_tsd_get) (int key); + void ** __attribute__ ((__const__)) + (*ptr_pthread_internal_tsd_address) (int key); + int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, + struct sigaction *oact); + int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); + int (*ptr_pthread_raise) (int sig); + int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + + void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, + int execute); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif /* pthread-functions.h */ diff --git a/linuxthreads/sysdeps/pthread/pthread.h b/linuxthreads/sysdeps/pthread/pthread.h new file mode 100644 index 0000000000..86c7ff7391 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/pthread.h @@ -0,0 +1,686 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include <features.h> + +#include <sched.h> +#include <time.h> + +#define __need_sigset_t +#include <signal.h> +#include <bits/pthreadtypes.h> +#include <bits/initspin.h> + + +__BEGIN_DECLS + +/* Initializers. */ + +#define PTHREAD_MUTEX_INITIALIZER \ + {0, 0, 0, PTHREAD_MUTEX_TIMED_NP, __LOCK_INITIALIZER} +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#endif + +#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0, "", 0} + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +# define PTHREAD_RWLOCK_INITIALIZER \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } +#endif +#ifdef __USE_GNU +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } +#endif + +/* Values for attributes. */ + +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#ifdef __USE_UNIX98 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP +#endif +}; + +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP +}; +#endif /* Unix98 */ + +#define PTHREAD_ONCE_INIT 0 + +/* Special constants */ + +#ifdef __USE_XOPEN2K +/* -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + +/* Cleanup buffers */ + +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ + +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Function for handling threads. */ + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW; + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW; + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + +/* Terminate calling thread. */ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Functions for handling attributes. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) __THROW; + +/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW; + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW; + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW; + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) __THROW; + +#ifdef __USE_UNIX98 +/* Set the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) __THROW; + +/* Get the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __guardsize) + __THROW; +#endif + +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_MIN. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW; + +#ifdef __USE_XOPEN2K +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) __THROW; +#endif + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_MIN + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) __THROW; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW; + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on unitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW; + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +#ifdef __USE_GNU +/* Yield the processor to another thread or process. + This function is similar to the POSIX `sched_yield' function but + might be differently implemented in the case of a m-on-n thread + implementation. */ +extern int pthread_yield (void) __THROW; +#endif + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, + __const pthread_mutexattr_t *__restrict + __mutex_attr) __THROW; + +/* Destroy MUTEX. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW; +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW; + +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) __THROW; +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW; + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW; + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) __THROW; + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr, + int *__pref) __THROW; + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The IEEE Std. 1003.1j-2000 introduces functions to implement + spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW; + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Barriers are a also a new feature in 1003.1j-2000. */ + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) __THROW; + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) __THROW; + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + +/* Functions for handling cancellation. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __cancelthread); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is cancelled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ + +#define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ + +#define pthread_cleanup_pop(execute) \ + _pthread_cleanup_pop (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +#ifdef __USE_GNU +# define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ + +# define pthread_cleanup_pop_restore_np(execute) \ + _pthread_cleanup_pop_restore (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +#endif + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) __THROW; +#endif + + +/* Functions for handling signals. */ +#include <bits/sigthread.h> + + +/* Functions for handling process creation and process execution. */ + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + +/* Terminate all threads in the program except the calling process. + Should be called just before invoking one of the exec*() functions. */ + +extern void pthread_kill_other_threads_np (void) __THROW; + +__END_DECLS + +#endif /* pthread.h */ diff --git a/linuxthreads/sysdeps/pthread/ptlongjmp.c b/linuxthreads/sysdeps/pthread/ptlongjmp.c new file mode 100644 index 0000000000..a2a56b8d9c --- /dev/null +++ b/linuxthreads/sysdeps/pthread/ptlongjmp.c @@ -0,0 +1,39 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#include <setjmp.h> +#include "pthread.h" +#include "internals.h" + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + +#ifdef SHARED +void siglongjmp (sigjmp_buf env, int val) +{ + __libc_siglongjmp (env, val); +} + +void longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} +#endif diff --git a/linuxthreads/sysdeps/pthread/res-state.c b/linuxthreads/sysdeps/pthread/res-state.c new file mode 100644 index 0000000000..016e20b4ef --- /dev/null +++ b/linuxthreads/sysdeps/pthread/res-state.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1996, 97, 98, 2002, 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 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. */ + +#include <resolv.h> +#include <tls.h> +#include <linuxthreads/internals.h> +#include <sysdep-cancel.h> + +#if ! USE___THREAD +# undef _res +extern struct __res_state _res; +#endif + +/* When threaded, _res may be a per-thread variable. */ +struct __res_state * +#if ! USE___THREAD +weak_const_function +#endif +__res_state (void) +{ +#if ! USE___THREAD + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_resp); + } + return &_res; +#else + return __resp; +#endif +} +libc_hidden_def (__res_state) diff --git a/linuxthreads/sysdeps/pthread/semaphore.h b/linuxthreads/sysdeps/pthread/semaphore.h new file mode 100644 index 0000000000..8793768a8e --- /dev/null +++ b/linuxthreads/sysdeps/pthread/semaphore.h @@ -0,0 +1 @@ +#include <linuxthreads/semaphore.h> diff --git a/linuxthreads/sysdeps/pthread/sigaction.c b/linuxthreads/sysdeps/pthread/sigaction.c new file mode 100644 index 0000000000..f4e20790d9 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/sigaction.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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. */ + +/* This is tricky. GCC doesn't like #include_next in the primary + source file and even if it did, the first #include_next is this + exact file anyway. */ +#ifndef LIBC_SIGACTION + +# include <bits/libc-lock.h> + +# define LIBC_SIGACTION 1 + +# include <linuxthreads/sysdeps/pthread/sigaction.c> + +# ifndef NOT_IN_libc +# ifndef SHARED +weak_extern (__pthread_sigaction) +# endif + +int +__sigaction (sig, act, oact) + int sig; + const struct sigaction *act; + struct sigaction *oact; +{ + return __libc_maybe_call2 (pthread_sigaction, (sig, act, oact), + __libc_sigaction (sig, act, oact)); +} +# else +weak_alias (__libc_sigaction, __sigaction) +# endif +libc_hidden_weak (__sigaction) +weak_alias (__sigaction, sigaction) + +#else + +# include_next <sigaction.c> + +#endif /* LIBC_SIGACTION */ diff --git a/linuxthreads/sysdeps/pthread/tcb-offsets.h b/linuxthreads/sysdeps/pthread/tcb-offsets.h new file mode 100644 index 0000000000..3fe13702ea --- /dev/null +++ b/linuxthreads/sysdeps/pthread/tcb-offsets.h @@ -0,0 +1 @@ +/* This is overridden by generated tcb-offsets.h on arches which need it. */ diff --git a/linuxthreads/sysdeps/pthread/timer_create.c b/linuxthreads/sysdeps/pthread/timer_create.c new file mode 100644 index 0000000000..7f7e886c83 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/timer_create.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <signal.h> +#include <pthread.h> +#include <time.h> +#include <unistd.h> + +#include "posix-timer.h" + + +/* Create new per-process timer using CLOCK. */ +int +timer_create (clock_id, evp, timerid) + clockid_t clock_id; + struct sigevent *evp; + timer_t *timerid; +{ + int retval = -1; + struct timer_node *newtimer = NULL; + struct thread_node *thread = NULL; + + if (0 +#ifdef _POSIX_CPUTIME + || clock_id == CLOCK_PROCESS_CPUTIME_ID +#endif +#ifdef _POSIX_THREAD_CPUTIME + || clock_id == CLOCK_THREAD_CPUTIME_ID +#endif + ) + { + /* We don't allow timers for CPU clocks. At least not in the + moment. */ + __set_errno (ENOTSUP); + return -1; + } + + if (clock_id != CLOCK_REALTIME) + { + __set_errno (EINVAL); + return -1; + } + + pthread_once (&__timer_init_once_control, __timer_init_once); + + if (__timer_init_failed) + { + __set_errno (ENOMEM); + return -1; + } + + pthread_mutex_lock (&__timer_mutex); + + newtimer = __timer_alloc (); + if (__builtin_expect (newtimer == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + if (evp != NULL) + newtimer->event = *evp; + else + { + newtimer->event.sigev_notify = SIGEV_SIGNAL; + newtimer->event.sigev_signo = SIGALRM; + newtimer->event.sigev_value.sival_int = timer_ptr2id (newtimer); + newtimer->event.sigev_notify_function = 0; + } + + newtimer->event.sigev_notify_attributes = &newtimer->attr; + newtimer->creator_pid = getpid (); + + switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + case SIGEV_SIGNAL: + /* We have a global thread for delivering timed signals. + If it is not running, try to start it up. */ + thread = &__timer_signal_thread_rclk; + if (! thread->exists) + { + if (__builtin_expect (__timer_thread_start (thread), + 1) < 0) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + } + break; + + case SIGEV_THREAD: + /* Copy over thread attributes or set up default ones. */ + if (evp->sigev_notify_attributes) + newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes; + else + pthread_attr_init (&newtimer->attr); + + /* Ensure thread attributes call for deatched thread. */ + pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); + + /* Try to find existing thread having the right attributes. */ + thread = __timer_thread_find_matching (&newtimer->attr, clock_id); + + /* If no existing thread has these attributes, try to allocate one. */ + if (thread == NULL) + thread = __timer_thread_alloc (&newtimer->attr, clock_id); + + /* Out of luck; no threads are available. */ + if (__builtin_expect (thread == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + /* If the thread is not running already, try to start it. */ + if (! thread->exists + && __builtin_expect (! __timer_thread_start (thread), 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + break; + + default: + __set_errno (EINVAL); + goto unlock_bail; + } + + newtimer->clock = clock_id; + newtimer->abstime = 0; + newtimer->armed = 0; + newtimer->thread = thread; + + *timerid = timer_ptr2id (newtimer); + retval = 0; + + if (__builtin_expect (retval, 0) == -1) + { + unlock_bail: + if (thread != NULL) + __timer_thread_dealloc (thread); + if (newtimer != NULL) + { + timer_delref (newtimer); + __timer_dealloc (newtimer); + } + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/linuxthreads/sysdeps/pthread/timer_delete.c b/linuxthreads/sysdeps/pthread/timer_delete.c new file mode 100644 index 0000000000..48ba1f2726 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/timer_delete.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Delete timer TIMERID. */ +int +timer_delete (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + if (! timer_valid (timer)) + /* Invalid timer ID or the timer is not in use. */ + __set_errno (EINVAL); + else + { + if (timer->armed && timer->thread != NULL) + { + struct thread_node *thread = timer->thread; + assert (thread != NULL); + + /* If thread is cancelled while waiting for handler to terminate, + the mutex is unlocked and timer_delete is aborted. */ + pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex); + + /* If timer is currently being serviced, wait for it to finish. */ + while (thread->current_timer == timer) + pthread_cond_wait (&thread->cond, &__timer_mutex); + + pthread_cleanup_pop (0); + } + + /* Remove timer from whatever queue it may be on and deallocate it. */ + timer->inuse = TIMER_DELETED; + list_unlink_ip (&timer->links); + timer_delref (timer); + retval = 0; + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/linuxthreads/sysdeps/pthread/timer_getoverr.c b/linuxthreads/sysdeps/pthread/timer_getoverr.c new file mode 100644 index 0000000000..f3e22215b2 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/timer_getoverr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Get expiration overrun for timer TIMERID. */ +int +timer_getoverrun (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + if (! timer_valid (timer = timer_id2ptr (timerid))) + __set_errno (EINVAL); + else + retval = timer->overrun_count; + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/linuxthreads/sysdeps/pthread/timer_gettime.c b/linuxthreads/sysdeps/pthread/timer_gettime.c new file mode 100644 index 0000000000..723a61632f --- /dev/null +++ b/linuxthreads/sysdeps/pthread/timer_gettime.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Get current value of timer TIMERID and store it in VLAUE. */ +int +timer_gettime (timerid, value) + timer_t timerid; + struct itimerspec *value; +{ + struct timer_node *timer; + struct timespec now, expiry; + int retval = -1, armed = 0, valid; + clock_t clock = 0; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + valid = timer_valid (timer); + + if (valid) { + armed = timer->armed; + expiry = timer->expirytime; + clock = timer->clock; + value->it_interval = timer->value.it_interval; + } + + pthread_mutex_unlock (&__timer_mutex); + + if (valid) + { + if (armed) + { + clock_gettime (clock, &now); + if (timespec_compare (&now, &expiry) < 0) + timespec_sub (&value->it_value, &expiry, &now); + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + } + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + + retval = 0; + } + else + __set_errno (EINVAL); + + return retval; +} diff --git a/linuxthreads/sysdeps/pthread/timer_routines.c b/linuxthreads/sysdeps/pthread/timer_routines.c new file mode 100644 index 0000000000..3877b86fbb --- /dev/null +++ b/linuxthreads/sysdeps/pthread/timer_routines.c @@ -0,0 +1,573 @@ +/* Helper code for POSIX timer implementation on LinuxThreads. + Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <pthread.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <time.h> +#include <unistd.h> +#include <sys/syscall.h> + +#include "posix-timer.h" + + +/* Number of threads used. */ +#define THREAD_MAXNODES 16 + +/* Array containing the descriptors for the used threads. */ +static struct thread_node thread_array[THREAD_MAXNODES]; + +/* Static array with the structures for all the timers. */ +struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Variable to protext initialization. */ +pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; + +/* Nonzero if initialization of timer implementation failed. */ +int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +struct thread_node __timer_signal_thread_rclk; + +/* Lists to keep free and used timers and threads. */ +struct list_links timer_free_list; +struct list_links thread_free_list; +struct list_links thread_active_list; + + +#ifdef __NR_rt_sigqueueinfo +extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); +#endif + + +/* List handling functions. */ +static inline void +list_init (struct list_links *list) +{ + list->next = list->prev = list; +} + +static inline void +list_append (struct list_links *list, struct list_links *newp) +{ + newp->prev = list->prev; + newp->next = list; + list->prev->next = newp; + list->prev = newp; +} + +static inline void +list_insbefore (struct list_links *list, struct list_links *newp) +{ + list_append (list, newp); +} + +/* + * Like list_unlink_ip, except that calling it on a node that + * is already unlinked is disastrous rather than a noop. + */ + +static inline void +list_unlink (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; +} + +static inline struct list_links * +list_first (struct list_links *list) +{ + return list->next; +} + +static inline struct list_links * +list_null (struct list_links *list) +{ + return list; +} + +static inline struct list_links * +list_next (struct list_links *list) +{ + return list->next; +} + +static inline int +list_isempty (struct list_links *list) +{ + return list->next == list; +} + + +/* Functions build on top of the list functions. */ +static inline struct thread_node * +thread_links2ptr (struct list_links *list) +{ + return (struct thread_node *) ((char *) list + - offsetof (struct thread_node, links)); +} + +static inline struct timer_node * +timer_links2ptr (struct list_links *list) +{ + return (struct timer_node *) ((char *) list + - offsetof (struct timer_node, links)); +} + + +/* Initialize a newly allocated thread structure. */ +static void +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) +{ + if (attr != NULL) + thread->attr = *attr; + else + { + pthread_attr_init (&thread->attr); + pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED); + } + + thread->exists = 0; + list_init (&thread->timer_queue); + pthread_cond_init (&thread->cond, 0); + thread->current_timer = 0; + thread->captured = pthread_self (); + thread->clock_id = clock_id; +} + + +/* Initialize the global lists, and acquire global resources. Error + reporting is done by storing a non-zero value to the global variable + timer_init_failed. */ +static void +init_module (void) +{ + int i; + + list_init (&timer_free_list); + list_init (&thread_free_list); + list_init (&thread_active_list); + + for (i = 0; i < TIMER_MAX; ++i) + { + list_append (&timer_free_list, &__timer_array[i].links); + __timer_array[i].inuse = TIMER_FREE; + } + + for (i = 0; i < THREAD_MAXNODES; ++i) + list_append (&thread_free_list, &thread_array[i].links); + + thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +} + + +/* This is a handler executed in a child process after a fork() + occurs. It reinitializes the module, resetting all of the data + structures to their initial state. The mutex is initialized in + case it was locked in the parent process. */ +static void +reinit_after_fork (void) +{ + init_module (); + pthread_mutex_init (&__timer_mutex, 0); +} + + +/* Called once form pthread_once in timer_init. This initializes the + module and ensures that reinit_after_fork will be executed in any + child process. */ +void +__timer_init_once (void) +{ + init_module (); + pthread_atfork (0, 0, reinit_after_fork); +} + + +/* Deinitialize a thread that is about to be deallocated. */ +static void +thread_deinit (struct thread_node *thread) +{ + assert (list_isempty (&thread->timer_queue)); + pthread_cond_destroy (&thread->cond); +} + + +/* Allocate a thread structure from the global free list. Global + mutex lock must be held by caller. The thread is moved to + the active list. */ +struct thread_node * +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) +{ + struct list_links *node = list_first (&thread_free_list); + + if (node != list_null (&thread_free_list)) + { + struct thread_node *thread = thread_links2ptr (node); + list_unlink (node); + thread_init (thread, desired_attr, clock_id); + list_append (&thread_active_list, node); + return thread; + } + + return 0; +} + + +/* Return a thread structure to the global free list. Global lock + must be held by caller. */ +void +__timer_thread_dealloc (struct thread_node *thread) +{ + thread_deinit (thread); + list_unlink (&thread->links); + list_append (&thread_free_list, &thread->links); +} + + +/* Each of our threads which terminates executes this cleanup + handler. We never terminate threads ourselves; if a thread gets here + it means that the evil application has killed it. If the thread has + timers, these require servicing and so we must hire a replacement + thread right away. We must also unblock another thread that may + have been waiting for this thread to finish servicing a timer (see + timer_delete()). */ + +static void +thread_cleanup (void *val) +{ + if (val != NULL) + { + struct thread_node *thread = val; + + /* How did the signal thread get killed? */ + assert (thread != &__timer_signal_thread_rclk); + + pthread_mutex_lock (&__timer_mutex); + + thread->exists = 0; + + /* We are no longer processing a timer event. */ + thread->current_timer = 0; + + if (list_isempty (&thread->timer_queue)) + __timer_thread_dealloc (thread); + else + (void) __timer_thread_start (thread); + + pthread_mutex_unlock (&__timer_mutex); + + /* Unblock potentially blocked timer_delete(). */ + pthread_cond_broadcast (&thread->cond); + } +} + + +/* Handle a timer which is supposed to go off now. */ +static void +thread_expire_timer (struct thread_node *self, struct timer_node *timer) +{ + self->current_timer = timer; /* Lets timer_delete know timer is running. */ + + pthread_mutex_unlock (&__timer_mutex); + + switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + break; + + case SIGEV_SIGNAL: +#ifdef __NR_rt_sigqueueinfo + { + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t + value. */ + info.si_signo = timer->event.sigev_signo; + info.si_code = SI_TIMER; + info.si_pid = timer->creator_pid; + info.si_uid = getuid (); + info.si_value = timer->event.sigev_value; + + INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info); + } +#else + if (pthread_kill (self->captured, timer->event.sigev_signo) != 0) + { + if (pthread_kill (self->id, timer->event.sigev_signo) != 0) + abort (); + } +#endif + break; + + case SIGEV_THREAD: + timer->event.sigev_notify_function (timer->event.sigev_value); + break; + + default: + assert (! "unknown event"); + break; + } + + pthread_mutex_lock (&__timer_mutex); + + self->current_timer = 0; + + pthread_cond_broadcast (&self->cond); +} + + +/* Thread function; executed by each timer thread. The job of this + function is to wait on the thread's timer queue and expire the + timers in chronological order as close to their scheduled time as + possible. */ +static void +__attribute__ ((noreturn)) +thread_func (void *arg) +{ + struct thread_node *self = arg; + + /* Register cleanup handler, in case rogue application terminates + this thread. (This cannot happen to __timer_signal_thread, which + doesn't invoke application callbacks). */ + + pthread_cleanup_push (thread_cleanup, self); + + pthread_mutex_lock (&__timer_mutex); + + while (1) + { + struct list_links *first; + struct timer_node *timer = NULL; + + /* While the timer queue is not empty, inspect the first node. */ + first = list_first (&self->timer_queue); + if (first != list_null (&self->timer_queue)) + { + struct timespec now; + + timer = timer_links2ptr (first); + + /* This assumes that the elements of the list of one thread + are all for the same clock. */ + clock_gettime (timer->clock, &now); + + while (1) + { + /* If the timer is due or overdue, remove it from the queue. + If it's a periodic timer, re-compute its new time and + requeue it. Either way, perform the timer expiry. */ + if (timespec_compare (&now, &timer->expirytime) < 0) + break; + + list_unlink_ip (first); + + if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 + || timer->value.it_interval.tv_nsec != 0) + { + timer->overrun_count = 0; + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + while (timespec_compare (&timer->expirytime, &now) < 0) + { + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + if (timer->overrun_count < DELAYTIMER_MAX) + ++timer->overrun_count; + } + __timer_thread_queue_timer (self, timer); + } + + thread_expire_timer (self, timer); + + first = list_first (&self->timer_queue); + if (first == list_null (&self->timer_queue)) + break; + + timer = timer_links2ptr (first); + } + } + + /* If the queue is not empty, wait until the expiry time of the + first node. Otherwise wait indefinitely. Insertions at the + head of the queue must wake up the thread by broadcasting + this condition variable. */ + if (timer != NULL) + pthread_cond_timedwait (&self->cond, &__timer_mutex, + &timer->expirytime); + else + pthread_cond_wait (&self->cond, &__timer_mutex); + } + /* This macro will never be executed since the while loop loops + forever - but we have to add it for proper nesting. */ + pthread_cleanup_pop (1); +} + + +/* Enqueue a timer in wakeup order in the thread's timer queue. + Returns 1 if the timer was inserted at the head of the queue, + causing the queue's next wakeup time to change. */ + +int +__timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert) +{ + struct list_links *iter; + int athead = 1; + + for (iter = list_first (&thread->timer_queue); + iter != list_null (&thread->timer_queue); + iter = list_next (iter)) + { + struct timer_node *timer = timer_links2ptr (iter); + + if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) + break; + athead = 0; + } + + list_insbefore (iter, &insert->links); + return athead; +} + + +/* Start a thread and associate it with the given thread node. Global + lock must be held by caller. */ +int +__timer_thread_start (struct thread_node *thread) +{ + int retval = 1; + + assert (!thread->exists); + thread->exists = 1; + + if (pthread_create (&thread->id, &thread->attr, + (void *(*) (void *)) thread_func, thread) != 0) + { + thread->exists = 0; + retval = -1; + } + + return retval; +} + + +void +__timer_thread_wakeup (struct thread_node *thread) +{ + pthread_cond_broadcast (&thread->cond); +} + + +/* Compare two pthread_attr_t thread attributes for exact equality. + Returns 1 if they are equal, otherwise zero if they are not equal or + contain illegal values. This version is LinuxThreads-specific for + performance reason. One could use the access functions to get the + values of all the fields of the attribute structure. */ +static int +thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) +{ + return (left->__detachstate == right->__detachstate + && left->__schedpolicy == right->__schedpolicy + && left->__guardsize == right->__guardsize + && (left->__schedparam.sched_priority + == right->__schedparam.sched_priority) + && left->__inheritsched == right->__inheritsched + && left->__scope == right->__scope + && left->__stacksize == right->__stacksize + && left->__stackaddr_set == right->__stackaddr_set + && (left->__stackaddr_set + || left->__stackaddr == right->__stackaddr)); +} + + +/* Search the list of active threads and find one which has matching + attributes. Global mutex lock must be held by caller. */ +struct thread_node * +__timer_thread_find_matching (const pthread_attr_t *desired_attr, + clockid_t desired_clock_id) +{ + struct list_links *iter = list_first (&thread_active_list); + + while (iter != list_null (&thread_active_list)) + { + struct thread_node *candidate = thread_links2ptr (iter); + + if (thread_attr_compare (desired_attr, &candidate->attr) + && desired_clock_id == candidate->clock_id) + return candidate; + + iter = list_next (iter); + } + + return NULL; +} + + +/* Grab a free timer structure from the global free list. The global + lock must be held by the caller. */ +struct timer_node * +__timer_alloc (void) +{ + struct list_links *node = list_first (&timer_free_list); + + if (node != list_null (&timer_free_list)) + { + struct timer_node *timer = timer_links2ptr (node); + list_unlink_ip (node); + timer->inuse = TIMER_INUSE; + timer->refcount = 1; + return timer; + } + + return NULL; +} + + +/* Return a timer structure to the global free list. The global lock + must be held by the caller. */ +void +__timer_dealloc (struct timer_node *timer) +{ + assert (timer->refcount == 0); + timer->thread = NULL; /* Break association between timer and thread. */ + timer->inuse = TIMER_FREE; + list_append (&timer_free_list, &timer->links); +} + + +/* Thread cancellation handler which unlocks a mutex. */ +void +__timer_mutex_cancel_handler (void *arg) +{ + pthread_mutex_unlock (arg); +} diff --git a/linuxthreads/sysdeps/pthread/timer_settime.c b/linuxthreads/sysdeps/pthread/timer_settime.c new file mode 100644 index 0000000000..592b5271ba --- /dev/null +++ b/linuxthreads/sysdeps/pthread/timer_settime.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +int +timer_settime (timerid, flags, value, ovalue) + timer_t timerid; + int flags; + const struct itimerspec *value; + struct itimerspec *ovalue; +{ + struct timer_node *timer; + struct thread_node *thread = NULL; + struct timespec now; + int have_now = 0, need_wakeup = 0; + int retval = -1; + + timer = timer_id2ptr (timerid); + if (timer == NULL) + { + __set_errno (EINVAL); + goto bail; + } + + if (value->it_interval.tv_nsec < 0 + || value->it_interval.tv_nsec >= 1000000000 + || value->it_value.tv_nsec < 0 + || value->it_value.tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + goto bail; + } + + /* Will need to know current time since this is a relative timer; + might as well make the system call outside of the lock now! */ + + if ((flags & TIMER_ABSTIME) == 0) + { + clock_gettime (timer->clock, &now); + have_now = 1; + } + + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + + /* One final check of timer validity; this one is possible only + until we have the mutex, because it accesses the inuse flag. */ + + if (! timer_valid(timer)) + { + __set_errno (EINVAL); + goto unlock_bail; + } + + if (ovalue != NULL) + { + ovalue->it_interval = timer->value.it_interval; + + if (timer->armed) + { + if (! have_now) + { + pthread_mutex_unlock (&__timer_mutex); + clock_gettime (timer->clock, &now); + have_now = 1; + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + } + + timespec_sub (&ovalue->it_value, &timer->expirytime, &now); + } + else + { + ovalue->it_value.tv_sec = 0; + ovalue->it_value.tv_nsec = 0; + } + } + + timer->value = *value; + + list_unlink_ip (&timer->links); + timer->armed = 0; + + thread = timer->thread; + + /* A value of { 0, 0 } causes the timer to be stopped. */ + if (value->it_value.tv_sec != 0 + || __builtin_expect (value->it_value.tv_nsec != 0, 1)) + { + if ((flags & TIMER_ABSTIME) != 0) + /* The user specified the expiration time. */ + timer->expirytime = value->it_value; + else + timespec_add (&timer->expirytime, &now, &value->it_value); + + /* Only need to wake up the thread if timer is inserted + at the head of the queue. */ + if (thread != NULL) + need_wakeup = __timer_thread_queue_timer (thread, timer); + timer->armed = 1; + } + + retval = 0; + +unlock_bail: + timer_delref (timer); + pthread_mutex_unlock (&__timer_mutex); + +bail: + if (thread != NULL && need_wakeup) + __timer_thread_wakeup (thread); + + return retval; +} diff --git a/linuxthreads/sysdeps/pthread/tst-timer.c b/linuxthreads/sysdeps/pthread/tst-timer.c new file mode 100644 index 0000000000..7417bcd5f0 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/tst-timer.c @@ -0,0 +1,114 @@ +/* Tests for POSIX timer implementation. + Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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; 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 <signal.h> +#include <stdio.h> +#include <time.h> +#include <unistd.h> + + +static void +notify_func (union sigval sigval) +{ + puts ("notify_func"); +} + + +static void +signal_func (int sig) +{ + static const char text[] = "signal_func\n"; + signal (sig, signal_func); + write (STDOUT_FILENO, text, sizeof text - 1); +} + +static void +intr_sleep (int sec) +{ + struct timespec ts; + + ts.tv_sec = sec; + ts.tv_nsec = 0; + + while (nanosleep (&ts, &ts) == -1 && errno == EINTR) + ; +} + +#define ZSIGALRM 14 + + +int +main (void) +{ + struct timespec ts; + timer_t timer_sig, timer_thr1, timer_thr2; + int retval; + struct sigevent sigev1 = + { + .sigev_notify = SIGEV_SIGNAL, + .sigev_signo = ZSIGALRM + }; + struct sigevent sigev2; + struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } }; + struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } }; + struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } }; + struct itimerspec old; + + retval = clock_gettime (CLOCK_REALTIME, &ts); + + sigev2.sigev_notify = SIGEV_THREAD; + sigev2.sigev_notify_function = notify_func; + sigev2.sigev_notify_attributes = NULL; + + setvbuf (stdout, 0, _IOLBF, 0); + + printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n", + retval, ts.tv_sec, ts.tv_nsec); + + retval = clock_getres (CLOCK_REALTIME, &ts); + + printf ("clock_getres returned %d, timespec = { %ld, %ld }\n", + retval, ts.tv_sec, ts.tv_nsec); + + timer_create (CLOCK_REALTIME, &sigev1, &timer_sig); + timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1); + timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2); + + timer_settime (timer_thr1, 0, &itimer2, &old); + timer_settime (timer_thr2, 0, &itimer3, &old); + + signal (ZSIGALRM, signal_func); + + timer_settime (timer_sig, 0, &itimer1, &old); + + timer_delete (-1); + + intr_sleep (3); + + timer_delete (timer_sig); + timer_delete (timer_thr1); + + intr_sleep (3); + + timer_delete (timer_thr2); + + return 0; +} diff --git a/linuxthreads/sysdeps/s390/Makefile b/linuxthreads/sysdeps/s390/Makefile new file mode 100644 index 0000000000..2885c968b3 --- /dev/null +++ b/linuxthreads/sysdeps/s390/Makefile @@ -0,0 +1,6 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif +ifeq ($(subdir),linuxthreads) +libpthread-routines += ptw-sysdep +endif diff --git a/linuxthreads/sysdeps/s390/pspinlock.c b/linuxthreads/sysdeps/s390/pspinlock.c new file mode 100644 index 0000000000..f963f35371 --- /dev/null +++ b/linuxthreads/sysdeps/s390/pspinlock.c @@ -0,0 +1,91 @@ +/* POSIX spinlock implementation. S/390 version. + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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; 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 <pthread.h> +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + asm volatile(" basr 1,0\n" + "0: slr 0,0\n" + " cs 0,1,%1\n" + " jl 0b\n" + : "=m" (*lock) + : "m" (*lock) : "0", "1", "cc" ); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + asm volatile(" slr %1,%1\n" + " basr 1,0\n" + "0: cs %1,1,%0" + : "=m" (*lock), "=&d" (oldval) + : "m" (*lock) : "1", "cc" ); + return oldval == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile(" xc 0(4,%0),0(%0)\n" + " bcr 15,0" + : : "a" (lock) : "memory" ); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/s390/s390-32/pt-machine.h b/linuxthreads/sysdeps/s390/s390-32/pt-machine.h new file mode 100644 index 0000000000..398332965f --- /dev/null +++ b/linuxthreads/sysdeps/s390/s390-32/pt-machine.h @@ -0,0 +1,120 @@ +/* Machine-dependent pthreads configuration and inline functions. + S390 version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("15"); + +#ifdef USE_TLS +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ()) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr) +#else +/* Return the thread descriptor for the current thread. + S/390 registers uses access register 0 as "thread register". */ +#define THREAD_SELF ({ \ + register pthread_descr __self; \ + __asm__ ("ear %0,%%a0" : "=d" (__self) ); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) ({ \ + __asm__ ("sar %%a0,%0" : : "d" (descr) ); \ +}) +#endif + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + int retval; + + __asm__ __volatile__( + " la 1,%1\n" + " lr 0,%2\n" + " cs 0,%3,0(1)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "+m" (*p) + : "d" (oldval) , "d" (newval) + : "cc", "0", "1" ); + return retval == 0; +} + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/s390/s390-64/pt-machine.h b/linuxthreads/sysdeps/s390/s390-64/pt-machine.h new file mode 100644 index 0000000000..49f8ae2b9a --- /dev/null +++ b/linuxthreads/sysdeps/s390/s390-64/pt-machine.h @@ -0,0 +1,125 @@ +/* Machine-dependent pthreads configuration and inline functions. + 64 bit S/390 version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("15"); + +#ifdef USE_TLS +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ()) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr) +#else +/* Return the thread descriptor for the current thread. + 64 bit S/390 uses access register 0 and 1 as "thread register". */ +#define THREAD_SELF ({ \ + register pthread_descr __self; \ + __asm__ (" ear %0,%%a0\n" \ + " sllg %0,%0,32\n" \ + " ear %0,%%a1\n" \ + : "=d" (__self) ); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) ({ \ + __asm__ (" sar %%a1,%0\n" \ + " srlg 0,%0,32\n" \ + " sar %%a0,0\n" \ + : : "d" (descr) : "0" ); \ +}) +#endif + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + int retval; + + __asm__ __volatile__( + " lgr 0,%2\n" + " csg 0,%3,%1\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "+m" (*p) + : "d" (oldval) , "d" (newval) + : "cc", "0"); + return retval == 0; +} + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/s390/tcb-offsets.sym b/linuxthreads/sysdeps/s390/tcb-offsets.sym new file mode 100644 index 0000000000..aee6be2570 --- /dev/null +++ b/linuxthreads/sysdeps/s390/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/linuxthreads/sysdeps/s390/tls.h b/linuxthreads/sysdeps/s390/tls.h new file mode 100644 index 0000000000..41a83a72fb --- /dev/null +++ b/linuxthreads/sysdeps/s390/tls.h @@ -0,0 +1,140 @@ +/* Definitions for thread-local data handling. linuxthreads/s390 version. + Copyright (C) 2002, 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 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 _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include <pt-machine.h> +# include <stddef.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + +/* TLS is always supported if the tools support it. There are no + kernel dependencies. To avoid bothering with the TLS support code + at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h + conditionals. */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The value of this macro is null if successful, or an error string. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __builtin_set_thread_pointer (_descr); \ + NULL; \ + }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +# endif /* __ASSEMBLER__ */ + +#else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +# ifndef __ASSEMBLER__ + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp \ + = { .multiple_threads = 0 }; \ + INIT_THREAD_SELF (&nontls_init_tp, 0); \ + } while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/sh/Makefile b/linuxthreads/sysdeps/sh/Makefile new file mode 100644 index 0000000000..81bddf688c --- /dev/null +++ b/linuxthreads/sysdeps/sh/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/linuxthreads/sysdeps/sh/pspinlock.c b/linuxthreads/sysdeps/sh/pspinlock.c new file mode 100644 index 0000000000..2dec849d3c --- /dev/null +++ b/linuxthreads/sysdeps/sh/pspinlock.c @@ -0,0 +1,80 @@ +/* POSIX spinlock implementation. SH version. + Copyright (C) 2000, 2001 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; 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 <pthread.h> +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + asm volatile ("tas.b @%1; movt %0" + : "=r" (val) + : "r" (lock) + : "memory"); + while (val == 0); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + asm volatile ("tas.b @%1; movt %0" + : "=r" (val) + : "r" (lock) + : "memory"); + return val ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/sh/pt-machine.h b/linuxthreads/sysdeps/sh/pt-machine.h new file mode 100644 index 0000000000..02545e6b45 --- /dev/null +++ b/linuxthreads/sysdeps/sh/pt-machine.h @@ -0,0 +1,81 @@ +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka <gniibe@m17n.org>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +/* Return the thread descriptor for the current thread. */ +struct _pthread_descr_struct; +#define THREAD_SELF \ + ({ struct _pthread_descr_struct *self; \ + __asm__("stc gbr,%0" : "=r" (self)); self;}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/sh/tcb-offsets.sym b/linuxthreads/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 0000000000..328eb05738 --- /dev/null +++ b/linuxthreads/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,10 @@ +#include <sysdep.h> +#include <tls.h> + +-- +#ifdef USE_TLS +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) +TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) +#else +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#endif diff --git a/linuxthreads/sysdeps/sh/tls.h b/linuxthreads/sysdeps/sh/tls.h new file mode 100644 index 0000000000..17a247c6b6 --- /dev/null +++ b/linuxthreads/sysdeps/sh/tls.h @@ -0,0 +1,148 @@ +/* Definition for thread-local data handling. linuxthreads/SH version. + Copyright (C) 2002, 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 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 _TLS_H +#define _TLS_H + +# include <dl-sysdep.h> +# include <pt-machine.h> + +#ifndef __ASSEMBLER__ +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm __volatile ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ({ struct _pthread_descr_struct *__self; \ + __asm ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + ({ struct _pthread_descr_struct *__self = (void *) descr; \ + __asm __volatile ("ldc %0,gbr" : : "r" (__self + 1)); \ + 0; }) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. This must be after the + the definition of THREAD_SELF for TLS. */ +# include <linuxthreads/descr.h> + +# endif /* __ASSEMBLER__ */ + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __asm __volatile ("ldc %0,gbr" : : "r" (&nontls_init_tp)); \ + } while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/sparc/Makefile b/linuxthreads/sysdeps/sparc/Makefile new file mode 100644 index 0000000000..81bddf688c --- /dev/null +++ b/linuxthreads/sysdeps/sparc/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c b/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c new file mode 100644 index 0000000000..a67dbf901e --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c @@ -0,0 +1,88 @@ +/* POSIX spinlock implementation. SPARC32 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 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; 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 <pthread.h> +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + asm volatile + ("1: ldstub [%0], %%g2\n" + " orcc %%g2, 0x0, %%g0\n" + " bne,a 2f\n" + " ldub [%0], %%g2\n" + ".subsection 2\n" + "2: orcc %%g2, 0x0, %%g0\n" + " bne,a 2b\n" + " ldub [%0], %%g2\n" + " b,a 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory", "cc"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + asm volatile + ("ldstub [%1], %0" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h b/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h new file mode 100644 index 0000000000..322a52051f --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h @@ -0,0 +1,83 @@ +/* Machine-dependent pthreads configuration and inline functions. + sparc version. + Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(ret), "=m"(*spinlock) + : "m"(*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". + %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions new file mode 100644 index 0000000000..32da57080d --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_PRIVATE { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c new file mode 100644 index 0000000000..04f588bed5 --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c @@ -0,0 +1,94 @@ +/* POSIX spinlock implementation. SPARC v9 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 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; 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 <pthread.h> +#include "internals.h" + + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + asm volatile + ("1: ldstub [%0], %%g2\n" + " brnz,pn %%g2, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g2\n" + " brnz,pt %%g2, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + asm volatile + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile + ("membar #StoreStore | #LoadStore\n" + "stb %%g0, [%0]" + : + : "r" (lock) + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/sparc/sparc64/Versions b/linuxthreads/sysdeps/sparc/sparc64/Versions new file mode 100644 index 0000000000..32da57080d --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc64/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_PRIVATE { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c b/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c new file mode 100644 index 0000000000..92b84f5108 --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c @@ -0,0 +1,93 @@ +/* POSIX spinlock implementation. SPARC64 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 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; 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 <pthread.h> +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + asm volatile + ("1: ldstub [%0], %%g5\n" + " brnz,pn %%g5, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g5\n" + " brnz,pt %%g5, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g5", "memory"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + asm volatile + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile + ("membar #StoreStore | #LoadStore\n" + "stb %%g0, [%0]" + : + : "r" (lock) + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h b/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h new file mode 100644 index 0000000000..f65c13be1b --- /dev/null +++ b/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h @@ -0,0 +1,105 @@ +/* Machine-dependent pthreads configuration and inline functions. + Sparc v9 version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@tamu.edu>. + + 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; 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_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory") +/* Read barrier. */ +#define READ_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__ ("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". The + TLS ABI specifies %g7 as the thread pointer. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__ ("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ ("casx [%4], %2, %0" + : "=r"(readval), "=m"(*p) + : "r"(oldval), "m"(*p), "r"(p), "0"(newval)); + MEMORY_BARRIER(); + return readval == oldval; +} + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/sparc/tcb-offsets.sym b/linuxthreads/sysdeps/sparc/tcb-offsets.sym new file mode 100644 index 0000000000..aee6be2570 --- /dev/null +++ b/linuxthreads/sysdeps/sparc/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/linuxthreads/sysdeps/sparc/tls.h b/linuxthreads/sysdeps/sparc/tls.h new file mode 100644 index 0000000000..6b1966fe1c --- /dev/null +++ b/linuxthreads/sysdeps/sparc/tls.h @@ -0,0 +1,110 @@ +/* Definitions for thread-local data handling. linuxthreads/sparc version. + Copyright (C) 2002, 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 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 _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include <pt-machine.h> +# include <stddef.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. */ +# define TLS_INIT_TP(descr, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (descr), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __thread_self)->dtv) + +# endif + +#else + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp \ + = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Implies b/linuxthreads/sysdeps/unix/sysv/linux/Implies new file mode 100644 index 0000000000..f1b3e8939c --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/Implies @@ -0,0 +1 @@ +pthread diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/Makefile new file mode 100644 index 0000000000..38c6cbc1af --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),linuxthreads) +sysdep_routines += register-atfork unregister-atfork +endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/Versions b/linuxthreads/sysdeps/unix/sysv/linux/Versions new file mode 100644 index 0000000000..6cd3dbe372 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/Versions @@ -0,0 +1,5 @@ +libc { + GLIBC_2.3.2 { + __register_atfork; + } +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h b/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h new file mode 100644 index 0000000000..f62f7d6e9f --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h @@ -0,0 +1,26 @@ +/* Determine whether block of given size can be allocated on the stack or not. + 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 <limits.h> + +extern inline int __libc_use_alloca (size_t size) +{ + return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) + || __libc_alloca_cutoff (size)); +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c b/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c new file mode 100644 index 0000000000..af1581a4c3 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c @@ -0,0 +1,87 @@ +/* Handle real-time signal allocation. + Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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. */ + +#include <signal.h> + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +static int current_rtmin; +static int current_rtmax; + +static int initialized; + +#include <testrtsig.h> + +static void +init (void) +{ + if (!kernel_has_rtsig ()) + { + current_rtmin = -1; + current_rtmax = -1; + } + else + { + current_rtmin = __SIGRTMIN + 3; + current_rtmax = __SIGRTMAX; + } + initialized = 1; +} + +/* Return number of available real-time signal with highest priority. */ +int +__libc_current_sigrtmin (void) +{ + if (!initialized) + init (); + return current_rtmin; +} +strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private); +libc_hidden_def (__libc_current_sigrtmin) + +/* Return number of available real-time signal with lowest priority. */ +int +__libc_current_sigrtmax (void) +{ + if (!initialized) + init (); + return current_rtmax; +} +strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private); +libc_hidden_def (__libc_current_sigrtmax) + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int +__libc_allocate_rtsig (int high) +{ + if (!initialized) + init (); + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + + return high ? current_rtmin++ : current_rtmax--; +} +strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile new file mode 100644 index 0000000000..e03aee99fc --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),linuxthreads) +libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask +endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions new file mode 100644 index 0000000000..d102772482 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/Versions @@ -0,0 +1,6 @@ +libpthread { + GLIBC_2.3.3 { + # Changed PTHREAD_STACK_MIN. + pthread_attr_setstack; pthread_attr_setstacksize; + } +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c b/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c new file mode 100644 index 0000000000..0d6da82919 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c @@ -0,0 +1,33 @@ +#include <shlib-compat.h> + +#define aio_cancel64 XXX +#include <aio.h> +#undef aio_cancel64 +#include <errno.h> + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 0000000000..96893c59da --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002,2003,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 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h new file mode 100644 index 0000000000..a2724885e2 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/Alpha version. + Copyright (C) 2002, 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 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_TYPES_H +# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See <bits/types.h> for the meaning of these macros. This file exists so + that <bits/types.h> need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __U64_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __U32_TYPE +#define __INO64_T_TYPE __U64_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __S64_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __U64_TYPE +#define __BLKCNT_T_TYPE __U32_TYPE +#define __BLKCNT64_T_TYPE __U64_TYPE +#define __FSBLKCNT_T_TYPE __S32_TYPE +#define __FSBLKCNT64_T_TYPE __S64_TYPE +#define __FSFILCNT_T_TYPE __U32_TYPE +#define __FSFILCNT64_T_TYPE __U64_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S64_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __U32_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S b/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S new file mode 100644 index 0000000000..91e5c86782 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S @@ -0,0 +1,28 @@ +/* Internal sigsuspend system call for LinuxThreads. Alpha 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 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. */ + +#include <sysdep.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS ldq a0, 0(a0); + + .hidden __pthread_sigsuspend +PSEUDO_NOERRNO(__pthread_sigsuspend, sigsuspend, 1) + ret +PSEUDO_END_NOERRNO(__pthread_sigsuspend) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 0000000000..9ea779e0d5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,146 @@ +/* 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 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. */ + +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# ifdef PROF +# define PSEUDO_PROF \ + .set noat; \ + lda AT, _mcount; \ + jsr AT, (AT), _mcount; \ + .set at +# else +# define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END + besides "ret". */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .type name, @function; \ + .usepv name, std; \ + cfi_startproc; \ +__LABEL(name) \ + ldgp gp, 0(pv); \ + PSEUDO_PROF; \ + PSEUDO_PREPARE_ARGS \ + SINGLE_THREAD_P(t0); \ + bne t0, $pseudo_cancel; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + bne a3, SYSCALL_ERROR_LABEL; \ +__LABEL($pseudo_ret) \ + .subsection 2; \ +__LABEL($pseudo_cancel) \ + subq sp, 64, sp; \ + cfi_def_cfa_offset(64); \ + stq ra, 0(sp); \ + cfi_offset(ra, -64); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + stq v0, 8(sp); \ + bne a3, $multi_error; \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_remember_state; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ + ret; \ + cfi_restore_state; \ +__LABEL($multi_error) \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ +__LABEL($syscall_error) \ + SYSCALL_ERROR_HANDLER; \ + .previous + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + .subsection 2; \ + cfi_endproc; \ + .size sym, .-sym + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2 SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3 SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4 SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5 SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6 SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2 LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3 LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4 LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5 LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6 LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# else +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifdef PIC +# define CENABLE bsr ra, __local_enable_asynccancel !samegp +# define CDISABLE bsr ra, __local_disable_asynccancel !samegp +# else +# define CENABLE jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +# define CDISABLE jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# elif defined(PIC) +# define SINGLE_THREAD_P(reg) ldl reg, __local_multiple_threads(gp) !gprel +# else +# define SINGLE_THREAD_P(reg) \ + ldah reg, __local_multiple_threads(gp) !gprelhigh; \ + ldl reg, __local_multiple_threads(reg) !gprellow +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 0000000000..cfaae10606 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,70 @@ +/* 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 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. */ + + +#include <sysdep-cancel.h> + + .align 4 + .globl __vfork + .type __vfork, @function + .usepv __vfork, std + cfi_startproc +__vfork: + ldgp gp, 0(pv) + PSEUDO_PROF + +#ifdef SHARED + ldq t0, __libc_pthread_functions(gp) !gprel + bne t0, HIDDEN_JUMPTARGET (__fork) !samegp +#else + .weak pthread_create + ldq t0, pthread_create(gp) !literal + bne t0, $do_fork +#endif + + lda v0, SYS_ify(vfork) + call_pal PAL_callsys + bne a3, SYSCALL_ERROR_LABEL + ret + +#ifndef SHARED + /* Can't tail-call due to possible mismatch between GP in + fork and vfork object files. */ +$do_fork: + subq sp, 16, sp + cfi_adjust_cfa_offset(16) + stq ra, 0(sp) + cfi_offset(ra, -16) + jsr ra, HIDDEN_JUMPTARGET (__fork) + ldgp gp, 0(ra) + ldq ra, 0(sp) + addq sp, 16, sp + cfi_restore(ra) + cfi_adjust_cfa_offset(-16) + ret + +$syscall_error: + SYSCALL_ERROR_HANDLER +#endif + + cfi_endproc + .size __vfork, .-__vfork + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h new file mode 100644 index 0000000000..019bd54913 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -0,0 +1,145 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell <pb@nexus.co.uk>, 2003. + + 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. */ + +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +/* We push lr onto the stack, so we have to use ldmib instead of ldmia + to find the saved arguments. */ +# ifdef PIC +# undef DOARGS_5 +# undef DOARGS_6 +# undef DOARGS_7 +# define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $8]; +# define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmib ip, {r4, r5}; +# define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmib ip, {r4, r5, r6}; +# endif + +# undef PSEUDO_RET +# define PSEUDO_RET \ + ldrcc pc, [sp], $4; \ + ldr lr, [sp], $4; \ + b PLTJMP(SYSCALL_ERROR) + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + PSEUDO_PROLOGUE; \ + ENTRY (name); \ + SINGLE_THREAD_P_INT; \ + bne .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + cmn r0, $4096; \ + PSEUDO_RET_MOV; \ + .Lpseudo_cancel: \ + MAYBE_SAVE_LR; \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + mov ip, r0; /* put mask in safe place. */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + swi SYS_ify (syscall_name); /* do the call. */ \ + str r0, [sp, $-4]!; /* save syscall return value. */ \ + mov r0, ip; /* get mask back. */ \ + CDISABLE; \ + ldr r0, [sp], $4; /* retrieve return value. */ \ + UNDOC2ARGS_##args; /* fix register damage. */ \ + cmn r0, $4096; + +# define DOCARGS_0 +# define UNDOCARGS_0 +# define UNDOC2ARGS_0 + +# define DOCARGS_1 str r0, [sp, #-4]!; +# define UNDOCARGS_1 ldr r0, [sp], #4; +# define UNDOC2ARGS_1 + +# define DOCARGS_2 str r1, [sp, #-4]!; str r0, [sp, #-4]!; +# define UNDOCARGS_2 ldr r0, [sp], #4; ldr r1, [sp], #4; +# define UNDOC2ARGS_2 + +# define DOCARGS_3 str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!; +# define UNDOCARGS_3 ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4 +# define UNDOC2ARGS_3 + +# define DOCARGS_4 stmfd sp!, {r0-r3} +# define UNDOCARGS_4 ldmfd sp!, {r0-r3} +# define UNDOC2ARGS_4 + +# define DOCARGS_5 stmfd sp!, {r0-r3} +# define UNDOCARGS_5 ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24] +# define UNDOC2ARGS_5 ldr r4, [sp], #20 + +# ifdef IS_IN_libpthread +# define CENABLE bl PLTJMP(__pthread_enable_asynccancel) +# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# else +# define CENABLE bl PLTJMP(__libc_enable_asynccancel) +# define CDISABLE bl PLTJMP(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined PIC +# define SINGLE_THREAD_P_INT \ + ldr ip, =__local_multiple_threads; \ + ldr ip, [ip]; \ + teq ip, #0; +# define SINGLE_THREAD_P SINGLE_THREAD_P_INT +# define MAYBE_SAVE_LR \ + str lr, [sp, $-4]!; +# define PSEUDO_RET_MOV \ + RETINSTR(cc, lr); \ + b PLTJMP(SYSCALL_ERROR) +# define PSEUDO_PROLOGUE +# else +# define SINGLE_THREAD_P_PIC(reg) \ + ldr ip, 1b; \ + ldr reg, 2b; \ +3: \ + add ip, pc, ip; \ + ldr ip, [ip, reg]; \ + teq ip, #0; +# define SINGLE_THREAD_P_INT \ + str lr, [sp, $-4]!; \ + SINGLE_THREAD_P_PIC(lr) +# define SINGLE_THREAD_P \ + SINGLE_THREAD_P_INT; \ + ldr lr, [sp], $4 +# define PSEUDO_PROLOGUE \ + 1: .word _GLOBAL_OFFSET_TABLE_ - 3f - 8; \ + 2: .word __local_multiple_threads(GOTOFF); +# define MAYBE_SAVE_LR /* lr already saved */ +# define PSEUDO_RET_MOV PSEUDO_RET +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 0000000000..2708c701eb --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,80 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <philb@gnu.org>. + + 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <kernel-features.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + + PSEUDO_PROLOGUE + +ENTRY (__vfork) + +#ifdef __NR_vfork + +#ifdef SHARED + ldr ip, 1f + ldr r0, 2f +3: add ip, pc, ip + ldr r0, [ip, r0] +#else + ldr r0, 1f +#endif + movs r0, r0 + bne HIDDEN_JUMPTARGET (__fork) + + swi __NR_vfork + cmn a1, #4096 + RETINSTR(cc, lr) + +#ifndef __ASSUME_VFORK_SYSCALL + /* Check if vfork syscall is known at all. */ + cmn a1, #ENOSYS + bne PLTJMP(C_SYMBOL_NAME(__syscall_error)) +#endif + +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + swi __NR_fork + cmn a1, #4096 + RETINSTR(cc, lr) +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif + b PLTJMP(C_SYMBOL_NAME(__syscall_error)) + +#ifdef SHARED +1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8 +2: .word __libc_pthread_functions(GOTOFF) +#else + .weak pthread_create +1: .word pthread_create +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h new file mode 100644 index 0000000000..ed6c3c589b --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux version. + Copyright (C) 1993-1998,2000,2002,2003,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 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 16384 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h b/linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h new file mode 100644 index 0000000000..71b7e74649 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/bits/posix_opt.h @@ -0,0 +1,181 @@ +/* Define POSIX options for Linux. + Copyright (C) 1996-2001, 2002, 2003, 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 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; 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 _POSIX_OPT_H +#define _POSIX_OPT_H 1 + +/* Job control is supported. */ +#define _POSIX_JOB_CONTROL 1 + +/* Processes have a saved set-user-ID and a saved set-group-ID. */ +#define _POSIX_SAVED_IDS 1 + +/* Priority scheduling is supported. */ +#define _POSIX_PRIORITY_SCHEDULING 200112L + +/* Synchronizing file data is supported. */ +#define _POSIX_SYNCHRONIZED_IO 200112L + +/* The fsync function is present. */ +#define _POSIX_FSYNC 200112L + +/* Mapping of files to memory is supported. */ +#define _POSIX_MAPPED_FILES 200112L + +/* Locking of all memory is supported. */ +#define _POSIX_MEMLOCK 200112L + +/* Locking of ranges of memory is supported. */ +#define _POSIX_MEMLOCK_RANGE 200112L + +/* Setting of memory protections is supported. */ +#define _POSIX_MEMORY_PROTECTION 200112L + +/* Only root can change owner of file. */ +#define _POSIX_CHOWN_RESTRICTED 1 + +/* `c_cc' member of 'struct termios' structure can be disabled by + using the value _POSIX_VDISABLE. */ +#define _POSIX_VDISABLE '\0' + +/* Filenames are not silently truncated. */ +#define _POSIX_NO_TRUNC 1 + +/* X/Open realtime support is available. */ +#define _XOPEN_REALTIME 1 + +/* X/Open realtime thread support is available. */ +#define _XOPEN_REALTIME_THREADS 1 + +/* XPG4.2 shared memory is supported. */ +#define _XOPEN_SHM 1 + +/* Tell we have POSIX threads. */ +#define _POSIX_THREADS 200112L + +/* We have the reentrant functions described in POSIX. */ +#define _POSIX_REENTRANT_FUNCTIONS 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +/* We provide priority scheduling for threads. */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L + +/* We support user-defined stack sizes. */ +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* We support user-defined stacks. */ +#define _POSIX_THREAD_ATTR_STACKADDR 200112L + +/* We support POSIX.1b semaphores, but only the non-shared form for now. */ +#define _POSIX_SEMAPHORES 200112L + +/* Real-time signals are supported. */ +#define _POSIX_REALTIME_SIGNALS 200112L + +/* We support asynchronous I/O. */ +#define _POSIX_ASYNCHRONOUS_IO 200112L +#define _POSIX_ASYNC_IO 1 +/* Alternative name for Unix98. */ +#define _LFS_ASYNCHRONOUS_IO 1 +/* Support for prioritization is also available. */ +#define _POSIX_PRIORITIZED_IO 200112L + +/* The LFS support in asynchronous I/O is also available. */ +#define _LFS64_ASYNCHRONOUS_IO 1 + +/* The rest of the LFS is also available. */ +#define _LFS_LARGEFILE 1 +#define _LFS64_LARGEFILE 1 +#define _LFS64_STDIO 1 + +/* POSIX shared memory objects are implemented. */ +#define _POSIX_SHARED_MEMORY_OBJECTS 200112L + +/* CPU-time clocks support needs to be checked at runtime. */ +#define _POSIX_CPUTIME 0 + +/* Clock support in threads must be also checked at runtime. */ +#define _POSIX_THREAD_CPUTIME 0 + +/* GNU libc provides regular expression handling. */ +#define _POSIX_REGEXP 1 + +/* Reader/Writer locks are available. */ +#define _POSIX_READER_WRITER_LOCKS 200112L + +/* We have a POSIX shell. */ +#define _POSIX_SHELL 1 + +/* We support the Timeouts option. */ +#define _POSIX_TIMEOUTS 200112L + +/* We support spinlocks. */ +#define _POSIX_SPIN_LOCKS 200112L + +/* The `spawn' function family is supported. */ +#define _POSIX_SPAWN 200112L + +/* We have POSIX timers. */ +#define _POSIX_TIMERS 200112L + +/* The barrier functions are available. */ +#define _POSIX_BARRIERS 200112L + +/* POSIX message queues are available. */ +#define _POSIX_MESSAGE_PASSING 200112L + +/* Thread process-shared synchronization is not supported. */ +#define _POSIX_THREAD_PROCESS_SHARED -1 + +/* The monotonic clock might be available. */ +#define _POSIX_MONOTONIC_CLOCK 0 + +/* The clock selection interfaces are not available. */ +#define _POSIX_CLOCK_SELECTION -1 + +/* Advisory information interfaces are available. */ +#define _POSIX_ADVISORY_INFO 200112L + +/* IPv6 support is available. */ +#define _POSIX_IPV6 200112L + +/* Raw socket support is available. */ +#define _POSIX_RAW_SOCKETS 200112L + +/* We have at least one terminal. */ +#define _POSIX2_CHAR_TERM 200112L + +/* Neither process nor thread sporadic server interfaces is available. */ +#define _POSIX_SPORADIC_SERVER -1 +#define _POSIX_THREAD_SPORADIC_SERVER -1 + +/* trace.h is not available. */ +#define _POSIX_TRACE -1 +#define _POSIX_TRACE_EVENT_FILTER -1 +#define _POSIX_TRACE_INHERIT -1 +#define _POSIX_TRACE_LOG -1 + +/* Typed memory objects are not available. */ +#define _POSIX_TYPED_MEMORY_OBJECTS -1 + +/* No support for priority inheritance or protection. */ +#define _POSIX_THREAD_PRIO_INHERIT -1 +#define _POSIX_THREAD_PRIO_PROTECT -1 + +#endif /* posix_opt.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/bits/sigthread.h b/linuxthreads/sysdeps/unix/sysv/linux/bits/sigthread.h new file mode 100644 index 0000000000..960bde18a9 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/bits/sigthread.h @@ -0,0 +1,38 @@ +/* Signal handling function for threaded programs. + Copyright (C) 1998, 1999, 2000, 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; 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 _BITS_SIGTHREAD_H +#define _BITS_SIGTHREAD_H 1 + +#if !defined _SIGNAL_H && !defined _PTHREAD_H +# error "Never include this file directly. Use <pthread.h> instead" +#endif + +/* Functions for handling signals. */ + +/* Modify the signal mask for the calling thread. The arguments have + the same meaning as for sigprocmask(2). */ +extern int pthread_sigmask (int __how, + __const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__THROW; + +/* Send signal SIGNO to the given thread. */ +extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; + +#endif /* bits/sigthread.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/execve.c b/linuxthreads/sysdeps/unix/sysv/linux/execve.c new file mode 100644 index 0000000000..9fa912b90d --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/execve.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1999, 2000, 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. */ + +#include <errno.h> +#include <unistd.h> + +#include <sysdep.h> +#include <alloca.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +extern int __syscall_execve (const char *__unbounded file, + char *__unbounded const *__unbounded argv, + char *__unbounded const *__unbounded envp); +extern void __pthread_kill_other_threads_np (void); +weak_extern (__pthread_kill_other_threads_np) + + +int +__execve (file, argv, envp) + const char *file; + char *const argv[]; + char *const envp[]; +{ + /* If this is a threaded application kill all other threads. */ + if (__pthread_kill_other_threads_np) + __pthread_kill_other_threads_np (); +#if __BOUNDED_POINTERS__ + { + char *const *v; + int i; + char *__unbounded *__unbounded ubp_argv; + char *__unbounded *__unbounded ubp_envp; + char *__unbounded *__unbounded ubp_v; + + for (v = argv; *v; v++) + ; + i = v - argv + 1; + ubp_argv = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_argv) * i); + for (v = argv, ubp_v = ubp_argv; --i; v++, ubp_v++) + *ubp_v = CHECK_STRING (*v); + *ubp_v = 0; + + for (v = envp; *v; v++) + ; + i = v - envp + 1; + ubp_envp = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_envp) * i); + for (v = envp, ubp_v = ubp_envp; --i; v++, ubp_v++) + *ubp_v = CHECK_STRING (*v); + *ubp_v = 0; + + return INLINE_SYSCALL (execve, 3, CHECK_STRING (file), ubp_argv, ubp_envp); + } +#else + return INLINE_SYSCALL (execve, 3, file, argv, envp); +#endif +} +weak_alias (__execve, execve) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/fork.c b/linuxthreads/sysdeps/unix/sysv/linux/fork.c new file mode 100644 index 0000000000..00eb787093 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <errno.h> +#include <fork.h> +#include <bits/libc-lock.h> + +#ifndef SHARED +weak_extern (__pthread_fork); +#endif + +struct fork_block __fork_block = +{ + .lock = PTHREAD_MUTEX_INITIALIZER, + .prepare_list = { &__fork_block.prepare_list, &__fork_block.prepare_list }, + .parent_list = { &__fork_block.parent_list, &__fork_block.parent_list }, + .child_list = { &__fork_block.child_list, &__fork_block.child_list } +}; + +pid_t +__libc_fork (void) +{ + return __libc_maybe_call2 (pthread_fork, (&__fork_block), ARCH_FORK ()); +} +weak_alias (__libc_fork, __fork) +libc_hidden_def (__fork) +weak_alias (__libc_fork, fork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/fork.h new file mode 100644 index 0000000000..76708e3e39 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/fork.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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. */ + +#include <list.h> +#include <bits/libc-lock.h> +#include <sysdep.h> + +struct fork_block +{ + /* Lock to protect handling of fork handlers. */ + __libc_lock_define (, lock); + + /* Lists of registered fork handlers. */ + list_t prepare_list; + list_t parent_list; + list_t child_list; +}; + +extern struct fork_block __fork_block attribute_hidden; + +/* Elements of the fork handler lists. */ +struct fork_handler +{ + list_t list; + void (*handler) (void); + void *dso_handle; +}; + + +/* Function to call to unregister fork handlers. */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers. */ +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *dso_handle); +libc_hidden_proto (__register_atfork) + +#ifndef ARCH_FORK +# define ARCH_FORK() INLINE_SYSCALL (fork, 0) +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c b/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c new file mode 100644 index 0000000000..0d6da82919 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c @@ -0,0 +1,33 @@ +#include <shlib-compat.h> + +#define aio_cancel64 XXX +#include <aio.h> +#undef aio_cancel64 +#include <errno.h> + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h b/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h new file mode 100644 index 0000000000..9b13400286 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h @@ -0,0 +1,27 @@ +/* PA-RISC specific definitions for spinlock initializers. + Copyright (C) 2000, 2001 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. PA-RISC only implements atomic load + and clear so this must be non-zero. */ +#define __LT_SPINLOCK_INIT 1 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h b/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h new file mode 100644 index 0000000000..817cf59222 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h @@ -0,0 +1,73 @@ +/* HP-PARISC macro definitions for mutexes, thread-specific data + and parameters for malloc. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003. + + 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 _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include <atomic.h> +#include <bits/libc-lock.h> + +__libc_lock_define (typedef, mutex_t) + +/* Since our lock structure does not tolerate being initialized to zero, we must + modify the standard function calls made by malloc */ +# define mutex_init(m) \ + __libc_maybe_call (__pthread_mutex_init, (m, NULL), \ + (((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT),(*(int *)(m))) ) +# define mutex_lock(m) \ + __libc_maybe_call (__pthread_mutex_lock, (m), \ + (__load_and_clear(&((m)->__m_lock.__spinlock)), 0)) +# define mutex_trylock(m) \ + __libc_maybe_call (__pthread_mutex_trylock, (m), \ + (*(int *)(m) ? 1 : (__load_and_clear(&((m)->__m_lock.__spinlock)), 0))) +# define mutex_unlock(m) \ + __libc_maybe_call (__pthread_mutex_unlock, (m), \ + (((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT), (*(int *)(m))) ) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include <fork.h> + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include <bits/libc-tsd.h> + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include <sysdeps/generic/malloc-machine.h> + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c new file mode 100644 index 0000000000..27f850cf8f --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c @@ -0,0 +1,109 @@ +/* Special .init and .fini section support for HPPA. Linuxthreads version. + Copyright (C) 2001, 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 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +/* If we use the standard C version, the linkage table pointer won't + be properly preserved due to the splitting up of function prologues + and epilogues. Therefore we write these in assembly to make sure + they do the right thing. */ + +__asm__ ( +"#include \"defs.h\"\n" +"\n" +"/*@HEADER_ENDS*/\n" +"\n" +"/*@_init_PROLOG_BEGINS*/\n" +" .section .init\n" +" .align 4\n" +" .globl _init\n" +" .type _init,@function\n" +"_init:\n" +" stw %rp,-20(%sp)\n" +" stwm %r4,64(%sp)\n" +" stw %r19,-32(%sp)\n" +" bl __pthread_initialize_minimal,%rp\n" +" copy %r19,%r4 /* delay slot */\n" +" copy %r4,%r19\n" +"/*@_init_PROLOG_ENDS*/\n" +"\n" +"/*@_init_EPILOG_BEGINS*/\n" +"/* Here is the tail end of _init. */\n" +" .section .init\n" +" ldw -84(%sp),%rp\n" +" copy %r4,%r19\n" +" bv %r0(%rp)\n" +"_end_init:\n" +" ldwm -64(%sp),%r4\n" +"\n" +"/* Our very own unwind info, because the assembler can't handle\n" +" functions split into two or more pieces. */\n" +" .section .PARISC.unwind,\"a\",@progbits\n" +" .extern _init\n" +" .word _init, _end_init\n" +" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n" +"\n" +"/*@_init_EPILOG_ENDS*/\n" +"\n" +"/*@_fini_PROLOG_BEGINS*/\n" +" .section .fini\n" +" .align 4\n" +" .globl _fini\n" +" .type _fini,@function\n" +"_fini:\n" +" stw %rp,-20(%sp)\n" +" stwm %r4,64(%sp)\n" +" stw %r19,-32(%sp)\n" +" copy %r19,%r4\n" +"/*@_fini_PROLOG_ENDS*/\n" +"\n" +"/*@_fini_EPILOG_BEGINS*/\n" +" .section .fini\n" +" ldw -84(%sp),%rp\n" +" copy %r4,%r19\n" +" bv %r0(%rp)\n" +"_end_fini:\n" +" ldwm -64(%sp),%r4\n" +"\n" +" .section .PARISC.unwind,\"a\",@progbits\n" +" .extern _fini\n" +" .word _fini, _end_fini\n" +" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n" +"\n" +"/*@_fini_EPILOG_ENDS*/\n" +"\n" +"/*@TRAILER_BEGINS*/\n" +); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h new file mode 100644 index 0000000000..134977e074 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h @@ -0,0 +1,189 @@ +/* cancellable system calls for Linux/HPPA. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003. + + 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. */ + +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifndef NO_ERROR +# define NO_ERROR -0x1000 +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + ENTRY (name) \ + SINGLE_THREAD_P ASM_LINE_SEP \ + cmpib,<> 0,%ret0,Lpseudo_cancel ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + DO_CALL(syscall_name, args) ASM_LINE_SEP \ + /* DONE! */ ASM_LINE_SEP \ + bv 0(2) ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + Lpseudo_cancel: ASM_LINE_SEP \ + /* store return ptr */ ASM_LINE_SEP \ + stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \ + /* save syscall args */ ASM_LINE_SEP \ + PUSHARGS_##args /* MACRO */ ASM_LINE_SEP \ + STW_PIC ASM_LINE_SEP \ + CENABLE /* FUNC CALL */ ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* restore syscall args */ ASM_LINE_SEP \ + POPARGS_##args ASM_LINE_SEP \ + /* save r4 in arg0 stack slot */ ASM_LINE_SEP \ + stw %r4, -36(%sr0,%sp) ASM_LINE_SEP \ + /* save mask from cenable */ ASM_LINE_SEP \ + copy %ret0, %r4 ASM_LINE_SEP \ + ble 0x100(%sr2,%r0) ASM_LINE_SEP \ + ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* pass mask as arg0 to cdisable */ ASM_LINE_SEP \ + copy %r4, %r26 ASM_LINE_SEP \ + copy %ret0, %r4 ASM_LINE_SEP \ + CDISABLE ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* compare error */ ASM_LINE_SEP \ + ldi NO_ERROR,%r1 ASM_LINE_SEP \ + /* branch if no error */ ASM_LINE_SEP \ + cmpb,>>=,n %r1,%r4,Lpre_end ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + SYSCALL_ERROR_HANDLER ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + /* No need to LDW_PIC */ ASM_LINE_SEP \ + /* make syscall res value positive */ ASM_LINE_SEP \ + sub %r0, %r4, %r4 ASM_LINE_SEP \ + /* store into errno location */ ASM_LINE_SEP \ + stw %r4, 0(%sr0,%ret0) ASM_LINE_SEP \ + /* return -1 */ ASM_LINE_SEP \ + ldo -1(%r0), %ret0 ASM_LINE_SEP \ + Lpre_end: ASM_LINE_SEP \ + ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \ + /* No need to LDW_PIC */ ASM_LINE_SEP \ + ldw -36(%sr0,%sp), %r4 ASM_LINE_SEP + +/* Save arguments into our frame */ +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_5 PUSHARGS_4 /* Args are on the stack... */ +# define PUSHARGS_6 PUSHARGS_5 + +/* Bring them back from the stack */ +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP +# define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP +# define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP +# define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP +# define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP +# define POPARGS_6 POPARGS_5 ldw -54(%sr0,%sp), %r21 ASM_LINE_SEP + +# ifdef IS_IN_libpthread +# ifdef PIC +# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# elif !defined NOT_IN_libc +# ifdef PIC +# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \ + bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \ + bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \ + bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \ + bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# else +# ifdef PIC +# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \ + bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \ + bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \ + bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \ + bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# endif + +/* p_header.multiple_threads is +12 from the pthread_descr struct start, + We could have called __get_cr27() but we really want less overhead */ +# define MULTIPLE_THREADS_OFFSET 0xC + +/* cr27 has been initialized to 0x0 by kernel */ +# define NO_THREAD_CR27 0x0 + +# ifdef IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifndef __ASSEMBLER__ + extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +/* This ALT version requires newer kernel support */ +# define SINGLE_THREAD_P_MFCTL \ + mfctl %cr27, %ret0 ASM_LINE_SEP \ + cmpib,= NO_THREAD_CR27,%ret0,Lstp ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \ + Lstp: ASM_LINE_SEP +# ifdef PIC +/* Slower version uses GOT to get value of __local_multiple_threads */ +# define SINGLE_THREAD_P \ + addil LT%__local_multiple_threads, %r19 ASM_LINE_SEP \ + ldw RT%__local_multiple_threads(%sr0,%r1), %ret0 ASM_LINE_SEP \ + ldw 0(%sr0,%ret0), %ret0 ASM_LINE_SEP +# else + /* Slow non-pic version using DP */ +# define SINGLE_THREAD_P \ + addil LR%__local_multiple_threads-$global$,%r27 ASM_LINE_SEP \ + ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0 ASM_LINE_SEP +# endif +# endif +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif +/* !defined NOT_IN_libc || defined IS_IN_libpthread */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h b/linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h new file mode 100644 index 0000000000..5355310ccd --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/dl-sysdep.h @@ -0,0 +1,64 @@ +/* System-specific settings for dynamic linker code. IA-32 version. + Copyright (C) 2002, 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 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 _DL_SYSDEP_H +#define _DL_SYSDEP_H 1 + +/* This macro must be defined to either 0 or 1. + + If 1, then an errno global variable hidden in ld.so will work right with + all the errno-using libc code compiled for ld.so, and there is never a + need to share the errno location with libc. This is appropriate only if + all the libc functions that ld.so uses are called without PLT and always + get the versions linked into ld.so rather than the libc ones. */ + +#ifdef IS_IN_rtld +# define RTLD_PRIVATE_ERRNO 1 +#else +# define RTLD_PRIVATE_ERRNO 0 +#endif + +/* Traditionally system calls have been made using int $0x80. A + second method was introduced which, if possible, will use the + sysenter/syscall instructions. To signal the presence and where to + find the code the kernel passes an AT_SYSINFO value in the + auxiliary vector to the application. + sysenter/syscall is not useful on i386 through i586, but the dynamic + linker and dl code in libc.a has to be able to load i686 compiled + libraries. */ +#define NEED_DL_SYSINFO 1 +#undef USE_DL_SYSINFO + +#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__ +extern void _dl_sysinfo_int80 (void) attribute_hidden; +# define DL_SYSINFO_DEFAULT (uintptr_t) _dl_sysinfo_int80 +# define DL_SYSINFO_IMPLEMENTATION \ + asm (".text\n\t" \ + ".type _dl_sysinfo_int80,@function\n\t" \ + ".hidden _dl_sysinfo_int80\n" \ + CFI_STARTPROC "\n" \ + "_dl_sysinfo_int80:\n\t" \ + "int $0x80;\n\t" \ + "ret;\n\t" \ + CFI_ENDPROC "\n" \ + ".size _dl_sysinfo_int80,.-_dl_sysinfo_int80\n\t" \ + ".previous"); +#endif + +#endif /* dl-sysdep.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 0000000000..7865f7165e --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,179 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#include <pt-machine.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHCARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + int $0x80 \ + POPCARGS_##args; \ + POPSTATE_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %ecx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; +# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 + +# define PUSHCARGS_0 /* No arguments to push. */ +# define DOCARGS_0 /* No arguments to frob. */ +# define POPCARGS_0 /* No arguments to pop. */ +# define _PUSHCARGS_0 /* No arguments to push. */ +# define _POPCARGS_0 /* No arguments to pop. */ + +# define PUSHCARGS_1 movl %ebx, %edx; PUSHCARGS_0 +# define DOCARGS_1 _DOARGS_1 (4) +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx +# define _PUSHCARGS_1 pushl %ebx; L(PUSHBX2): _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; L(POPBX2): + +# define PUSHCARGS_2 PUSHCARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define POPCARGS_2 POPCARGS_1 +# define _PUSHCARGS_2 _PUSHCARGS_1 +# define _POPCARGS_2 _POPCARGS_1 + +# define PUSHCARGS_3 _PUSHCARGS_2 +# define DOCARGS_3 _DOARGS_3 (20) +# define POPCARGS_3 _POPCARGS_3 +# define _PUSHCARGS_3 _PUSHCARGS_2 +# define _POPCARGS_3 _POPCARGS_2 + +# define PUSHCARGS_4 _PUSHCARGS_4 +# define DOCARGS_4 _DOARGS_4 (28) +# define POPCARGS_4 _POPCARGS_4 +# define _PUSHCARGS_4 pushl %esi; L(PUSHSI2): _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; L(POPSI2): + +# define PUSHCARGS_5 _PUSHCARGS_5 +# define DOCARGS_5 _DOARGS_5 (36) +# define POPCARGS_5 _POPCARGS_5 +# define _PUSHCARGS_5 pushl %edi; L(PUSHDI2): _PUSHCARGS_4 +# define _POPCARGS_5 _POPCARGS_4; popl %edi; L(POPDI2): + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel +# elif defined IS_IN_librt +# ifdef PIC +# define CENABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_enable_asynccancel@PLT; \ + popl %ebx; +# define CDISABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_disable_asynccancel@PLT; \ + popl %ebx; +# else +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel +# endif +# else +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# endif +# define POPSTATE_0 pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax; +# define POPSTATE_1 POPSTATE_0 +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; +# define POPSTATE_3 POPSTATE_2 +# define POPSTATE_4 POPSTATE_2 +# define POPSTATE_5 POPSTATE_2 + +#if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +#elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +#else +# define __local_multiple_threads __librt_multiple_threads +#endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined PIC +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined PIC +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define __SINGLE_THREAD_CMP cmpl $0, __local_multiple_threads@GOTOFF(%ecx) +# else +# define __SINGLE_THREAD_CMP \ + movl __local_multiple_threads@GOT(%ecx), %ecx;\ + cmpl $0, (%ecx) +# endif +# if !defined HAVE_HIDDEN || !USE___THREAD +# define SINGLE_THREAD_P \ + SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# else +# define SINGLE_THREAD_P \ + call __i686.get_pc_thunk.cx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 0000000000..c7a120d239 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S @@ -0,0 +1,95 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab <schwab@gnu.org>. + + 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <kernel-features.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork + +# ifdef SHARED +# if !defined HAVE_HIDDEN || !USE___THREAD + SETUP_PIC_REG (cx) +# else + call __i686.get_pc_thunk.cx +# endif + addl $_GLOBAL_OFFSET_TABLE_, %ecx + cmpl $0, __libc_pthread_functions@GOTOFF(%ecx) +# else + .weak pthread_create + movl $pthread_create, %eax + testl %eax, %eax +# endif + jne HIDDEN_JUMPTARGET (__fork) + + /* Pop the return PC value into ECX. */ + popl %ecx + + /* Stuff the syscall number in EAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + int $0x80 + + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + + cmpl $-4095, %eax + /* Branch forward if it failed. */ +# ifdef __ASSUME_VFORK_SYSCALL + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: +# else + jae .Lerror +# endif + + ret + +# ifndef __ASSUME_VFORK_SYSCALL +.Lerror: + /* Check if vfork syscall is known at all. */ + cmpl $-ENOSYS, %eax + jne SYSCALL_ERROR_LABEL +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + movl $SYS_ify (fork), %eax + int $0x80 + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: + ret +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile new file mode 100644 index 0000000000..e03aee99fc --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),linuxthreads) +libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask +endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions new file mode 100644 index 0000000000..d102772482 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/Versions @@ -0,0 +1,6 @@ +libpthread { + GLIBC_2.3.3 { + # Changed PTHREAD_STACK_MIN. + pthread_attr_setstack; pthread_attr_setstacksize; + } +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h new file mode 100644 index 0000000000..629b1f89c1 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002,2003,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 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 196608 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h new file mode 100644 index 0000000000..27d5fdfbf5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h @@ -0,0 +1,49 @@ +/* System-specific settings for dynamic linker code. IA-64 version. + Copyright (C) 2003, 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 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 _DL_SYSDEP_H +#define _DL_SYSDEP_H 1 + +#define NEED_DL_SYSINFO 1 +#undef USE_DL_SYSINFO + +#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__ +/* Don't declare this as a function---we want it's entry-point, not + it's function descriptor... */ +extern int _dl_sysinfo_break attribute_hidden; +# define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break) +# define DL_SYSINFO_IMPLEMENTATION \ + asm (".text\n\t" \ + ".hidden _dl_sysinfo_break\n\t" \ + ".proc _dl_sysinfo_break\n\t" \ + "_dl_sysinfo_break:\n\t" \ + ".prologue\n\t" \ + ".altrp b6\n\t" \ + ".body\n\t" \ + "break 0x100000;\n\t" \ + "br.ret.sptk.many b6;\n\t" \ + ".endp _dl_sysinfo_break" \ + ".previous"); +#endif + +/* _dl_argv cannot be attribute_relro, because _dl_start_user + might write into it after _dl_start returns. */ +#define DL_ARGV_NOT_RELRO 1 + +#endif /* dl-sysdep.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h new file mode 100644 index 0000000000..30a0cc1918 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <signal.h> +#include <sysdep.h> + +#define ARCH_FORK() INLINE_SYSCALL (clone, 2, SIGCHLD, 0) + +#include_next <fork.h> diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c new file mode 100644 index 0000000000..85fd33f4a8 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c @@ -0,0 +1,140 @@ +/* Special .init and .fini section support for ia64. LinuxThreads version. + Copyright (C) 2000, 2001, 2002, 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 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include <stddef.h> + +#ifdef HAVE_INITFINI_ARRAY + +# define INIT_NEW_WAY \ + ".xdata8 \".init_array\", @fptr(__pthread_initialize_minimal)\n" +# define INIT_OLD_WAY "" +#else +# define INIT_NEW_WAY "" +# define INIT_OLD_WAY \ + "\n\ + st8 [r12] = gp, -16\n\ + br.call.sptk.many b0 = __pthread_initialize_minimal# ;;\n\ + ;;\n\ + adds r12 = 16, r12\n\ + ;;\n\ + ld8 gp = [r12]\n\ + ;;\n" +#endif + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n" + INIT_NEW_WAY + ".section .init\n\ + .align 16\n\ + .global _init#\n\ + .proc _init#\n\ +_init:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + .vframe r32\n\ + mov r32 = r12\n\ + .save rp, r33\n\ + mov r33 = b0\n\ + .body\n\ + adds r12 = -16, r12\n\ + ;;\n" + INIT_OLD_WAY + ".endp _init#\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + .proc _init#\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + .vframe r32\n\ + .save rp, r33\n\ + .body\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _init#\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 16\n\ + .global _fini#\n\ + .proc _fini#\n\ +_fini:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + .vframe r32\n\ + mov r32 = r12\n\ + .save rp, r33\n\ + mov r33 = b0\n\ + .body\n\ + adds r12 = -16, r12\n\ + ;;\n\ + .endp _fini#\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + .proc _fini#\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + .vframe r32\n\ + .save rp, r33\n\ + .body\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _fini#\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + .weak __gmon_start__#\n\ +"); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c new file mode 100644 index 0000000000..0b96e3d5bd --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c @@ -0,0 +1,33 @@ +/* Internal sigsuspend system call for LinuxThreads. IA64 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 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. */ + +#include <errno.h> +#include <signal.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <linuxthreads/internals.h> + +void +__pthread_sigsuspend (const sigset_t *set) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8); +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h new file mode 100644 index 0000000000..dd9637d2b5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef IS_IN_librt +# define PSEUDO_NLOCAL 6 +# define PSEUDO_SAVE_GP mov loc5 = gp +# define PSEUDO_RESTORE_GP mov gp = loc5 +# define PSEUDO_SAVE_GP_1 +# define PSEUDO_RESTORE_GP_1 mov gp = loc5 +# else +# define PSEUDO_NLOCAL 5 +# define PSEUDO_SAVE_GP +# define PSEUDO_RESTORE_GP +# define PSEUDO_SAVE_GP_1 mov loc4 = gp;; +# define PSEUDO_RESTORE_GP_1 mov gp = loc4 +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +.text; \ +ENTRY (name) \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13;; \ + ld4 r14 = [r14]; \ + mov r15 = SYS_ify(syscall_name);; \ + cmp4.ne p6, p7 = 0, r14; \ +(p6) br.cond.spnt .Lpseudo_cancel;; \ + break __BREAK_SYSCALL;; \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; \ + ret;; \ + .endp name; \ + .proc __GC_##name; \ + .globl __GC_##name; \ + .hidden __GC_##name; \ +__GC_##name: \ +.Lpseudo_cancel: \ + .prologue; \ + .regstk args, PSEUDO_NLOCAL, args, 0; \ + .save ar.pfs, loc0; \ + alloc loc0 = ar.pfs, args, PSEUDO_NLOCAL, args, 0; \ + .save rp, loc1; \ + mov loc1 = rp; \ + PSEUDO_SAVE_GP;; \ + .body; \ + CENABLE;; \ + PSEUDO_RESTORE_GP; \ + mov loc2 = r8; \ + COPY_ARGS_##args \ + mov r15 = SYS_ify(syscall_name); \ + break __BREAK_SYSCALL;; \ + mov loc3 = r8; \ + mov loc4 = r10; \ + mov out0 = loc2; \ + CDISABLE;; \ + PSEUDO_RESTORE_GP; \ + cmp.eq p6,p0=-1,loc4; \ +(p6) br.cond.spnt.few __syscall_error_##args; \ + mov r8 = loc3; \ + mov rp = loc1; \ + mov ar.pfs = loc0; \ +.Lpseudo_end: \ + ret; \ + .endp __GC_##name; \ +.section .gnu.linkonce.t.__syscall_error_##args, "ax"; \ + .align 32; \ + .proc __syscall_error_##args; \ + .global __syscall_error_##args; \ + .hidden __syscall_error_##args; \ + .size __syscall_error_##args, 64; \ +__syscall_error_##args: \ + .prologue; \ + .regstk args, PSEUDO_NLOCAL, args, 0; \ + .save ar.pfs, loc0; \ + .save rp, loc1; \ + .body; \ + PSEUDO_SAVE_GP_1; \ + br.call.sptk.many b0 = __errno_location;; \ + st4 [r8] = loc3; \ + PSEUDO_RESTORE_GP_1; \ + mov rp = loc1; \ + mov r8 = -1; \ + mov ar.pfs = loc0 + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp + +# ifdef IS_IN_libpthread +# define CENABLE br.call.sptk.many b0 = __pthread_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE br.call.sptk.many b0 = __libc_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __libc_disable_asynccancel +# else +# define CENABLE br.call.sptk.many b0 = __librt_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov out0 = in0; +#define COPY_ARGS_2 COPY_ARGS_1 mov out1 = in1; +#define COPY_ARGS_3 COPY_ARGS_2 mov out2 = in2; +#define COPY_ARGS_4 COPY_ARGS_3 mov out3 = in3; +#define COPY_ARGS_5 COPY_ARGS_4 mov out4 = in4; +#define COPY_ARGS_6 COPY_ARGS_5 mov out5 = in5; +#define COPY_ARGS_7 COPY_ARGS_6 mov out6 = in6; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S new file mode 100644 index 0000000000..54acedad4c --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2000, 2002, 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 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. */ + + +#include <sysdep-cancel.h> +#define _SIGNAL_H +#include <bits/signum.h> + +/* The following are defined in linux/sched.h, which unfortunately */ +/* is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY(__vfork) +#ifdef SHARED + addl r14 = @gprel(__libc_pthread_functions#), gp;; +#else + .weak pthread_create + addl r14 = @ltoff(@fptr(pthread_create#)), gp;; +#endif + ld8 r14 = [r14];; + cmp.ne p6, p7 = 0, r14 +(p6) br.cond.spnt.few HIDDEN_JUMPTARGET (__fork);; + alloc r2=ar.pfs,0,0,2,0 + mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 + ;; +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c b/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c new file mode 100644 index 0000000000..4b90315707 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -0,0 +1,34 @@ +/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. + Copyright (C) 2002, 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 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. */ + +#include <setjmp.h> +#include <stddef.h> +#include <bits/libc-lock.h> + +#ifndef SHARED +weak_extern (__pthread_cleanup_upto); +#endif + +void +_longjmp_unwind (jmp_buf env, int val) +{ + __libc_maybe_call2 (pthread_cleanup_upto, + (env->__jmpbuf, __builtin_frame_address (0)), + (void) 0); +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h new file mode 100644 index 0000000000..bb798e40d6 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab <schwab@suse.de>, 2002. + + 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. */ + +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + cmp.l &-4095, %d0; \ + jcc SYSCALL_ERROR_LABEL; \ + rts; \ + .Lpseudo_cancel: \ + CENABLE; \ + DOCARGS_##args \ + move.l %d0, -(%sp); \ + move.l &SYS_ify (syscall_name), %d0; \ + trap &0; \ + move.l %d0, %d2; \ + CDISABLE; \ + addq.l &4, %sp; \ + move.l %d2, %d0; \ + UNDOCARGS_##args \ + cmp.l &-4095, %d0; \ + jcc SYSCALL_ERROR_LABEL + +# define DOCARGS_0 move.l %d2, -(%sp); +# define _DOCARGS_0(n) +# define UNDOCARGS_0 move.l (%sp)+, %d2; + +# define DOCARGS_1 _DOCARGS_1 (4); DOCARGS_0 +# define _DOCARGS_1(n) move.l n(%sp), %d1; _DOARGS_0 (n) +# define UNDOCARGS_1 UNDOCARGS_0 + +# define DOCARGS_2 _DOCARGS_2 (8) +# define _DOCARGS_2(n) move.l %d2, -(%sp); move.l n+4(%sp), %d2; \ + _DOCARGS_1 (n) +# define UNDOCARGS_2 UNDOCARGS_1 + +# define DOCARGS_3 _DOCARGS_3 (12) +# define _DOCARGS_3(n) move.l %d3, -(%sp); move.l n+4(%sp), %d3; \ + _DOCARGS_2 (n) +# define UNDOCARGS_3 UNDOCARGS_2; move.l (%sp)+, %d3; + +# define DOCARGS_4 _DOCARGS_4 (16) +# define _DOCARGS_4(n) move.l %d4, -(%sp); move.l n+4(%sp), %d4; \ + _DOCARGS_3 (n) +# define UNDOCARGS_4 UNDOCARGS_3; move.l (%sp)+, %d4; + +# define DOCARGS_5 _DOCARGS_5 (20) +# define _DOCARGS_5(n) move.l %d5, -(%sp); move.l n+4(%sp), %d5; \ + _DOCARGS_4 (n) +# define UNDOCARGS_5 UNDOCARGS_4; move.l (%sp)+, %d5; + +# ifdef IS_IN_libpthread +# ifdef PIC +# define CENABLE jbsr __pthread_enable_asynccancel@PLTPC +# define CDISABLE jbsr __pthread_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __pthread_enable_asynccancel +# define CDISABLE jbsr __pthread_disable_asynccancel +# endif +# elif !defined NOT_IN_libc +# ifdef PIC +# define CENABLE jbsr __libc_enable_asynccancel@PLTPC +# define CDISABLE jbsr __libc_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __libc_enable_asynccancel +# define CDISABLE jbsr __libc_disable_asynccancel +# endif +# else +# ifdef PIC +# define CENABLE jbsr __librt_enable_asynccancel@PLTPC +# define CDISABLE jbsr __librt_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __librt_enable_asynccancel +# define CDISABLE jbsr __librt_disable_asynccancel +# endif +# endif + +# if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined PIC +# define SINGLE_THREAD_P tst.l __local_multiple_threads +# else +# define SINGLE_THREAD_P tst.l (__local_multiple_threads, %pc) +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S new file mode 100644 index 0000000000..49b8a3c0ac --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S @@ -0,0 +1,84 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab <schwab@gnu.org>. + + 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <kernel-features.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef SHARED + tstl (__libc_pthread_functions@GOTPC, %pc) +#else + .weak pthread_create + movel #pthread_create, %d0 +#endif + jbne HIDDEN_JUMPTARGET (__fork) + +#ifdef __NR_vfork + + /* Pop the return PC value into A0. */ + movel %sp@+, %a0 + + /* Stuff the syscall number in D0 and trap into the kernel. */ + movel #SYS_ify (vfork), %d0 + trap #0 + tstl %d0 + jmi .Lerror /* Branch forward if it failed. */ + + /* Jump to the return PC. */ + jmp %a0@ + +.Lerror: + /* Push back the return PC. */ + movel %a0,%sp@- + +# ifdef __ASSUME_VFORK_SYSCALL +# ifndef PIC + jbra SYSCALL_ERROR_LABEL +# endif +# else + /* Check if vfork syscall is known at all. */ + movel #-ENOSYS,%d1 + cmpl %d0,%d1 + jne SYSCALL_ERROR_LABEL + +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + movel #SYS_ify (fork), %d0 + trap #0 + tstl %d0 + jmi SYSCALL_ERROR_LABEL + rts +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile new file mode 100644 index 0000000000..56eeecc789 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/mips/Makefile @@ -0,0 +1,3 @@ +# pull in __syscall_error routine +libpthread-routines += sysdep + diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h new file mode 100644 index 0000000000..fc51774252 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* system call stubs with cancellation handling. Linux/MIPS version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Demetriou of Broadcom Corporation, + based on work by Guido Guenther <agx@sigxcpu.org>. + + 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. */ + +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif +#include <sys/asm.h> + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: \ + PTR_LA t9,__syscall_error; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + jr t9; \ + ENTRY (name) \ + SAVESTK ; \ + .cpsetup t9, STKOFF_GP, name ; \ + .set reorder; \ + SINGLE_THREAD_P(t0); \ + bne zero, t0, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + ret; \ + L(pseudo_cancel): \ + REG_S ra, STKOFF_RA(sp); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + REG_S v0, STKOFF_SVMSK(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + REG_S v0, STKOFF_SC_V0(sp); /* save syscall result */ \ + REG_S a3, STKOFF_SC_ERR(sp); /* save syscall error flag */ \ + REG_L a0, STKOFF_SVMSK(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + REG_L a3, STKOFF_SC_ERR(sp); /* restore syscall error flag */ \ + REG_L ra, STKOFF_RA(sp); /* restore return address */ \ + REG_L v0, STKOFF_SC_V0(sp); /* restore syscall result */ \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + L(pseudo_end): +#endif + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 REG_S a0, STKOFF_A0(sp); +# define PUSHARGS_2 PUSHARGS_1 REG_S a1, STKOFF_A1(sp); +# define PUSHARGS_3 PUSHARGS_2 REG_S a2, STKOFF_A2(sp); +# define PUSHARGS_4 PUSHARGS_3 REG_S a3, STKOFF_A3(sp); +# define PUSHARGS_5 PUSHARGS_4 REG_S a4, STKOFF_A4(sp); +# define PUSHARGS_6 PUSHARGS_5 REG_S a5, STKOFF_A5(sp); + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 REG_L a0, STKOFF_A0(sp); +# define POPARGS_2 POPARGS_1 REG_L a1, STKOFF_A1(sp); +# define POPARGS_3 POPARGS_2 REG_L a2, STKOFF_A2(sp); +# define POPARGS_4 POPARGS_3 REG_L a3, STKOFF_A3(sp); +# define POPARGS_5 POPARGS_4 REG_L a4, STKOFF_A4(sp); +# define POPARGS_6 POPARGS_5 REG_L a5, STKOFF_A5(sp); + +/* Save an even number of slots. Should be 0 if an even number of slots + are used below, or SZREG if an odd number are used. */ +# define STK_PAD SZREG + +/* Place values that we are more likely to use later in this sequence, i.e. + closer to the SP at function entry. If you do that, the are more + likely to already be in your d-cache. */ +# define STKOFF_A5 (STK_PAD) +# define STKOFF_A4 (STKOFF_A5 + SZREG) +# define STKOFF_A3 (STKOFF_A4 + SZREG) +# define STKOFF_A2 (STKOFF_A3 + SZREG) /* MT and more args. */ +# define STKOFF_A1 (STKOFF_A2 + SZREG) /* MT and 2 args. */ +# define STKOFF_A0 (STKOFF_A1 + SZREG) /* MT and 1 arg. */ +# define STKOFF_RA (STKOFF_A0 + SZREG) /* Used if MT. */ +# define STKOFF_SC_V0 (STKOFF_RA + SZREG) /* Used if MT. */ +# define STKOFF_SC_ERR (STKOFF_SC_V0 + SZREG) /* Used if MT. */ +# define STKOFF_SVMSK (STKOFF_SC_ERR + SZREG) /* Used if MT. */ +# define STKOFF_GP (STKOFF_SVMSK + SZREG) /* Always used. */ + +# define STKSPACE (STKOFF_GP + SZREG) +# define SAVESTK PTR_SUBU sp, STKSPACE +# define RESTORESTK PTR_ADDU sp, STKSPACE + +# ifdef IS_IN_libpthread +# define CENABLE PTR_LA t9, __pthread_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __pthread_disable_asynccancel; jalr t9; +# define __local_multiple_threads __pthread_multiple_threads +# elif defined IS_IN_librt +# define CENABLE PTR_LA t9, __librt_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __librt_disable_asynccancel; jalr t9; +# define __local_multiple_threads __librt_multiple_threads +# else +# define CENABLE PTR_LA t9, __libc_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __libc_disable_asynccancel; jalr t9; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads +#endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h new file mode 100644 index 0000000000..1fff782397 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,143 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Guido Guenther <agx@sigxcpu.org>, 2003. + + 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. */ + +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: la t9,__syscall_error; \ + jr t9; \ + ENTRY (name) \ + .set noreorder; \ + .cpload t9; \ + .set reorder; \ + SINGLE_THREAD_P(t0); \ + bne zero, t0, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + SAVESTK_##args; \ + sw ra, 28(sp); \ + sw gp, 32(sp); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + lw gp, 32(sp); \ + sw v0, 44(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + sw v0, 36(sp); /* save syscall result */ \ + sw a3, 40(sp); /* save syscall error flag */ \ + lw a0, 44(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + lw gp, 32(sp); \ + lw v0, 36(sp); /* restore syscall result */ \ + lw a3, 40(sp); /* restore syscall error flag */ \ + lw ra, 28(sp); /* restore return address */ \ + RESTORESTK; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + L(pseudo_end): +#endif + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 sw a0, 0(sp); +# define PUSHARGS_2 PUSHARGS_1 sw a1, 4(sp); +# define PUSHARGS_3 PUSHARGS_2 sw a2, 8(sp); +# define PUSHARGS_4 PUSHARGS_3 sw a3, 12(sp); +# define PUSHARGS_5 PUSHARGS_4 /* handeld by SAVESTK_## */ +# define PUSHARGS_6 PUSHARGS_5 +# define PUSHARGS_7 PUSHARGS_6 + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 lw a0, 0(sp); +# define POPARGS_2 POPARGS_1 lw a1, 4(sp); +# define POPARGS_3 POPARGS_2 lw a2, 8(sp); +# define POPARGS_4 POPARGS_3 lw a3, 12(sp); +# define POPARGS_5 POPARGS_4 /* args already in new stackframe */ +# define POPARGS_6 POPARGS_5 +# define POPARGS_7 POPARGS_6 + + +# define STKSPACE 48 +# define SAVESTK_0 subu sp, STKSPACE +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 SAVESTK_2 +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 lw t0, 16(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp) + +# define SAVESTK_6 lw t0, 16(sp); \ + lw t1, 20(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp); \ + sw t1, 20(sp) + +# define SAVESTK_7 lw t0, 16(sp); \ + lw t1, 20(sp); \ + lw t2, 24(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp); \ + sw t1, 20(sp); \ + sw t2, 24(sp) + +# define RESTORESTK addu sp, STKSPACE + + +# ifdef IS_IN_libpthread +# define CENABLE la t9, __pthread_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __pthread_disable_asynccancel; jalr t9; +# define __local_multiple_threads __pthread_multiple_threads +# elif defined IS_IN_librt +# define CENABLE la t9, __librt_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __librt_disable_asynccancel; jalr t9; +# define __local_multiple_threads __librt_multiple_threads +# else +# define CENABLE la t9, __libc_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __libc_disable_asynccancel; jalr t9; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads +#endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c b/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c new file mode 100644 index 0000000000..e9c2b6e79a --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,287 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by Ulrich Drepper <drepper@redhat.com>, 2004. + + 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. */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <unistd.h> +#include <sys/socket.h> +#include <not-cancel.h> + + +#ifdef __NR_mq_notify + +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ +#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ +#define NOTIFY_REMOVED 2 /* Code for closed message queue + of de-notifcation. */ + + +/* Data structure for the queued notification requests. */ +union notify_data +{ + struct + { + void (*fct) (union sigval); /* The function to run. */ + union sigval param; /* The parameter to pass. */ + pthread_attr_t *attr; /* Attributes to create the thread with. */ + /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means + byte 31 can still be used for returning the status. */ + }; + char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization. */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket. */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not + resused by the parent. */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask. We move this into a separate function so + that the stack space needed for sigset_t is not deducted from what + the thread can use. */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ + sigset_t ss; + sigfillset (&ss); + return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification. */ +static void * +notification_function (void *arg) +{ + /* Copy the function and parameter so that the parent thread can go + on with its life. */ + volatile union notify_data *data = (volatile union notify_data *) arg; + void (*fct) (union sigval) = data->fct; + union sigval param = data->param; + + /* Let the parent go. */ + (void) pthread_barrier_wait (¬ify_barrier); + + /* Make the thread detached. */ + (void) pthread_detach (pthread_self ()); + + /* The parent thread has all signals blocked. This is probably a + bit surprising for this thread. So we unblock all of them. */ + (void) change_sigmask (SIG_UNBLOCK, NULL); + + /* Now run the user code. */ + fct (param); + + /* And we are done. */ + return NULL; +} + + +/* Helper thread. */ +static void * +helper_thread (void *arg) +{ + while (1) + { + union notify_data data; + + ssize_t n = recv (netlink_socket, &data, sizeof (data), + MSG_NOSIGNAL | MSG_WAITALL); + if (n < NOTIFY_COOKIE_LEN) + continue; + + if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) + { + /* Just create the thread as instructed. There is no way to + report a problem with creating a thread. */ + pthread_t th; + if (__builtin_expect (pthread_create (&th, data.attr, + notification_function, &data) + == 0, 0)) + /* Since we passed a pointer to DATA to the new thread we have + to wait until it is done with it. */ + (void) pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) + /* The only state we keep is the copy of the thread attributes. */ + free (data.attr); + } + return NULL; +} + + +static void +reset_once (void) +{ + once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ + /* This code might be called a second time after fork(). The file + descriptor is inherited from the parent. */ + if (netlink_socket == -1) + { + /* Just a normal netlink socket, not bound. */ + netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0); + /* No need to do more if we have no socket. */ + if (netlink_socket == -1) + return; + + /* Make sure the descriptor is closed on exec. */ + if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0) + goto errout; + } + + int err = 1; + + /* Initialize the barrier. */ + if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, + 0)) + { + /* Create the helper thread. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* We do not need much stack space, the bare minimum will be enough. */ + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Temporarily block all signals so that the newly created + thread inherits the mask. */ + sigset_t oss; + int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + + pthread_t th; + err = pthread_create (&th, &attr, helper_thread, NULL); + + /* Reset the signal mask. */ + if (!have_no_oss) + pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + + if (err == 0) + { + static int added_atfork; + + if (added_atfork == 0 + && pthread_atfork (NULL, NULL, reset_once) != 0) + { + /* The child thread will call recv() which is a + cancellation point. */ + (void) pthread_cancel (th); + err = 1; + } + else + added_atfork = 1; + } + } + + if (err != 0) + { + errout: + close_not_cancel_no_status (netlink_socket); + netlink_socket = -1; + } +} + + +/* Register notification upon message arrival to an empty message queue + MQDES. */ +int +mq_notify (mqd_t mqdes, const struct sigevent *notification) +{ + /* Make sure the type is correctly defined. */ + assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + + /* Special treatment needed for SIGEV_THREAD. */ + if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) + return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* The kernel cannot directly start threads. This will have to be + done at userlevel. Since we cannot start threads from signal + handlers we have to create a dedicated thread which waits for + notifications for arriving messages and creates threads in + response. */ + + /* Initialize only once. */ + pthread_once (&once, init_mq_netlink); + + /* If we cannot create the netlink socket we cannot provide + SIGEV_THREAD support. */ + if (__builtin_expect (netlink_socket == -1, 0)) + { + __set_errno (ENOSYS); + return -1; + } + + /* Create the cookie. It will hold almost all the state. */ + union notify_data data; + memset (&data, '\0', sizeof (data)); + data.fct = notification->sigev_notify_function; + data.param = notification->sigev_value; + + if (notification->sigev_notify_attributes != NULL) + { + /* The thread attribute has to be allocated separately. */ + data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); + if (data.attr == NULL) + return -1; + + memcpy (data.attr, notification->sigev_notify_attributes, + sizeof (pthread_attr_t)); + } + + /* Construct the new request. */ + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_signo = netlink_socket; + se.sigev_value.sival_ptr = &data; + + /* Tell the kernel. */ + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ + if (__builtin_expect (retval != 0, 0)) + free (data.attr); + + return retval; +} + +#else +# include <sysdeps/generic/mq_notify.c> +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile new file mode 100644 index 0000000000..e98c9bd866 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine +libpthread-routines += sysdep diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions new file mode 100644 index 0000000000..326307c30c --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_2.3.4 { + longjmp; siglongjmp; + } +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h new file mode 100644 index 0000000000..0ee10c1c3a --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,131 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stwu 1,-48(1); \ + mflr 9; \ + stw 9,52(1); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + stw 3,16(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + stw 3,8(1); \ + stw 0,12(1); \ + lwz 3,16(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + lwz 4,52(1); \ + lwz 0,12(1); /* restore CR/R3. */ \ + lwz 3,8(1); \ + mtlr 4; \ + mtcr 0; \ + addi 1,1,48; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 stw 3,20(1); DOCARGS_0 +# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0 + +# define DOCARGS_2 stw 4,24(1); DOCARGS_1 +# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1 + +# define DOCARGS_3 stw 5,28(1); DOCARGS_2 +# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2 + +# define DOCARGS_4 stw 6,32(1); DOCARGS_3 +# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3 + +# define DOCARGS_5 stw 7,36(1); DOCARGS_4 +# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4 + +# define DOCARGS_6 stw 8,40(1); DOCARGS_5 +# define UNDOCARGS_6 lwz 8,40(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# elif !defined NOT_IN_libc +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# endif + +# ifdef HAVE_TLS_SUPPORT +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(2); \ + cmpwi 10,0 +# endif +# else +# if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined PIC +# define SINGLE_THREAD_P \ + lis 10,__local_multiple_threads@ha; \ + lwz 10,__local_multiple_threads@l(10); \ + cmpwi 10,0 +# else +# define SINGLE_THREAD_P \ + mflr 9; \ + bl _GLOBAL_OFFSET_TABLE_@local-4; \ + mflr 10; \ + mtlr 9; \ + lwz 10,__local_multiple_threads@got(10); \ + lwz 10,0(10); \ + cmpwi 10,0 +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S new file mode 100644 index 0000000000..ee6254a950 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S @@ -0,0 +1,78 @@ +/* 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 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <kernel-features.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork +# ifdef SHARED + mflr 9 + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr 10 + mtlr 9 + lwz 10,__libc_pthread_functions@got(10) + lwz 10,0(10) +# else + .weak pthread_create + lis 10,pthread_create@ha + la 10,pthread_create@l(10) +# endif + + cmpwi 10,0 + bne- .Lhidden_fork + + DO_CALL (SYS_ify (vfork)); + +# ifdef __ASSUME_VFORK_SYSCALL + PSEUDO_RET +# else + bnslr+ + /* Check if vfork syscall is known at all. */ + cmpwi r3,ENOSYS + bne- .Lsyscall_error + +# endif + +.Lhidden_fork: + b HIDDEN_JUMPTARGET(__fork) + +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + DO_CALL (SYS_ify (fork)); + bnslr+ + +.Lsyscall_error: + b JUMPTARGET(__syscall_error) +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 0000000000..0c74676766 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,127 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stdu 1,-128(1); \ + mflr 9; \ + std 9,128+16(1); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + std 3,72(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + std 3,64(1); \ + std 0,8(1); \ + ld 3,72(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + ld 9,128+16(1); \ + ld 0,8(1); /* restore CR/R3. */ \ + ld 3,64(1); \ + mtlr 9; \ + mtcr 0; \ + addi 1,1,128; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2 std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3 std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4 std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5 std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6 std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel); nop +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifdef HAVE_TLS_SUPPORT +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(13); \ + cmpwi 10,0 +# endif +# else /* !HAVE_TLS_SUPPORT */ +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + .section ".toc","aw"; \ +.LC__local_multiple_threads:; \ + .tc __local_multiple_threads[TC],__local_multiple_threads; \ + .previous; \ + ld 10,.LC__local_multiple_threads@toc(2); \ + lwz 10,0(10); \ + cmpwi 10,0 +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S new file mode 100644 index 0000000000..b408e31b7b --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -0,0 +1,91 @@ +/* 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 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <kernel-features.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +#ifdef SHARED + .section ".toc","aw" +.LC0: + .tc __libc_pthread_functions[TC],__libc_pthread_functions + .section ".text" + .align 2 +#endif + +ENTRY (__vfork) + +#ifdef __NR_vfork + +# ifdef SHARED + ld 10,.LC0@toc(2) + ld 10,0(10) + cmpwi 10,0 + bne- HIDDEN_JUMPTARGET(__fork) +# else + .weak pthread_create + lis 10,pthread_create@highest + ori 10,10,pthread_create@higher + sldi 10,10,32 + oris 10,10,pthread_create@h + ori 10,10,pthread_create@l + cmpwi 10,0 + bne- .Lhidden_fork +# endif + + DO_CALL (SYS_ify (vfork)); + +# ifdef __ASSUME_VFORK_SYSCALL + PSEUDO_RET +# else + bnslr+ + /* Check if vfork syscall is known at all. */ + cmpdi r3,ENOSYS +# ifdef SHARED + bne JUMPTARGET(__syscall_error) +# else + bne- .Lsyscall_error +# endif + +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + DO_CALL (SYS_ify (fork)); + PSEUDO_RET +#endif + +# ifndef SHARED +.Lhidden_fork: + b HIDDEN_JUMPTARGET(__fork) +.Lsyscall_error: + b JUMPTARGET(__syscall_error) +# endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c new file mode 100644 index 0000000000..177256c7fb --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c @@ -0,0 +1,70 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ +/* Derived from linuxthreads/ptlongjmp.c & added AltiVec/VMX versioning. */ +#include "pthread.h" +#include <setjmp.h> +#include <bits/wordsize.h> +#include <shlib-compat.h> +#if defined SHARED +# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __novmx__libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __novmx__libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + + +void __novmx_siglongjmp (sigjmp_buf env, int val) +{ + __novmx__libc_siglongjmp (env, val); +} + +void __novmx_longjmp (jmp_buf env, int val) +{ + __novmx__libc_longjmp (env, val); +} + +# if __WORDSIZE == 64 +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3); +# else +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0); +# endif +# endif /* SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) ) */ + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __vmx__libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __vmx__libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + +void __vmx_siglongjmp (sigjmp_buf env, int val) +{ + __vmx__libc_siglongjmp (env, val); +} + +void __vmx_longjmp (jmp_buf env, int val) +{ + __vmx__libc_longjmp (env, val); +} +default_symbol_version (__vmx_longjmp,longjmp,GLIBC_2.3.4); +default_symbol_version (__vmx_siglongjmp,siglongjmp,GLIBC_2.3.4); +#endif /* SHARED */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c new file mode 100644 index 0000000000..5528c55ca5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c @@ -0,0 +1,56 @@ +/* Internal sigsuspend system call for LinuxThreads. Generic Linux 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 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. */ + +#include <errno.h> +#include <signal.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <linuxthreads/internals.h> + +#include "kernel-features.h" + +void +__pthread_sigsuspend (const sigset_t *set) +{ + INTERNAL_SYSCALL_DECL (err); +#if !__ASSUME_REALTIME_SIGNALS + static int __pthread_missing_rt_sigs; + +# ifdef __NR_rt_sigsuspend + /* First try the RT signals. */ + if (!__pthread_missing_rt_sigs) + { + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int r; + r = INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8); + if (INTERNAL_SYSCALL_ERRNO (r, err) != ENOSYS) + return; + + __pthread_missing_rt_sigs = 1; + } +# endif + + INTERNAL_SYSCALL (sigsuspend, err, 3, 0, 0, set->__val[0]); +#else + INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8); +#endif +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/raise.c b/linuxthreads/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 0000000000..9dad2b2697 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1996, 2002, 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 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. */ + +#include <signal.h> +#include <unistd.h> +#include <bits/libc-lock.h> + +#ifndef SHARED +weak_extern (__pthread_raise) +#endif + +/* Raise the signal SIG. */ +int +raise (sig) + int sig; +{ + return __libc_maybe_call2 (pthread_raise, (sig), + __kill (__getpid (), sig)); +} +libc_hidden_def (raise) +weak_alias (raise, gsignal) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c b/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c new file mode 100644 index 0000000000..e4490e73e9 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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. */ + +#include <errno.h> +#include <stdlib.h> +#include "fork.h" + + +int +__register_atfork (prepare, parent, child, dso_handle) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); + void *dso_handle; +{ + struct fork_handler *new_prepare = NULL; + struct fork_handler *new_parent = NULL; + struct fork_handler *new_child = NULL; + + if (prepare != NULL) + { + new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare)); + if (new_prepare == NULL) + goto out1; + + new_prepare->handler = prepare; + new_prepare->dso_handle = dso_handle; + } + + if (parent != NULL) + { + new_parent = (struct fork_handler *) malloc (sizeof (*new_parent)); + if (new_parent == NULL) + goto out2; + + new_parent->handler = parent; + new_parent->dso_handle = dso_handle; + } + + if (child != NULL) + { + new_child = (struct fork_handler *) malloc (sizeof (*new_child)); + if (new_child == NULL) + { + free (new_parent); + out2: + free (new_prepare); + out1: + return errno; + } + + new_child->handler = child; + new_child->dso_handle = dso_handle; + } + + /* Get the lock to not conflict with running forks. */ + __libc_lock_lock (__fork_block.lock); + + /* Now that we have all the handlers allocate enqueue them. */ + if (new_prepare != NULL) + list_add_tail (&new_prepare->list, &__fork_block.prepare_list); + if (new_parent != NULL) + list_add_tail (&new_parent->list, &__fork_block.parent_list); + if (new_child != NULL) + list_add_tail (&new_child->list, &__fork_block.child_list); + + /* Release the lock. */ + __libc_lock_unlock (__fork_block.lock); + + return 0; +} +libc_hidden_def (__register_atfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h new file mode 100644 index 0000000000..bee7639f06 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h @@ -0,0 +1,72 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/s390 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 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_TYPES_H +# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See <bits/types.h> for the meaning of these macros. This file exists so + that <bits/types.h> need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#if defined __GNUC__ && __GNUC__ <= 2 +/* Compatibility with g++ 2.95.x. */ +#define __SSIZE_T_TYPE __SWORD_TYPE +#else +/* size_t is unsigned long int on s390 -m31. */ +#define __SSIZE_T_TYPE __SLONGWORD_TYPE +#endif + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c new file mode 100644 index 0000000000..b7d901c4c6 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c @@ -0,0 +1,154 @@ +/* Special .init and .fini section support for S/390. + Copyright (C) 2000, 2001 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 36\n\ + STM 6,15,24(15)\n\ + BRAS 13,.LTN1_0\n\ +.LT1_0:\n\ +.LC13:\n\ + .long __pthread_initialize_minimal@PLT-.LT1_0\n\ +.LC14:\n\ + .long __gmon_start__@GOT\n\ +.LC15:\n\ + .long _GLOBAL_OFFSET_TABLE_-.LT1_0\n\ +.LTN1_0:\n\ + LR 1,15\n\ + AHI 15,-96\n\ + ST 1,0(15)\n\ + L 12,.LC15-.LT1_0(13)\n\ + AR 12,13\n\ + L 1,.LC13-.LT1_0(13)\n\ + LA 1,0(1,13)\n\ + BASR 14,1\n\ + L 1,.LC14-.LT1_0(13)\n\ + L 1,0(1,12)\n\ + LTR 1,1\n\ + JE .L22\n\ + BASR 14,1\n\ +.L22:\n\ +#APP\n\ + .align 4,0x07\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ + L 4,152(15)\n\ + LM 6,15,120(15)\n\ + BR 4\n\ +#APP\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 30\n\ + STM 6,15,24(15)\n\ + BRAS 13,.LTN2_0\n\ +.LT2_0:\n\ +.LC17:\n\ + .long _GLOBAL_OFFSET_TABLE_-.LT2_0\n\ +.LTN2_0:\n\ + LR 1,15\n\ + AHI 15,-96\n\ + ST 1,0(15)\n\ + L 12,.LC17-.LT2_0(13)\n\ + AR 12,13\n\ +#APP\n\ + .align 4,0x07\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ + L 4,152(15)\n\ + LM 6,15,120(15)\n\ + BR 4\n\ +#APP\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\ +"); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h new file mode 100644 index 0000000000..06f7aed7dc --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# if !defined NOT_IN_libc || defined IS_IN_libpthread + +# define PSEUDO_CANCEL(name, syscall_name, args) \ +L(pseudo_cancel): \ + STM_##args \ + stm %r12,%r15,48(%r15); \ + lr %r14,%r15; \ + ahi %r15,-96; \ + st %r14,0(%r15); \ + basr %r13,0; \ +0: l %r1,1f-0b(%r13); \ + bas %r14,0(%r1,%r13); \ + lr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + l %r1,2f-0b(%r13); \ + lr %r12,%r2; \ + lr %r2,%r0; \ + bas %r14,0(%r1,%r13); \ + lr %r2,%r12; \ + lm %r12,%r15,48+96(%r15); \ + j L(pseudo_check); \ +1: .long CENABLE-0b; \ +2: .long CDISABLE-0b; + +# else /* !libc.so && !libpthread.so */ + +# define PSEUDO_CANCEL(name, syscall_name, args) \ +L(pseudo_cancel): \ + STM_##args \ + stm %r11,%r15,44(%r15); \ + lr %r14,%r15; \ + ahi %r15,-96; \ + st %r14,0(%r15); \ + basr %r13,0; \ +0: l %r12,3f-0b(%r13); \ + l %r1,1f-0b(%r13); \ + la %r12,0(%r12,%r13); \ + bas %r14,0(%r1,%r13); \ + lr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + l %r1,2f-0b(%r13); \ + lr %r11,%r2; \ + lr %r2,%r0; \ + bas %r14,0(%r1,%r13); \ + lr %r2,%r11; \ + lm %r11,%r15,44+96(%r15); \ + j L(pseudo_check); \ +1: .long CENABLE@PLT-0b; \ +2: .long CDISABLE@PLT-0b; \ +3: .long _GLOBAL_OFFSET_TABLE_-0b; + +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +PSEUDO_CANCEL(name, syscall_name, args) \ +ENTRY(name) \ + SINGLE_THREAD_P(%r1) \ + jne L(pseudo_cancel); \ + DO_CALL(syscall_name, args); \ +L(pseudo_check): \ + lhi %r4,-4095; \ + clr %r2,%r4; \ + jnl SYSCALL_ERROR_LABEL; \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +# define CENABLE __pthread_enable_asynccancel +# define CDISABLE __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE __libc_enable_asynccancel +# define CDISABLE __libc_disable_asynccancel +# else +# define CENABLE __librt_enable_asynccancel +# define CDISABLE __librt_disable_asynccancel +# endif + +#define STM_0 /* Nothing */ +#define STM_1 st %r2,8(%r15); +#define STM_2 stm %r2,%r3,8(%r15); +#define STM_3 stm %r2,%r4,8(%r15); +#define STM_4 stm %r2,%r5,8(%r15); +#define STM_5 stm %r2,%r5,8(%r15); + +#define LM_0 /* Nothing */ +#define LM_1 l %r2,8+96(%r15); +#define LM_2 lm %r2,%r3,8+96(%r15); +#define LM_3 lm %r2,%r4,8+96(%r15); +#define LM_4 lm %r2,%r5,8+96(%r15); +#define LM_5 lm %r2,%r5,8+96(%r15); + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + ear reg,%a0; \ + icm reg,15,MULTIPLE_THREADS_OFFSET(reg); +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S new file mode 100644 index 0000000000..6dfeca86d4 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S @@ -0,0 +1,69 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com> + + 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + basr %r1,0 +0: +#ifdef SHARED + al %r1,4f-0b(%r1) + l %r1,0(%r1) + ltr %r1,%r1 +#else + icm %r1,15,4f-0b(%r1) +#endif + jne 1f + + /* Do vfork system call. */ + svc SYS_ify (vfork) + + /* Check for error. */ + lhi %r4,-4095 + clr %r2,%r4 + jnl SYSCALL_ERROR_LABEL + + /* Normal return. */ + br %r14 +1: + basr %r1,0 +2: + al %r1,3f-2b(%r1) + br %r1 +3: + .long HIDDEN_JUMPTARGET(__fork)-2b +4: +#ifdef SHARED + .long __libc_pthread_functions-0b +#else + .weak pthread_create + .long pthread_create +#endif +PSEUDO_END(__vfork) + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c new file mode 100644 index 0000000000..540443e6a3 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c @@ -0,0 +1,137 @@ +/* Special .init and .fini section support for 64 bit S/390. + Copyright (C) 2001 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 36\n\ + STMG 6,15,48(15)\n\ + LGR 1,15\n\ + AGHI 15,-160\n\ + STG 1,0(15)\n\ + LARL 12,_GLOBAL_OFFSET_TABLE_\n\ + BRASL 14,__pthread_initialize_minimal@PLT\n\ + LARL 1,__gmon_start__@GOTENT\n\ + LG 1,0(1)\n\ + LTGR 1,1\n\ + JE .L22\n\ + BASR 14,1\n\ +.L22:\n\ +#APP\n\ + .align 4,0x07\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ + LG 4,272(15)\n\ + LMG 6,15,208(15)\n\ + BR 4\n\ +#APP\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 30\n\ + STMG 6,15,48(15)\n\ + LGR 1,15\n\ + AGHI 15,-160\n\ + STG 1,0(15)\n\ + LARL 12,_GLOBAL_OFFSET_TABLE_\n\ +#APP\n\ + .align 4,0x07\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ + LG 4,272(15)\n\ + LMG 6,15,208(15)\n\ + BR 4\n\ +#APP\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + "); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c new file mode 100644 index 0000000000..d57283ad23 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h new file mode 100644 index 0000000000..f71ef3f689 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +L(pseudo_cancel): \ + STM_##args \ + stmg %r13,%r15,104(%r15); \ + lgr %r14,%r15; \ + aghi %r15,-160; \ + stg %r14,0(%r15); \ + brasl %r14,CENABLE; \ + lgr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + lgr %r13,%r2; \ + lgr %r2,%r0; \ + brasl %r14,CDISABLE; \ + lgr %r2,%r13; \ + lmg %r13,%r15,104+160(%r15); \ + j L(pseudo_check); \ +ENTRY(name) \ + SINGLE_THREAD_P \ + jne L(pseudo_cancel); \ + DO_CALL(syscall_name, args); \ +L(pseudo_check): \ + lghi %r4,-4095; \ + clgr %r2,%r4; \ + jgnl SYSCALL_ERROR_LABEL; \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +# define CENABLE __pthread_enable_asynccancel +# define CDISABLE __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE __libc_enable_asynccancel +# define CDISABLE __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE __librt_enable_asynccancel@PLT +# define CDISABLE __librt_disable_asynccancel@PLT +# endif + +#define STM_0 /* Nothing */ +#define STM_1 stg %r2,16(%r15); +#define STM_2 stmg %r2,%r3,16(%r15); +#define STM_3 stmg %r2,%r4,16(%r15); +#define STM_4 stmg %r2,%r5,16(%r15); +#define STM_5 stmg %r2,%r5,16(%r15); + +#define LM_0 /* Nothing */ +#define LM_1 lg %r2,16+160(%r15); +#define LM_2 lmg %r2,%r3,16+160(%r15); +#define LM_3 lmg %r2,%r4,16+160(%r15); +#define LM_4 lmg %r2,%r5,16+160(%r15); +#define LM_5 lmg %r2,%r5,16+160(%r15); + +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + larl %r1,__local_multiple_threads; \ + icm %r0,15,0(%r1); +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + ear %r1,%a0; \ + sllg %r1,%r1,32; \ + ear %r1,%a1; \ + icm %r1,15,MULTIPLE_THREADS_OFFSET(%r1); +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S new file mode 100644 index 0000000000..199f0017ff --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com> + + 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) +#ifdef SHARED + larl %r1,__libc_pthread_functions + lg %r1,0(%r1) +#else + .weak pthread_create + larl %r1,pthread_create +#endif + ltgr %r1,%r1 + jgne HIDDEN_JUMPTARGET(__fork) + + /* Do vfork system call. */ + svc SYS_ify (vfork) + + /* Check for error. */ + lghi %r4,-4095 + clgr %r2,%r4 + jgnl SYSCALL_ERROR_LABEL + + /* Normal return. */ + br %r14 +PSEUDO_END(__vfork) + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 0000000000..1cdb98f0f7 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,143 @@ +/* Special .init and .fini section support for SH. Linuxthread version. + Copyright (C) 2000, 2001, 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 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .section .init\n\ + .align 5\n\ + .global _init\n\ + .type _init,@function\n\ +_init:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L22,r0\n\ + mov.l .L22,r12\n\ + add r0,r12\n\ + mova .L24,r0\n\ + mov.l .L24,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + nop\n\ + mova .L23,r0\n\ + mov.l .L23,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + mov r15,r14\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L22:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +.L23:\n\ + .long __gmon_start__@PLT\n\ +.L24:\n\ + .long __pthread_initialize_minimal@PLT\n\ +1:\n\ + ALIGN\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ + END_INIT\n\ + .section .text\n\ + .align 5\n\ + .weak __gmon_start__\n\ + .type __gmon_start__,@function\n\ +__gmon_start__:\n\ + mov.l r14,@-r15\n\ + mov r15,r14\n\ + mov r14,r15\n\ + rts \n\ + mov.l @r15+,r14\n\ + \n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 5\n\ + .global _fini\n\ + .type _fini,@function\n\ +_fini:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L27,r0\n\ + mov.l .L27,r12\n\ + add r0,r12\n\ + mov r15,r14\n\ + ALIGN\n\ + END_FINI\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L27:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ +\n\ + END_FINI\n\ + \n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h b/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 0000000000..2c0cbe99ac --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors. SH 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. */ + +static inline int +is_smp_system (void) +{ + return 0; +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 0000000000..03c6fedbfe --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,227 @@ +/* Copyright (C) 2003, 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 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. */ + +#include <sysdep.h> +#include <tls.h> +#include <pt-machine.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + bf .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bt .Lsyscall_error; \ + bra .Lpseudo_end; \ + nop; \ + .Lpseudo_cancel: \ + sts.l pr,@-r15; \ + add _IMM16,r15; \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + add _IMP16,r15; \ + lds.l @r15+,pr; \ + DO_CALL(syscall_name, args); \ + SYSCALL_INST_PAD; \ + sts.l pr,@-r15; \ + mov.l r0,@-r15; \ + CDISABLE; \ + mov.l @r15+,r0; \ + lds.l @r15+,pr; \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bf .Lpseudo_end; \ + .Lsyscall_error: \ + SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + END (sym) + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; mov.l r4,@(0,r15) +# define SAVE_ARGS_2 SAVE_ARGS_1; mov.l r5,@(4,r15) +# define SAVE_ARGS_3 SAVE_ARGS_2; mov.l r6,@(8,r15) +# define SAVE_ARGS_4 SAVE_ARGS_3; mov.l r7,@(12,r15) +# define SAVE_ARGS_5 SAVE_ARGS_4 +# define SAVE_ARGS_6 SAVE_ARGS_5 + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2 LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3 LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4 LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5 LOAD_ARGS_4 +# define LOAD_ARGS_6 LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# define __local_multiple_threads __librt_multiple_threads +# endif + +# if defined IS_IN_librt && defined PIC +# define CENABLE \ + mov.l r12,@-r15; \ + mov.l 1f,r12; \ + mova 1f,r0; \ + add r0,r12; \ + mov.l 2f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 3f; \ + mov r0,r2; \ + .align 2; \ + 1: .long _GLOBAL_OFFSET_TABLE_; \ + 2: .long __local_enable_asynccancel@PLT - (0b-.); \ + 3: mov.l @r15+,r12 + +# define CDISABLE \ + mov.l r12,@-r15; \ + mov.l 1f,r12; \ + mova 1f,r0; \ + add r0,r12; \ + mov.l 2f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 3f; \ + nop; \ + .align 2; \ + 1: .long _GLOBAL_OFFSET_TABLE_; \ + 2: .long __local_disable_asynccancel@PLT - (0b-.); \ + 3: mov.l @r15+,r12 +# else +# define CENABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 2f; \ + mov r0,r2; \ + .align 2; \ + 1: .long __local_enable_asynccancel - 0b; \ + 2: + +# define CDISABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 2f; \ + nop; \ + .align 2; \ + 1: .long __local_disable_asynccancel - 0b; \ + 2: +# endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined PIC +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined PIC +# define SINGLE_THREAD_P \ + mov.l 1f,r0; \ + mov.l @r0,r0; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 1: .long __local_multiple_threads; \ + 2: +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P \ + stc gbr,r0; \ + mov.w 0f,r1; \ + sub r1,r0; \ + mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ + bra 1f; \ + tst r0,r0; \ + 0: .word TLS_PRE_TCB_SIZE; \ + 1: + +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define SINGLE_THREAD_P \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov r2,r12; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long __local_multiple_threads@GOTOFF; \ + 2: +# else +# define SINGLE_THREAD_P \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov.l @r0,r0; \ + mov r2,r12; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long __local_multiple_threads@GOT; \ + 2: +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 0000000000..f230c01226 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,77 @@ +/* Copyright (C) 2003, 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 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) +#ifdef SHARED + mov.l .Lgot, r1 + mova .Lgot, r0 + add r0, r1 + mov.l .Lpthread_func, r0 + mov.l @(r0,r1), r0 +#else + mov.l .Lpthread_create, r0 +#endif + tst r0, r0 + bf .Lhidden_fork + + mov.w .L1, r3 + trapa #0x10 + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: .word __NR_vfork + .align 2 +#ifdef SHARED +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lpthread_func: + .long __libc_pthread_functions@GOTOFF +#else +.Lpthread_create: + .weak pthread_create + .long pthread_create +#endif + +.Lhidden_fork: + mov.l .L2, r1 + braf r1 + nop +1: + .align 2 +.L2: .long HIDDEN_JUMPTARGET(__fork)-1b + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 0000000000..fdec09455a --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997, 1998, 2000, 2002, 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 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. */ + +#include <errno.h> +#include <signal.h> +#define __need_NULL +#include <stddef.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> +#include <bits/libc-lock.h> + +extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__unbounded, + const struct timespec *__unbounded, size_t); + + +/* Return any pending signal or wait for one for the given time. */ +static inline int +do_sigwait (const sigset_t *set, int *sig) +{ + int ret; + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL_DECL (err); + ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, CHECK_SIGSET (set), + NULL, NULL, _NSIG / 8); + if (! INTERNAL_SYSCALL_ERROR_P (ret, err)) + { + *sig = ret; + ret = 0; + } + else + ret = INTERNAL_SYSCALL_ERRNO (ret, err); +#else + ret = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + NULL, NULL, _NSIG / 8); + if (ret != -1) + { + *sig = ret; + ret = 0; + } + else + ret = errno; +#endif + + return ret; +} + +#ifndef SHARED +weak_extern (__pthread_sigwait) +#endif + +int +__sigwait (set, sig) + const sigset_t *set; + int *sig; +{ +#ifndef NOT_IN_libc + return __libc_maybe_call2 (pthread_sigwait, (set, sig), + do_sigwait (set, sig)); +#else + return do_sigwait (set, sig); +#endif +} +libc_hidden_def (__sigwait) +weak_alias (__sigwait, sigwait) +strong_alias (__sigwait, __libc_sigwait) + +/* Cancellation is handled in __pthread_sigwait. */ +LIBC_CANCEL_HANDLED (); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/smp.h b/linuxthreads/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 0000000000..81289294b4 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,48 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 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 <sys/sysctl.h> + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + static const int sysctl_args[] = { CTL_KERN, KERN_VERSION }; + char buf[512]; + size_t reslen = sizeof (buf); + + /* Try reading the number using `sysctl' first. */ + if (__sysctl ((int *) sysctl_args, + sizeof (sysctl_args) / sizeof (sysctl_args[0]), + buf, &reslen, NULL, 0) < 0) + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = __open ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || (reslen = __read (fd, buf, sizeof (buf))) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + buf[0] = '\0'; + + __close (fd); + } + + return strstr (buf, "SMP") != NULL; +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions b/linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions new file mode 100644 index 0000000000..d102772482 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/Versions @@ -0,0 +1,6 @@ +libpthread { + GLIBC_2.3.3 { + # Changed PTHREAD_STACK_MIN. + pthread_attr_setstack; pthread_attr_setstacksize; + } +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c b/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c new file mode 100644 index 0000000000..0d6da82919 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c @@ -0,0 +1,33 @@ +#include <shlib-compat.h> + +#define aio_cancel64 XXX +#include <aio.h> +#undef aio_cancel64 +#include <errno.h> + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include <sysdeps/pthread/aio_cancel.c> + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h new file mode 100644 index 0000000000..27ffa668f4 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/SPARC version. + Copyright (C) 1993-1998,2000,2002,2003,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 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h new file mode 100644 index 0000000000..7e4253789c --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/SPARC version. + Copyright (C) 2002, 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 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_TYPES_H +# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See <bits/types.h> for the meaning of these macros. This file exists so + that <bits/types.h> need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S32_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h new file mode 100644 index 0000000000..793cb1d5f9 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <sysdep.h> + +#define ARCH_FORK() \ +({ \ + register long __o0 __asm__ ("o0"); \ + register long __o1 __asm__ ("o1"); \ + register long __g1 __asm__ ("g1") = __NR_fork; \ + __asm __volatile (__SYSCALL_STRING \ + : "=r" (__g1), "=r" (__o0), "=r" (__o1) \ + : "0" (__g1) \ + : __SYSCALL_CLOBBERS); \ + __o0 == -1 ? __o0 : (__o0 & (__o1 - 1)); \ +}) + +#include_next <fork.h> diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h new file mode 100644 index 0000000000..dd3f52a989 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \ + cmp %g1, 0; \ + bne 1f; \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcs __syscall_error_handler; \ + nop; \ + .subsection 2; \ +1: save %sp, -96, %sp; \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcs __syscall_error_handler2; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; \ + .previous; \ + SYSCALL_ERROR_HANDLER \ + SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2 \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \ + .global __errno_location; \ + .type __errno_location,@function; \ + CDISABLE; \ + mov %l0, %o0; \ + call __errno_location; \ + nop; \ + st %l1, [%o0]; \ + jmpl %i7 + 8, %g0; \ + restore %g0, -1, %o0; \ + .previous; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# else +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S new file mode 100644 index 0000000000..132da67a14 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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. */ + +#include <sysdep-cancel.h> + + .text +#ifdef SHARED +.LLGETPC0: + retl + add %o7, %o0, %o0 +#endif +ENTRY(__vfork) +#ifdef SHARED + mov %o7, %o1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o0 + call .LLGETPC0 + add %o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0 + sethi %hi(__libc_pthread_functions), %o2 + mov %o1, %o7 + or %o2, %lo(__libc_pthread_functions), %o2 + ld [%o0 + %o2], %o2 + ld [%o2], %o2 + cmp %o2, 0 +#else + .weak pthread_create + sethi %hi(pthread_create), %o0 + orcc %o0, %lo(pthread_create), %o0 +#endif +#if defined SHARED && !defined BROKEN_SPARC_WDISP22 + bne HIDDEN_JUMPTARGET(__fork) +#else + bne 1f +#endif + mov __NR_vfork, %g1 + ta 0x10 + bcs __syscall_error_handler + nop + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 +#if !defined SHARED || defined BROKEN_SPARC_WDISP22 +1: mov %o7, %g1 + call HIDDEN_JUMPTARGET(__fork) + mov %g1, %o7 +#endif + SYSCALL_ERROR_HANDLER +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile new file mode 100644 index 0000000000..90203051ae --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile @@ -0,0 +1,5 @@ +# glibc makefile fragment for linuxthreads on sparc/sparc64. + +ifeq ($(subdir),linuxthreads) +libpthread-routines += ptw-sigprocmask +endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c new file mode 100644 index 0000000000..d57283ad23 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h new file mode 100644 index 0000000000..80834292e5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \ + brnz,pn %g1, 1f; \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcs,pn %xcc, __syscall_error_handler; \ + nop; \ + .subsection 2; \ +1: save %sp, -192, %sp; \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcs,pn %xcc, __syscall_error_handler2; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; \ + .previous; \ + SYSCALL_ERROR_HANDLER \ + SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2 \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \ + .global __errno_location; \ + .type __errno_location,@function; \ + CDISABLE; \ + mov %l0, %o0; \ + call __errno_location; \ + nop; \ + st %l1, [%o0]; \ + jmpl %i7 + 8, %g0; \ + restore %g0, -1, %o0; \ + .previous; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# else +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S new file mode 100644 index 0000000000..8a6d2771e8 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,64 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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. */ + +#include <sysdep-cancel.h> + +#ifdef SHARED +.LLGETPC0: + retl + add %o7, %o0, %o0 +#endif +ENTRY(__vfork) +#ifdef SHARED + mov %o7, %o1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o0 + call .LLGETPC0 + add %o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0 + sethi %hi(__libc_pthread_functions), %o2 + mov %o1, %o7 + or %o2, %lo(__libc_pthread_functions), %o2 + ldx [%o0 + %o2], %o2 + ldx [%o2], %o0 +#else + .weak pthread_create + sethi %hi(pthread_create), %o0 + or %o0, %lo(pthread_create), %o0 +#endif +#if defined SHARED && !defined BROKEN_SPARC_WDISP22 + cmp %o0, 0 + bne HIDDEN_JUMPTARGET(__fork) +#else + brnz,pn %o0, 1f +#endif + mov __NR_vfork, %g1 + ta 0x6d + bcs,pn %xcc, __syscall_error_handler + nop + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 +#if !defined SHARED || defined BROKEN_SPARC_WDISP22 +1: mov %o7, %g1 + call HIDDEN_JUMPTARGET(__fork) + mov %g1, %o7 +#endif + SYSCALL_ERROR_HANDLER +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c b/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c new file mode 100644 index 0000000000..dad273fdf5 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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. */ + +#include <errno.h> +#include <stdlib.h> +#include "fork.h" + + +void +__unregister_atfork (dso_handle) + void *dso_handle; +{ + /* Get the lock to not conflict with running forks. */ + __libc_lock_lock (__fork_block.lock); + + list_t *runp; + list_t *prevp; + + list_for_each_prev_safe (runp, prevp, &__fork_block.prepare_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + list_for_each_prev_safe (runp, prevp, &__fork_block.parent_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + list_for_each_prev_safe (runp, prevp, &__fork_block.child_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + /* Release the lock. */ + __libc_lock_unlock (__fork_block.lock); +} diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile new file mode 100644 index 0000000000..b5e5d5d480 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),linuxthreads) +CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions \ + -fno-asynchronous-unwind-tables $(fno-unit-at-a-time) +endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c new file mode 100644 index 0000000000..3a0c2afc0f --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../ia64/pt-sigsuspend.c" diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 0000000000..742dbeb0de --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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. */ + +#include <sysdep.h> +#include <tls.h> +#include <pt-machine.h> +#ifndef __ASSEMBLER__ +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + /* Save registers that might get destroyed. */ \ + SAVESTK_##args \ + PUSHARGS_##args \ + CENABLE \ + /* Restore registers. */ \ + POPARGS_##args \ + /* The return value from CENABLE is argument for CDISABLE. */ \ + movq %rax, (%rsp); \ + movq $SYS_ify (syscall_name), %rax; \ + syscall; \ + movq (%rsp), %rdi; \ + /* Save %rax since it's the error code from the syscall. */ \ + movq %rax, 8(%rsp); \ + CDISABLE \ + movq 8(%rsp), %rax; \ + RESTSTK_##args \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define PUSHARGS_0 /* Nothing. */ +# define PUSHARGS_1 PUSHARGS_0 movq %rdi, 8(%rsp); +# define PUSHARGS_2 PUSHARGS_1 movq %rsi, 16(%rsp); +# define PUSHARGS_3 PUSHARGS_2 movq %rdx, 24(%rsp); +# define PUSHARGS_4 PUSHARGS_3 movq %rcx, 32(%rsp); +# define PUSHARGS_5 PUSHARGS_4 movq %r8, 40(%rsp); +# define PUSHARGS_6 PUSHARGS_5 movq %r9, 48(%rsp); + +# define POPARGS_0 /* Nothing. */ +# define POPARGS_1 POPARGS_0 movq 8(%rsp), %rdi; +# define POPARGS_2 POPARGS_1 movq 16(%rsp), %rsi; +# define POPARGS_3 POPARGS_2 movq 24(%rsp), %rdx; +# define POPARGS_4 POPARGS_3 movq 32(%rsp), %r10; +# define POPARGS_5 POPARGS_4 movq 40(%rsp), %r8; +# define POPARGS_6 POPARGS_5 movq 48(%rsp), %r9; + +/* We always have to align the stack before calling a function. */ +# define SAVESTK_0 subq $24, %rsp;cfi_adjust_cfa_offset(24); +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 subq $40, %rsp;cfi_adjust_cfa_offset(40); +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 subq $56, %rsp;cfi_adjust_cfa_offset(56); +# define SAVESTK_6 SAVESTK_5 + +# define RESTSTK_0 addq $24,%rsp;cfi_adjust_cfa_offset(-24); +# define RESTSTK_1 RESTSTK_0 +# define RESTSTK_2 RESTSTK_1 +# define RESTSTK_3 addq $40, %rsp;cfi_adjust_cfa_offset(-40); +# define RESTSTK_4 RESTSTK_3 +# define RESTSTK_5 addq $56, %rsp;cfi_adjust_cfa_offset(-56); +# define RESTSTK_6 RESTSTK_5 + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE call __librt_enable_asynccancel@plt; +# define CDISABLE call __librt_disable_asynccancel@plt; +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 0000000000..25d1d3f96a --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,62 @@ +/* Copyright (C) 2001, 2002, 2003, 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 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. */ + +#include <sysdep-cancel.h> +#define _ERRNO_H 1 +#include <bits/errno.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef SHARED + cmpq $0, __libc_pthread_functions(%rip) +#else + .weak pthread_create + movq $pthread_create, %rax + testq %rax, %rax +#endif + jne HIDDEN_JUMPTARGET (__fork) + + /* Pop the return PC value into RDI. We need a register that + is preserved by the syscall and that we're allowed to destroy. */ + popq %rdi + cfi_adjust_cfa_offset(-8) + + /* Stuff the syscall number in RAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + syscall + + /* Push back the return PC. */ + pushq %rdi + cfi_adjust_cfa_offset(8) + + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */ + + /* Normal return. */ +.Lpseudo_end: + ret + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/linuxthreads/sysdeps/x86_64/Makefile b/linuxthreads/sysdeps/x86_64/Makefile new file mode 100644 index 0000000000..81bddf688c --- /dev/null +++ b/linuxthreads/sysdeps/x86_64/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/linuxthreads/sysdeps/x86_64/Versions b/linuxthreads/sysdeps/x86_64/Versions new file mode 100644 index 0000000000..32da57080d --- /dev/null +++ b/linuxthreads/sysdeps/x86_64/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_PRIVATE { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/x86_64/pspinlock.c b/linuxthreads/sysdeps/x86_64/pspinlock.c new file mode 100644 index 0000000000..e1b2a66841 --- /dev/null +++ b/linuxthreads/sysdeps/x86_64/pspinlock.c @@ -0,0 +1,97 @@ +/* POSIX spinlock implementation. x86-64 version. + Copyright (C) 2001 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. */ + +#include <errno.h> +#include <pthread.h> +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + asm volatile + ("\n" + "1:\n\t" + "lock; decl %0\n\t" + "js 2f\n\t" + ".section .text.spinlock,\"ax\"\n" + "2:\n\t" + "cmpl $0,%0\n\t" + "rep; nop\n\t" + "jle 2b\n\t" + "jmp 1b\n\t" + ".previous" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + asm volatile + ("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0)); + return oldval > 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + asm volatile + ("movl $1,%0" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/linuxthreads/sysdeps/x86_64/pt-machine.h b/linuxthreads/sysdeps/x86_64/pt-machine.h new file mode 100644 index 0000000000..df187a7c03 --- /dev/null +++ b/linuxthreads/sysdeps/x86_64/pt-machine.h @@ -0,0 +1,225 @@ +/* Machine-dependent pthreads configuration and inline functions. + x86-64 version. + Copyright (C) 2001, 2002, 2003, 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 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 _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef __ASSEMBLER__ +# include <stddef.h> /* For offsetof. */ +# include <stdlib.h> /* For abort(). */ +# include <asm/prctl.h> + + +# ifndef PT_EI +# define PT_EI extern inline __attribute__ ((always_inline)) +# endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +# define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%rsp") __attribute_used__; + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %k0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. */ +# define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + +/* Prototype for the system call. */ +extern int __arch_prctl (int __code, unsigned long __addr); + +/* Initialize the thread-unique value. */ +# define INIT_THREAD_SELF(descr, nr) \ +{ \ + if (__arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \ + abort (); \ +} + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P2,%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:(%2),%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +#endif /* !__ASSEMBLER__ */ + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* The ia32e really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/x86_64/tcb-offsets.sym b/linuxthreads/sysdeps/x86_64/tcb-offsets.sym new file mode 100644 index 0000000000..aee6be2570 --- /dev/null +++ b/linuxthreads/sysdeps/x86_64/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/linuxthreads/sysdeps/x86_64/tls.h b/linuxthreads/sysdeps/x86_64/tls.h new file mode 100644 index 0000000000..63feebdb2c --- /dev/null +++ b/linuxthreads/sysdeps/x86_64/tls.h @@ -0,0 +1,129 @@ +/* Definitions for thread-local data handling. linuxthreads/x86-64 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 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 _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include <pt-machine.h> +# include <stddef.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + +/* Get the thread descriptor definition. */ +# include <linuxthreads/descr.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + long int _result; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + asm volatile ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_descr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ |