summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads/sysdeps
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-02-27 18:13:05 +0000
committerEric Andersen <andersen@codepoet.org>2003-02-27 18:13:05 +0000
commit187dd78d7bd1c03fcf16e54a30314512d38e1a4a (patch)
tree9780638e5286b40da74a128c9f540a9ea720862f /libpthread/linuxthreads/sysdeps
parentd4d6e2c50565da18253cd0d6f3332484142b6587 (diff)
Major update for pthreads, based in large part on improvements
from glibc 2.3. This should make threads much more efficient. -Erik
Diffstat (limited to 'libpthread/linuxthreads/sysdeps')
-rw-r--r--libpthread/linuxthreads/sysdeps/alpha/pt-machine.h45
-rw-r--r--libpthread/linuxthreads/sysdeps/alpha/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/pt-machine.h19
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/sigcontextinfo.h75
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/cris/pt-machine.h20
-rw-r--r--libpthread/linuxthreads/sysdeps/cris/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h38
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/pt-machine.h27
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/sigcontextinfo.h45
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/tls.h183
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/useldt.h213
-rw-r--r--libpthread/linuxthreads/sysdeps/m68k/pt-machine.h27
-rw-r--r--libpthread/linuxthreads/sysdeps/m68k/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/mips/pt-machine.h111
-rw-r--r--libpthread/linuxthreads/sysdeps/mips/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h82
-rw-r--r--libpthread/linuxthreads/sysdeps/powerpc/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h327
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h35
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/tls.h81
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/pt-machine.h33
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/tls.h115
-rw-r--r--libpthread/linuxthreads/sysdeps/sparc/stackinfo.h28
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 */