From 187dd78d7bd1c03fcf16e54a30314512d38e1a4a Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 27 Feb 2003 18:13:05 +0000 Subject: Major update for pthreads, based in large part on improvements from glibc 2.3. This should make threads much more efficient. -Erik --- libpthread/linuxthreads/sysdeps/alpha/pt-machine.h | 45 ++- libpthread/linuxthreads/sysdeps/alpha/stackinfo.h | 28 ++ libpthread/linuxthreads/sysdeps/arm/pt-machine.h | 19 +- .../linuxthreads/sysdeps/arm/sigcontextinfo.h | 75 ++++- libpthread/linuxthreads/sysdeps/arm/stackinfo.h | 28 ++ libpthread/linuxthreads/sysdeps/cris/pt-machine.h | 20 +- libpthread/linuxthreads/sysdeps/cris/stackinfo.h | 28 ++ .../linuxthreads/sysdeps/i386/i686/pt-machine.h | 38 ++- libpthread/linuxthreads/sysdeps/i386/pt-machine.h | 27 +- .../linuxthreads/sysdeps/i386/sigcontextinfo.h | 45 ++- libpthread/linuxthreads/sysdeps/i386/stackinfo.h | 28 ++ libpthread/linuxthreads/sysdeps/i386/tls.h | 183 ++++++++++++ libpthread/linuxthreads/sysdeps/i386/useldt.h | 213 +++++++++++--- libpthread/linuxthreads/sysdeps/m68k/pt-machine.h | 27 +- libpthread/linuxthreads/sysdeps/m68k/stackinfo.h | 28 ++ libpthread/linuxthreads/sysdeps/mips/pt-machine.h | 111 +++---- libpthread/linuxthreads/sysdeps/mips/stackinfo.h | 28 ++ .../linuxthreads/sysdeps/powerpc/pt-machine.h | 82 ++++-- .../linuxthreads/sysdeps/powerpc/stackinfo.h | 28 ++ .../linuxthreads/sysdeps/pthread/bits/libc-lock.h | 327 +++++++++++++++++++++ .../linuxthreads/sysdeps/pthread/bits/libc-tsd.h | 35 ++- libpthread/linuxthreads/sysdeps/pthread/tls.h | 81 +++++ libpthread/linuxthreads/sysdeps/sh/pt-machine.h | 33 ++- libpthread/linuxthreads/sysdeps/sh/stackinfo.h | 28 ++ libpthread/linuxthreads/sysdeps/sh/tls.h | 115 ++++++++ libpthread/linuxthreads/sysdeps/sparc/stackinfo.h | 28 ++ 26 files changed, 1503 insertions(+), 225 deletions(-) create mode 100644 libpthread/linuxthreads/sysdeps/alpha/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/arm/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/cris/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/i386/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/i386/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/m68k/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/mips/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/sh/stackinfo.h create mode 100644 libpthread/linuxthreads/sysdeps/sh/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/sparc/stackinfo.h (limited to 'libpthread/linuxthreads/sysdeps') diff --git a/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h b/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h index e59c6906c..fa0374bc5 100644 --- a/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h @@ -1,30 +1,39 @@ /* Machine-dependent pthreads configuration and inline functions. Alpha version. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #endif -#include +#ifdef __linux__ +# include +#else +# include +#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. */ @@ -32,6 +41,12 @@ 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) @@ -55,11 +70,6 @@ testandset (int *spinlock) return ret; } -/* Spinlock release; default is just set to zero. */ -#define RELEASE(spinlock) \ - __asm__ __volatile__("mb" : : : "memory"); \ - *spinlock = 0 - /* Begin allocating thread stacks at this address. Default is to allocate them just below the initial program stack. */ @@ -70,7 +80,7 @@ testandset (int *spinlock) #define THREAD_SELF \ ({ \ register pthread_descr __self __asm__("$0"); \ - __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq) : "$0"); \ + __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ __self; \ }) @@ -102,7 +112,16 @@ __compare_and_swap (long int *p, long int oldval, long int newval) "2:\tmb\n" "/* End compare & swap */" : "=&r"(ret), "=m"(*p) - : "r"(oldval), "r"(newval), "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/libpthread/linuxthreads/sysdeps/alpha/stackinfo.h b/libpthread/linuxthreads/sysdeps/alpha/stackinfo.h new file mode 100644 index 000000000..0a281bd43 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/alpha/stackinfo.h @@ -0,0 +1,28 @@ +/* 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Alpha the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h index d4dc4c4ed..71001ebc2 100644 --- a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h @@ -1,35 +1,40 @@ /* Machine-dependent pthreads configuration and inline functions. ARM version. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Philip Blundell . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #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 int +PT_EI long int testandset (int *spinlock) { register unsigned int ret; @@ -46,3 +51,5 @@ testandset (int *spinlock) 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/libpthread/linuxthreads/sysdeps/arm/sigcontextinfo.h b/libpthread/linuxthreads/sysdeps/arm/sigcontextinfo.h index aebc3cfd5..0e6d295c3 100644 --- a/libpthread/linuxthreads/sysdeps/arm/sigcontextinfo.h +++ b/libpthread/linuxthreads/sysdeps/arm/sigcontextinfo.h @@ -17,7 +17,80 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include + +/* Definition of `struct sigcontext' for Linux/ARM + Copyright (C) 1996, 1997, 1998, 1999, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The format of struct sigcontext changed between 2.0 and 2.1 kernels. + Fortunately 2.0 puts a magic number in the first word and this is not + a legal value for `trap_no', so we can tell them apart. */ + +/* Early 2.2 and 2.3 kernels do not have the `fault_address' member in + the sigcontext structure. Unfortunately there is no reliable way + to test for its presence and this word will contain garbage for too-old + kernels. Versions 2.2.14 and 2.3.35 (plus later versions) are known to + include this element. */ + +#ifndef __ARMSIGCTX_H +#define __ARMSIGCTX_H 1 + +#include + +union k_sigcontext + { + struct + { + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + unsigned long int arm_r0; + unsigned long int arm_r1; + unsigned long int arm_r2; + unsigned long int arm_r3; + unsigned long int arm_r4; + unsigned long int arm_r5; + unsigned long int arm_r6; + unsigned long int arm_r7; + unsigned long int arm_r8; + unsigned long int arm_r9; + unsigned long int arm_r10; + unsigned long int arm_fp; + unsigned long int arm_ip; + unsigned long int arm_sp; + unsigned long int arm_lr; + unsigned long int arm_pc; + unsigned long int arm_cpsr; + unsigned long fault_address; + } v21; + struct + { + unsigned long int magic; + struct pt_regs reg; + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + } v20; +}; + +#define SIGCONTEXT_2_0_MAGIC 0x4B534154 + +#endif /* bits/armsigctx.h */ #define SIGCONTEXT int _a2, int _a3, int _a4, union k_sigcontext #define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4, diff --git a/libpthread/linuxthreads/sysdeps/arm/stackinfo.h b/libpthread/linuxthreads/sysdeps/arm/stackinfo.h new file mode 100644 index 000000000..2410ba9bd --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/arm/stackinfo.h @@ -0,0 +1,28 @@ +/* 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Arm the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/cris/pt-machine.h b/libpthread/linuxthreads/sysdeps/cris/pt-machine.h index e8073559a..eaead3058 100644 --- a/libpthread/linuxthreads/sysdeps/cris/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/cris/pt-machine.h @@ -1,27 +1,33 @@ /* Machine-dependent pthreads configuration and inline functions. CRIS version. - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001, 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #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) { @@ -37,7 +43,7 @@ testandset (int *spinlock) "bwf 0b\n\t" "clearf" : "=&r" (ret), "=m" (*spinlock) - : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) + : "r" (spinlock), "r" ((int) 1) : "memory"); return ret; } @@ -48,3 +54,5 @@ testandset (int *spinlock) 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/libpthread/linuxthreads/sysdeps/cris/stackinfo.h b/libpthread/linuxthreads/sysdeps/cris/stackinfo.h new file mode 100644 index 000000000..43c944834 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/cris/stackinfo.h @@ -0,0 +1,28 @@ +/* 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On cris the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h b/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h index 8d9ea709b..3596224c1 100644 --- a/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h @@ -1,45 +1,51 @@ /* Machine-dependent pthreads configuration and inline functions. i686 version. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #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 stack_pointer -register char * stack_pointer __asm__ ("%esp"); +#define CURRENT_STACK_FRAME __builtin_frame_address (0) /* Spinlock implementation; required. */ -PT_EI int +PT_EI long int testandset (int *spinlock) { - int ret; + long int ret; __asm__ __volatile__ ( "xchgl %0, %1" - : "=r"(ret), "=m"(*spinlock) - : "0"(1), "m"(*spinlock) + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) : "memory"); return ret; @@ -61,7 +67,13 @@ __compare_and_swap (long int *p, long int oldval, long int newval) : "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") -/* Use the LDT implementation only if the kernel is fixed. */ -//#include "../useldt.h" +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/pt-machine.h b/libpthread/linuxthreads/sysdeps/i386/pt-machine.h index f542bb2d2..79c69b549 100644 --- a/libpthread/linuxthreads/sysdeps/i386/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/i386/pt-machine.h @@ -1,39 +1,45 @@ /* Machine-dependent pthreads configuration and inline functions. i386 version. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #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__ ("%esp"); +#define CURRENT_STACK_FRAME __builtin_frame_address (0) /* Spinlock implementation; required. */ -PT_EI int +PT_EI long int testandset (int *spinlock) { - int ret; + long int ret; __asm__ __volatile__( "xchgl %0, %1" @@ -97,3 +103,6 @@ compare_and_swap_is_available (void) Otherwise, it's a 486 or above and it has cmpxchg. */ return changed != 0; } +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/sigcontextinfo.h b/libpthread/linuxthreads/sysdeps/i386/sigcontextinfo.h index 42c18b22b..6530ba6f3 100644 --- a/libpthread/linuxthreads/sysdeps/i386/sigcontextinfo.h +++ b/libpthread/linuxthreads/sysdeps/i386/sigcontextinfo.h @@ -1,24 +1,51 @@ -/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. 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. + 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 - Library General Public License for more details. + Lesser 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. */ + 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. */ #define SIGCONTEXT struct sigcontext #define SIGCONTEXT_EXTRA_ARGS #define GET_PC(ctx) ((void *) ctx.eip) #define GET_FRAME(ctx) ((void *) ctx.ebp) #define GET_STACK(ctx) ((void *) ctx.esp_at_signal) +#define CALL_SIGHANDLER(handler, signo, ctx) \ +do { \ + int __tmp1, __tmp2, __tmp3, __tmp4; \ + __asm __volatile ("movl\t%%esp, %%edi\n\t" \ + "andl\t$-16, %%esp\n\t" \ + "subl\t%8, %%esp\n\t" \ + "movl\t%%edi, %c8-4(%%esp)\n\t" \ + "movl\t%1, 0(%%esp)\n\t" \ + "leal\t4(%%esp), %%edi\n\t" \ + "cld\n\t" \ + "rep\tmovsl\n\t" \ + "call\t*%0\n\t" \ + "cld\n\t" \ + "movl\t%9, %%ecx\n\t" \ + "subl\t%%edi, %%esi\n\t" \ + "leal\t4(%%esp,%%esi,1), %%edi\n\t" \ + "leal\t4(%%esp), %%esi\n\t" \ + "rep\tmovsl\n\t" \ + "movl\t%c8-4(%%esp), %%esp\n\t" \ + : "=a" (__tmp1), "=d" (__tmp2), "=S" (__tmp3), \ + "=c" (__tmp4) \ + : "0" (handler), "1" (signo), "2" (&ctx), \ + "3" (sizeof (struct sigcontext) / 4), \ + "n" ((sizeof (struct sigcontext) + 19) & ~15), \ + "i" (sizeof (struct sigcontext) / 4) \ + : "cc", "edi"); \ +} while (0) diff --git a/libpthread/linuxthreads/sysdeps/i386/stackinfo.h b/libpthread/linuxthreads/sysdeps/i386/stackinfo.h new file mode 100644 index 000000000..a9a6745aa --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 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 contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/tls.h b/libpthread/linuxthreads/sysdeps/i386/tls.h new file mode 100644 index 000000000..5d1551e57 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/tls.h @@ -0,0 +1,183 @@ +/* Definition for thread-local data handling. linuxthreads/i386 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 + +# include + +#ifndef __ASSEMBLER__ +# include + +/* 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. */ +} tcbhead_t; +#endif + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +//# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* 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 + +# define TLS_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 }; \ + 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 ? -1 : nr * 8 + 7; \ +}) + +# 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)); \ + __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \ +}) + +# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_SET_THREAD_AREA (descr, firstcall) +# elif defined __NR_set_thread_area +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \ + __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; }) +# else +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_MODIFY_LDT ((descr), 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(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + int __gs; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ + if (__builtin_expect (__gs, 7) != -1) \ + { \ + asm ("movw %w0, %%gs" : : "q" (__gs)); \ + __gs = 0; \ + } \ + __gs; \ + }) + + +/* 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 /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/useldt.h b/libpthread/linuxthreads/sysdeps/i386/useldt.h index 1a789e2e0..16aee9989 100644 --- a/libpthread/linuxthreads/sysdeps/i386/useldt.h +++ b/libpthread/linuxthreads/sysdeps/i386/useldt.h @@ -1,29 +1,31 @@ /* Special definitions for ix86 machine using segment register based thread descriptor. - Copyright (C) 1998 Free Software Foundation, Inc. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper . 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 + 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 - Library General Public License for more details. + 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 Library General Public + 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. */ + Boston, MA 02111-1307, USA. */ +#ifndef __ASSEMBLER__ #include /* For offsetof. */ +#include /* For abort(). */ -/* We don't want to include the kernel header. So duplicate the - information. */ +/* We don't want to include the kernel header. So duplicate the + information. */ /* Structure passed on `modify_ldt' call. */ struct modify_ldt_ldt_s @@ -54,28 +56,128 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); ({ \ register pthread_descr __self; \ __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ - : "i" (offsetof (struct _pthread_descr_struct, p_self))); \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ __self; \ }) -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) \ -{ \ + +/* 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, sizeof (*descr), 1, 0, 0, 0, 0, 1, 0 }; \ + { 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__ __volatile__ ("movw %w0, %%gs" : : "r" (nr * 8 + 7)); \ -} + asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ +}) + +#ifdef __PIC__ +# define USETLS_EBX_ARG "r" +# define USETLS_LOAD_EBX "xchgl %3, %%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)); \ + 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)); \ + 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. */ -#define FREE_THREAD_SELF(descr, nr) \ +#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 }; \ - __asm__ __volatile__ ("movw %w0,%%gs" : : "r" (0)); \ __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ } +#endif /* Read member of the thread descriptor directly. */ #define THREAD_GETMEM(descr, member) \ @@ -83,20 +185,28 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); __typeof__ (descr->member) __value; \ if (sizeof (__value) == 1) \ __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ - : "=r" (__value) \ + : "=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) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + 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,%0" \ - : "=r" (__value) \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ : "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ } \ __value; \ }) @@ -107,18 +217,24 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); __typeof__ (descr->member) __value; \ if (sizeof (__value) == 1) \ __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ - : "=r" (__value) \ + : "=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) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + 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),%0" \ - : "=r" (__value) \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ : "r" (offsetof (struct _pthread_descr_struct, \ member))); \ } \ @@ -131,19 +247,27 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); __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) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ abort (); \ \ - __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ - : "r" (__value), \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ } \ }) @@ -153,18 +277,31 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); __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) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ abort (); \ \ - __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ - : "r" (__value), \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ "r" (offsetof (struct _pthread_descr_struct, \ member))); \ } \ }) +#endif + +/* 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 diff --git a/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h b/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h index 644bc2f0c..161b53469 100644 --- a/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h @@ -1,41 +1,41 @@ /* Machine-dependent pthreads configuration and inline functions. m68k version. - Copyright (C) 1996, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #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 int +PT_EI long int testandset (int *spinlock) { char ret; - __asm__ __volatile__( -#ifdef __mcf5200__ - "bset #7,%1; sne %0" -#else - "tas %1; sne %0" -#endif + __asm__ __volatile__("tas %1; sne %0" : "=dm"(ret), "=m"(*spinlock) : "m"(*spinlock) : "cc"); @@ -52,7 +52,6 @@ register char * stack_pointer __asm__ ("%sp"); /* Compare-and-swap for semaphores. */ -#ifndef __mcf5200__ #define HAS_COMPARE_AND_SWAP PT_EI int __compare_and_swap (long int *p, long int oldval, long int newval) @@ -66,5 +65,5 @@ __compare_and_swap (long int *p, long int oldval, long int newval) return ret; } -#endif +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/m68k/stackinfo.h b/libpthread/linuxthreads/sysdeps/m68k/stackinfo.h new file mode 100644 index 000000000..66e5a17fb --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/m68k/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 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 contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On m68k the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/mips/pt-machine.h b/libpthread/linuxthreads/sysdeps/mips/pt-machine.h index c40ab9e3e..59d26740f 100644 --- a/libpthread/linuxthreads/sysdeps/mips/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/mips/pt-machine.h @@ -1,59 +1,44 @@ /* Machine-dependent pthreads configuration and inline functions. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Ralf Baechle . + Contributed by Ralf Baechle . Based on the Alpha version by Richard Henderson . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - TODO: This version makes use of MIPS ISA 2 features. It won't - work on ISA 1. These machines will have to take the overhead of - a sysmips(MIPS_ATOMIC_SET, ...) syscall which isn't implemented - yet correctly. There is however a better solution for R3000 - uniprocessor machines possible. */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include #ifndef PT_EI # define PT_EI extern 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) { - long int ret, temp; - - __asm__ __volatile__( - "# Inline spinlock test & set\n\t" - ".set\tmips2\n" - "1:\tll\t%0,%3\n\t" - "bnez\t%0,2f\n\t" - ".set\tnoreorder\n\t" - "li\t%1,1\n\t" - ".set\treorder\n\t" - "sc\t%1,%2\n\t" - "beqz\t%1,1b\n" - "2:\t.set\tmips0\n\t" - "/* End spinlock test & set */" - : "=&r"(ret), "=&r" (temp), "=m"(*spinlock) - : "m"(*spinlock) - : "memory"); - - return ret; + return _test_and_set (spinlock, 1); } @@ -69,49 +54,27 @@ register char * stack_pointer __asm__ ("$29"); PT_EI int __compare_and_swap (long int *p, long int oldval, long int newval) { - long ret; - - __asm__ __volatile__ ( - "/* Inline compare & swap */\n\t" - ".set\tmips2\n" - "1:\tll\t%0,%4\n\t" - ".set\tnoreorder\n\t" - "bne\t%0,%2,2f\n\t" - "move\t%0,$0\n\t" /*[NDF] Failure case. */ - "move\t%0,%3\n\t" - ".set\treorder\n\t" - "sc\t%0,%1\n\t" - "beqz\t%0,1b\n" - "2:\t.set\tmips0\n\t" - "/* End compare & swap */" - : "=&r"(ret), "=m"(*p) - : "r"(oldval), "r"(newval), "m"(*p)); - - return ret; - - /* - 1: load locked: into ret(%0), from *p(0(%4)) - branch to 2 if ret(%0) != oldval(%2) - Delay slot: move 0 into ret(%0) // [NDF] Added - Don't branch case: - move newval(%3) into ret(%0) - setcompare ret(%0) into *p(0(%1)) - branch to 1 if ret(%0) == 0 (sc failed) - Delay slot: unknown/none - return - - 2: Delay slot - return - -ll a b -Sets a to the value pointed to by address b, and "locks" b so that if -any of a number of things are attempted that might access b then the -next sc will fail. - -sc a b -Sets the memory address pointed to by b to the value in a atomically. -If it succeeds then a will be set to 1, if it fails a will be set to 0. + long int ret, temp; - */ + __asm__ __volatile__ + ("/* Inline compare & swap */\n" + "1:\n\t" + ".set push\n\t" + ".set mips2\n\t" + "ll %1,%5\n\t" + "move %0,$0\n\t" + "bne %1,%3,2f\n\t" + "move %0,%4\n\t" + "sc %0,%2\n\t" + ".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/libpthread/linuxthreads/sysdeps/mips/stackinfo.h b/libpthread/linuxthreads/sysdeps/mips/stackinfo.h new file mode 100644 index 000000000..86e3d621b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/mips/stackinfo.h @@ -0,0 +1,28 @@ +/* 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On MIPS the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h b/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h index 578369a7f..19b77b7e6 100644 --- a/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h @@ -1,19 +1,19 @@ /* Machine-dependent pthreads configuration and inline functions. powerpc version. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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. */ @@ -21,18 +21,20 @@ /* 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 #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. */ -#if 0 -/* on non multiprocessor systems, you can just: */ -#define sync() /* nothing */ -#else -#define sync() __asm__ __volatile__ ("sync") -#endif + 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") /* Get some notion of the current stack. Need not be exactly the top of the stack, just something somewhere in the current frame. */ @@ -40,30 +42,52 @@ register char * stack_pointer __asm__ ("r1"); /* Compare-and-swap for semaphores. */ -/* note that test-and-set(x) is the same as compare-and-swap(x, 0, 1) */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ -#define HAS_COMPARE_AND_SWAP -#if BROKEN_PPC_ASM_CR0 -static -#else -PT_EI -#endif -int +#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; - sync(); - __asm__ __volatile__( - "0: lwarx %0,0,%1 ;" - " xor. %0,%3,%0;" - " bne 1f;" - " stwcx. %2,0,%1;" - " bne- 0b;" - "1: " + __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"); - sync(); + /* 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/libpthread/linuxthreads/sysdeps/powerpc/stackinfo.h b/libpthread/linuxthreads/sysdeps/powerpc/stackinfo.h new file mode 100644 index 000000000..839758a4e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 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 contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On PPC the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 000000000..4e884a030 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,327 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,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. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +/* 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 +#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 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} + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#define __libc_lock_init(NAME) \ + (__pthread_mutex_init != NULL ? __pthread_mutex_init (&(NAME), NULL) : 0); +#define __libc_rwlock_init(NAME) \ + (__pthread_rwlock_init != NULL ? __pthread_rwlock_init (&(NAME), NULL) : 0); + +/* Same as last but this time we initialize a recursive mutex. */ +#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); + +/* 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) \ + (__pthread_mutex_destroy != NULL ? __pthread_mutex_destroy (&(NAME)) : 0); +#define __libc_rwlock_fini(NAME) \ + (__pthread_rwlock_destroy != NULL ? __pthread_rwlock_destroy (&(NAME)) : 0); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__pthread_mutex_lock != NULL ? __pthread_mutex_lock (&(NAME)) : 0); +#define __libc_rwlock_rdlock(NAME) \ + (__pthread_rwlock_rdlock != NULL ? __pthread_rwlock_rdlock (&(NAME)) : 0); +#define __libc_rwlock_wrlock(NAME) \ + (__pthread_rwlock_wrlock != NULL ? __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) \ + (__pthread_mutex_trylock != NULL ? __pthread_mutex_trylock (&(NAME)) : 0) +#define __libc_rwlock_tryrdlock(NAME) \ + (__pthread_rwlock_tryrdlock != NULL \ + ? __pthread_rwlock_tryrdlock (&(NAME)) : 0) +#define __libc_rwlock_trywrlock(NAME) \ + (__pthread_rwlock_trywrlock != NULL \ + ? __pthread_rwlock_trywrlock (&(NAME)) : 0) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__pthread_mutex_unlock != NULL ? __pthread_mutex_unlock (&(NAME)) : 0); +#define __libc_rwlock_unlock(NAME) \ + (__pthread_rwlock_unlock != NULL ? __pthread_rwlock_unlock (&(NAME)) : 0); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + + +/* 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) = !PTHREAD_ONCE_INIT; \ + } \ + } 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)); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__pthread_key_create != NULL ? __pthread_key_create (KEY, DESTRUCTOR) : 1) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__pthread_getspecific != NULL ? __pthread_getspecific (KEY) : NULL) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__pthread_setspecific != NULL ? __pthread_setspecific (KEY, VALUE) : 0) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__pthread_atfork != NULL ? __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 +# 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_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 +# 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/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h index ca53b94d2..35a6a19a6 100644 --- a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h @@ -1,18 +1,18 @@ /* libc-internal interface for thread-specific data. LinuxThreads version. - Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + Copyright (C) 1997,98,99,2001,02 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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. */ @@ -20,17 +20,36 @@ #ifndef _BITS_LIBC_TSD_H #define _BITS_LIBC_TSD_H 1 -#include - /* Fast thread-specific data internal to libc. */ enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, _LIBC_TSD_KEY_DL_ERROR, _LIBC_TSD_KEY_RPC_VARS, + _LIBC_TSD_KEY_LOCALE, + _LIBC_TSD_KEY_CTYPE_B, + _LIBC_TSD_KEY_CTYPE_TOLOWER, + _LIBC_TSD_KEY_CTYPE_TOUPPER, _LIBC_TSD_KEY_N }; +#include +#include + +#if USE_TLS && HAVE___THREAD + +/* When __thread works, the generic definition is what we want. */ +# include + +#else + extern void *(*__libc_internal_tsd_get) (enum __libc_tsd_key_t) __THROW; extern int (*__libc_internal_tsd_set) (enum __libc_tsd_key_t, __const void *) __THROW; +extern void **(*const __libc_internal_tsd_address) (enum __libc_tsd_key_t) + __THROW __attribute__ ((__const__)); + +#define __libc_tsd_address(KEY) \ + (__libc_internal_tsd_address != NULL \ + ? __libc_internal_tsd_address (_LIBC_TSD_KEY_##KEY) \ + : &__libc_tsd_##KEY##_data) #define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; #define __libc_tsd_get(KEY) \ @@ -42,4 +61,6 @@ extern int (*__libc_internal_tsd_set) (enum __libc_tsd_key_t, ? __libc_internal_tsd_set (_LIBC_TSD_KEY_##KEY, (VALUE)) \ : ((__libc_tsd_##KEY##_data = (VALUE)), 0)) +#endif + #endif /* bits/libc-tsd.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/tls.h b/libpthread/linuxthreads/sysdeps/pthread/tls.h new file mode 100644 index 000000000..6a23ec05e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/tls.h @@ -0,0 +1,81 @@ +/* Definition for thread-local data handling. Generic 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. */ + +/* By default no TLS support is available. This is signaled by the + absence of the symbol USE_TLS. */ +#undef USE_TLS + + +/* An architecture-specific version of this file has to defined a + number of symbols: + + TLS_TCB_AT_TP or TLS_DTV_AT_TP + + The presence of one of these symbols signals which variant of + the TLS ABI is used. There are in the moment two variants + available: + + * the thread pointer points to a thread control block + + * the thread pointer points to the dynamic thread vector + + + TLS_TCB_SIZE + + This is the size of the thread control block structure. How + this is actually defined depends on the ABI. The thread control + block could be internal descriptor of the thread library or + just a data structure which allows finding the DTV. + + TLS_INIT_TCB_SIZE + + Similarly, but this value is only used at startup and in the + dynamic linker itself. There are no threads in use at that time. + + + TLS_TCB_ALIGN + + Alignment requirements for the TCB structure. + + TLS_INIT_TCB_ALIGN + + Similarly, but for the structure used at startup time. + + + INSTALL_DTV(tcb, init_dtv) + + This macro must install the given initial DTV into the thread control + block TCB. The normal runtime functionality must then be able to + use the value. + + + TLS_INIT_TP(tcb, firstcall) + + This macro must initialize the thread pointer to enable normal TLS + operation. The first parameter is a pointer to the thread control + block. The second parameter specifies whether this is the first + call for the TCB. ld.so calls this macro more than once. + + + THREAD_DTV() + + This macro returns the address of the DTV of the current thread. + This normally is done using the the thread register which points + to the dtv or the TCB (from which the DTV can found). + */ diff --git a/libpthread/linuxthreads/sysdeps/sh/pt-machine.h b/libpthread/linuxthreads/sysdeps/sh/pt-machine.h index 7287dc936..cc3a4f2ce 100644 --- a/libpthread/linuxthreads/sysdeps/sh/pt-machine.h +++ b/libpthread/linuxthreads/sysdeps/sh/pt-machine.h @@ -1,28 +1,35 @@ /* Machine-dependent pthreads configuration and inline functions. SuperH version. - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Niibe Yutaka . 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 + 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 - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public + 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 #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) @@ -39,6 +46,11 @@ testandset (int *spinlock) 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. */ @@ -53,4 +65,13 @@ struct _pthread_descr_struct; /* Initialize the thread-unique value. */ #define INIT_THREAD_SELF(descr, nr) \ - ({ __asm__("ldc %0,gbr" : : "r" (descr));}) + ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) THREAD_SELF->member +#define THREAD_GETMEM_NC(descr, member) THREAD_SELF->member +#define THREAD_SETMEM(descr, member, value) THREAD_SELF->member = (value) +#define THREAD_SETMEM_NC(descr, member, value) THREAD_SELF->member = (value) +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/sh/stackinfo.h b/libpthread/linuxthreads/sysdeps/sh/stackinfo.h new file mode 100644 index 000000000..e65338f25 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sh/stackinfo.h @@ -0,0 +1,28 @@ +/* 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On SH the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libpthread/linuxthreads/sysdeps/sh/tls.h b/libpthread/linuxthreads/sysdeps/sh/tls.h new file mode 100644 index 000000000..ee3db5ae8 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sh/tls.h @@ -0,0 +1,115 @@ +/* Definition for thread-local data handling. linuxthreads/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 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 + +#include + +/* 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. */ +} tcbhead_t; + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Get system call information. */ +# include + +/* Signal that TLS support is available. */ +//# define USE_TLS 1 + + +/* Get the thread descriptor definition. */ +# include + +/* 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 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(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); \ + int result; \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + asm ("ldc %0,gbr" : : "r" (_descr)); \ + \ + 0; \ + }) + + +/* 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 /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/sparc/stackinfo.h b/libpthread/linuxthreads/sysdeps/sparc/stackinfo.h new file mode 100644 index 000000000..fd34e2deb --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/stackinfo.h @@ -0,0 +1,28 @@ +/* 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. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On sparc the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ -- cgit v1.2.3