diff options
Diffstat (limited to 'libpthread/linuxthreads/sysdeps')
26 files changed, 1503 insertions, 225 deletions
| 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 <rth@tamu.edu>.     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 <asm/pal.h> +#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.  */ @@ -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 <philb@gnu.org>.     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 <bits/armsigctx.h> + +/* 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 <asm/ptrace.h> + +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 <rth@tamu.edu>.     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 <rth@tamu.edu>.     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 <drepper@cygnus.com>, 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 <pt-machine.h> + +#ifndef __ASSEMBLER__ +# 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.  */ +} 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 <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 + +#  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 <drepper@cygnus.com>.     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 <stddef.h>	/* For offsetof.  */ +#include <stdlib.h>	/* 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 <rth@tamu.edu>.     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 <ralf@gnu.ai.mit.edu>. +   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 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 <sys/tas.h>  #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 <pthread.h> + +/* 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 <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_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 <features.h> -  /* 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 <sys/cdefs.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 +  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 <gniibe@m17n.org>.     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 <stddef.h> + +#include <pt-machine.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.  */ +} 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 <sysdep.h> + +/* Signal that TLS support is available.  */ +//# define USE_TLS	1 + + +/* 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 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 */ | 
