summaryrefslogtreecommitdiff
path: root/libpthread/nptl/sysdeps/arm
diff options
context:
space:
mode:
authorAustin Foxley <austinf@cetoncorp.com>2009-10-17 12:26:24 -0700
committerAustin Foxley <austinf@cetoncorp.com>2009-10-17 12:26:24 -0700
commitc68d0fa2d88fc2134a38d99e7e944828384a7671 (patch)
tree6596943bd1c77f18d6e49d4153ddd3f3d67b49f5 /libpthread/nptl/sysdeps/arm
parent9a03e98a3b418f33c347a6023e9320f3a42cb9e4 (diff)
libpthread/nptl: core of the "Native Posix Threading Library" for uClibc
targetting arm,sh,i386,mips,sparc for now Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Diffstat (limited to 'libpthread/nptl/sysdeps/arm')
-rw-r--r--libpthread/nptl/sysdeps/arm/Makefile.arch69
-rw-r--r--libpthread/nptl/sysdeps/arm/aeabi_read_tp.S1
-rw-r--r--libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c1
-rw-r--r--libpthread/nptl/sysdeps/arm/dl-tls.h30
-rw-r--r--libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h37
-rw-r--r--libpthread/nptl/sysdeps/arm/pthread_spin_lock.S32
-rw-r--r--libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S35
-rw-r--r--libpthread/nptl/sysdeps/arm/pthreaddef.h40
-rw-r--r--libpthread/nptl/sysdeps/arm/sysdep.h92
-rw-r--r--libpthread/nptl/sysdeps/arm/tcb-offsets.sym12
-rw-r--r--libpthread/nptl/sysdeps/arm/thumb_atomics.S1
-rw-r--r--libpthread/nptl/sysdeps/arm/tls.h141
12 files changed, 491 insertions, 0 deletions
diff --git a/libpthread/nptl/sysdeps/arm/Makefile.arch b/libpthread/nptl/sysdeps/arm/Makefile.arch
new file mode 100644
index 000000000..6d16ae3fd
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/Makefile.arch
@@ -0,0 +1,69 @@
+# Makefile for uClibc NPTL
+#
+# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org>
+# Portions Copyright (C) 2006 CodeSourcery
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+libpthread_SSRC = pthread_spin_lock.S pthread_spin_trylock.S aeabi_read_tp.S \
+ thumb_atomics.S
+libpthread_CSRC = aeabi_unwind_cpp_pr1.c
+
+librt_SSRC = aeabi_read_tp.S thumb_atomics.S
+librt_CSRC = aeabi_unwind_cpp_pr1.c
+
+libc_a_CSRC =
+
+CFLAGS-pt-raise.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1
+
+ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1
+ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1
+ASFLAGS-aeabi_read_tp.S = -DNOT_IN_libc=1
+
+CFLAGS-arm = $(SSP_ALL_CFLAGS)
+
+PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/arm
+PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/arm
+PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC))
+PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC))
+LIBRT_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(librt_SSRC))
+LIBRT_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(librt_CSRC))
+
+
+ifeq ($(DOPIC),y)
+libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os)
+else
+libpthread-a-y += $(PTHREAD_ARCH_OBJ)
+endif
+libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS)
+
+librt-a-y += $(LIBRT_ARCH_OBJ)
+librt-so-y += $(LIBRT_ARCH_OBJ:.o=.oS)
+
+libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ)
+
+objclean-y += nptl_arch_objclean
+headers_clean-y += nptl_arch_headers_clean
+
+#
+# Create 'tcb-offsets.h' header file.
+#
+CFLAGS-tcb-offsets.c = -S
+
+$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym
+ $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@
+
+$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c
+ $(compile.c)
+
+nptl_arch_headers: $(PTHREAD_ARCH_OUT)/tcb-offsets.s
+ $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $(PTHREAD_ARCH_OUT)/tcb-offsets.h
+
+nptl_arch_headers_clean:
+ $(RM) $(PTHREAD_ARCH_OUT)/tcb-offsets.c \
+ $(PTHREAD_ARCH_OUT)/tcb-offsets.s \
+ $(PTHREAD_ARCH_OUT)/tcb-offsets.h
+
+nptl_arch_objclean:
+ $(RM) $(PTHREAD_ARCH_OUT)/*.{o,os,oS}
diff --git a/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S b/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S
new file mode 100644
index 000000000..af640d625
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S
@@ -0,0 +1 @@
+#include <../../../../ldso/ldso/arm/aeabi_read_tp.S>
diff --git a/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c b/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c
new file mode 100644
index 000000000..84683627b
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c
@@ -0,0 +1 @@
+#include <../../../../libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c>
diff --git a/libpthread/nptl/sysdeps/arm/dl-tls.h b/libpthread/nptl/sysdeps/arm/dl-tls.h
new file mode 100644
index 000000000..f74f3f8da
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/dl-tls.h
@@ -0,0 +1,30 @@
+/* Thread-local storage handling in the ELF dynamic linker. ARM version.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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. */
+
+
+/* Type used for the representation of TLS information in the GOT. */
+typedef struct
+{
+ unsigned long int ti_module;
+ unsigned long int ti_offset;
+} tls_index;
+
+
+extern void *__tls_get_addr (tls_index *ti);
+
diff --git a/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h
new file mode 100644
index 000000000..97a7760a9
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2005,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#undef _JMPBUF_UNWINDS
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+ ((void *) (address) < (void *) demangle (jmpbuf[__JMP_BUF_SP]))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj))
+
+/* We use the normal longjmp for unwinding. */
+#define __libc_unwind_longjmp(buf, val) longjmp (buf, val)
+
diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S
new file mode 100644
index 000000000..614711446
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S
@@ -0,0 +1,32 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+
+ .text
+ .align 4
+
+ENTRY (pthread_spin_lock)
+ mov r1, #1
+1: swp r2, r1, [r0]
+ teq r2, #0
+ bne 1b
+ mov r0, #0
+ PSEUDO_RET_NOERRNO
+END (pthread_spin_lock)
+
diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S
new file mode 100644
index 000000000..0c633f94c
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S
@@ -0,0 +1,35 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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. */
+
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+#include <sysdep.h>
+
+ .text
+ .align 4
+
+ENTRY (pthread_spin_trylock)
+ mov r1, #1
+ swp r2, r1, [r0]
+ teq r2, #0
+ moveq r0, #0
+ movne r0, #EBUSY
+ PSEUDO_RET_NOERRNO
+END (pthread_spin_trylock)
+
diff --git a/libpthread/nptl/sysdeps/arm/pthreaddef.h b/libpthread/nptl/sysdeps/arm/pthreaddef.h
new file mode 100644
index 000000000..72206d18d
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/pthreaddef.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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. */
+
+/* Default stack size. */
+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning. SSE requires 16
+ bytes. */
+#define STACK_ALIGN 16
+
+/* Minimal stack size after allocating thread descriptor and guard size. */
+#define MINIMAL_REST_STACK 2048
+
+/* Alignment requirement for TCB. */
+#define TCB_ALIGNMENT 16
+
+
+/* Location of current stack frame. */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
+
+
+/* XXX Until we have a better place keep the definitions here. */
+#define __exit_thread_inline(val) \
+ INLINE_SYSCALL (exit, 1, (val))
+
diff --git a/libpthread/nptl/sysdeps/arm/sysdep.h b/libpthread/nptl/sysdeps/arm/sysdep.h
new file mode 100644
index 000000000..5c6fc0804
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/sysdep.h
@@ -0,0 +1,92 @@
+/* Assembler macros for ARM.
+ Copyright (C) 1997, 1998, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdeps/generic/sysdep.h>
+
+#ifdef __ASSEMBLER__
+
+/* Syntactic details of assembler. */
+
+#define ALIGNARG(log2) log2
+/* For ELF we need the `.type' directive to make shared libs work right. */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+/* In ELF C symbols are asm symbols. */
+#undef NO_UNDERSCORES
+#define NO_UNDERSCORES
+
+#define PLTJMP(_x) _x##(PLT)
+
+/* APCS-32 doesn't preserve the condition codes across function call. */
+#ifdef __APCS_32__
+#define LOADREGS(cond, base, reglist...)\
+ ldm##cond base,reglist
+#ifdef __USE_BX__
+#define RETINSTR(cond, reg) \
+ bx##cond reg
+#define DO_RET(_reg) \
+ bx _reg
+#else
+#define RETINSTR(cond, reg) \
+ mov##cond pc, reg
+#define DO_RET(_reg) \
+ mov pc, _reg
+#endif
+#else /* APCS-26 */
+#define LOADREGS(cond, base, reglist...)\
+ ldm##cond base,reglist^
+#define RETINSTR(cond, reg) \
+ mov##cond##s pc, reg
+#define DO_RET(_reg) \
+ movs pc, _reg
+#endif
+
+/* Define an entry point visible from C. */
+#define ENTRY(name) \
+ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
+ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \
+ .align ALIGNARG(4); \
+ name##: \
+ CALL_MCOUNT
+
+#undef END
+#define END(name) \
+ ASM_SIZE_DIRECTIVE(name)
+
+/* If compiled for profiling, call `mcount' at the start of each function. */
+#ifdef PROF
+#define CALL_MCOUNT \
+ str lr,[sp, #-4]! ; \
+ bl PLTJMP(mcount) ; \
+ ldr lr, [sp], #4 ;
+#else
+#define CALL_MCOUNT /* Do nothing. */
+#endif
+
+#ifdef NO_UNDERSCORES
+/* Since C identifiers are not normally prefixed with an underscore
+ on this system, the asm identifier `syscall_error' intrudes on the
+ C name space. Make sure we use an innocuous name. */
+#define syscall_error __syscall_error
+#define mcount _mcount
+#endif
+
+#endif /* __ASSEMBLER__ */
+
diff --git a/libpthread/nptl/sysdeps/arm/tcb-offsets.sym b/libpthread/nptl/sysdeps/arm/tcb-offsets.sym
new file mode 100644
index 000000000..008ce3aa5
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/tcb-offsets.sym
@@ -0,0 +1,12 @@
+#include <sysdep.h>
+#include <tls.h>
+
+--
+
+-- Derive offsets relative to the thread register.
+#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread))
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
+PID_OFFSET thread_offsetof (pid)
+TID_OFFSET thread_offsetof (tid)
+
diff --git a/libpthread/nptl/sysdeps/arm/thumb_atomics.S b/libpthread/nptl/sysdeps/arm/thumb_atomics.S
new file mode 100644
index 000000000..aaa7a3d8f
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/thumb_atomics.S
@@ -0,0 +1 @@
+#include <../../../../ldso/ldso/arm/thumb_atomics.S>
diff --git a/libpthread/nptl/sysdeps/arm/tls.h b/libpthread/nptl/sysdeps/arm/tls.h
new file mode 100644
index 000000000..fa98124ee
--- /dev/null
+++ b/libpthread/nptl/sysdeps/arm/tls.h
@@ -0,0 +1,141 @@
+/* Definition for thread-local data handling. NPTL/ARM version.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU 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 1
+
+#ifndef __ASSEMBLER__
+#include <dl-sysdep.h>
+
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv. */
+typedef union dtv
+{
+ size_t counter;
+ struct
+ {
+ void *val;
+ bool is_static;
+ } pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+
+/* We require TLS support in the tools. */
+#define HAVE_TLS_SUPPORT 1
+#define HAVE_TLS_MODEL_ATTRIBUTE 1
+#define HAVE___THREAD 1
+
+/* Signal that TLS support is available. */
+#define USE_TLS 1
+
+/* Like all other modern NPTL ports, ARM uses forced unwinding. */
+#define HAVE_FORCED_UNWIND
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information. */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks. */
+# define TLS_DTV_AT_TP 1
+
+/* Get the thread descriptor definition. */
+# include <../../descr.h>
+
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
+
+/* This is the size of the initial TCB. */
+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB. */
+# define TLS_INIT_TCB_ALIGN 16
+
+/* This is the size of the TCB. */
+# define TLS_TCB_SIZE sizeof (tcbhead_t)
+
+/* This is the size we need before TCB. */
+# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
+
+/* Alignment requirements for the TCB. */
+# define TLS_TCB_ALIGN 16
+
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
+# define INSTALL_DTV(tcbp, dtvp) \
+ (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
+
+/* Install new dtv for current thread. */
+# define INSTALL_NEW_DTV(dtv) \
+ (THREAD_DTV() = (dtv))
+
+/* Return dtv of given thread descriptor. */
+# define GET_DTV(tcbp) \
+ (((tcbhead_t *) (tcbp))->dtv)
+
+/* Code to initially initialize the thread pointer. This might need
+ special attention since 'errno' is not yet available and if the
+ operation can cause a failure 'errno' must not be touched. */
+# define TLS_INIT_TP(tcbp, secondcall) \
+ ({ INTERNAL_SYSCALL_DECL (err); \
+ long result_var; \
+ result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (tcbp)); \
+ INTERNAL_SYSCALL_ERROR_P (result_var, err) \
+ ? "unknown error" : NULL; })
+
+/* Return the address of the dtv for the current thread. */
+# define THREAD_DTV() \
+ (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
+
+/* Return the thread descriptor for the current thread. */
+# define THREAD_SELF \
+ ((struct pthread *)__builtin_thread_pointer () - 1)
+
+/* Magic for libthread_db to know how to do THREAD_SELF. */
+# define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+/* Access to data in the thread descriptor is easy. */
+#define THREAD_GETMEM(descr, member) \
+ descr->member
+#define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+#define THREAD_SETMEM(descr, member, value) \
+ descr->member = (value)
+#define THREAD_SETMEM_NC(descr, member, idx, value) \
+ descr->member[idx] = (value)
+
+/* Initializing the thread pointer will generate a SIGILL if the syscall
+ is not available. */
+#define TLS_INIT_TP_EXPENSIVE 1
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
+