ARM NPTL - EABI

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

ARM NPTL - EABI

Daniel Jacobowitz-2
I've just checked in NPTL support for arm-none-linux-gnueabi.  Support for
the APCS ABI will follow in a moment.

Bits of this were originally written by Phil Blundell; thanks, Phil!  I've
butchered it all pretty thoroughly since then though.

For both ARM ports, most of the interesting bits were caused by the fact
that ARM doesn't use dwarf2 exception handling.  For EABI, all the necessary
bits have just been checked in to GCC (this morning, will be in 4.1).  The
implementation of _Unwind_GetCFA is a bit hokey, but works well enough for
NPTL.  One difference between the ARM compact EH tables and dwarf2 EH tables
is that the compact tables have only starting PC addresses, not ending; one
NPTL test had to be skipped because it relied on unwinding stopping when we
entered a region where we had no unwinding information.  As a consequence,
to use pthread cancellation on the ARM EABI, everything on the call chain
must either be compiled with exception tables, or in a shared object
containing no EH tables at all.  Otherwise, an earlier function's unwind
tables will be used with predictable results.

Atomic operations are provided by a kernel helper, in order to guarantee
atomicity on pre-ARMv6 platforms, where "swp" is the best we have.  The
kernel helper was added mid-2.6.  They could be implemented without a kernel
helper on v6 and later platforms if anyone is interested in doing that.
Futexes are implemented using only atomic_exchange_acq and swp; the cmpxchg
helper was not required here.  Nicolas Pitre lent me a hand with getting
those right.

--
Daniel Jacobowitz
CodeSourcery, LLC

2005-11-16  Daniel Jacobowitz  <[hidden email]>

        * sysdeps/arm/bits/setjmp.h, sysdeps/arm/fpu/bits/setjmp.h: Update
        include guards.

        * sysdeps/unix/arm/sysdep.S (syscall_error): Handle USE___THREAD and
        RTLD_PRIVATE_ERRNO.

        * sysdeps/unix/sysv/linux/arm/clone.S (__clone): Handle RESET_PID.
        Handle new arguments.
        * sysdeps/unix/sysv/linux/arm/vfork.S (__vfork): Use SAVE_PID and
        RESTORE_PID.  Use the right syscall error handler.

        * sysdeps/unix/sysv/linux/arm/eabi/sigrestorer.S
        (__default_sa_restorer, __default_rt_sa_restorer): Add unwind
        information.

        * sysdeps/unix/sysv/linux/arm/eabi/socket.S: Update formatting.
        Add unwind information.  Correct stack alignment typo.

        * sysdeps/unix/sysv/linux/arm/eabi/sysdep.h
        (INTERNAL_SYSCALL_NCS): Define.

        * sysdeps/unix/sysv/linux/arm/sigaction.c
        (__libc_sigaction): Remove never-valid handling for SA_ONSTACK.

        * sysdeps/unix/sysv/linux/arm/socket.S: Whitespace cleanup.

        * sysdeps/unix/sysv/linux/arm/sysdep.h (SYSCALL_ERROR_HANDLER): Handle
        RTLD_PRIVATE_ERRNO.
        (INTERNAL_SYSCALL_NCS): Implement.

        * sysdeps/arm/nptl/Makefile, sysdeps/arm/nptl/jmpbuf-unwind.h,
        sysdeps/arm/nptl/pthread_spin_lock.S,
        sysdeps/arm/nptl/pthread_spin_trylock.S,
        sysdeps/arm/nptl/pthreaddef.h, sysdeps/arm/nptl/tcb-offsets.sym,
        sysdeps/arm/nptl/tls.h, sysdeps/unix/sysv/linux/arm/eabi/Makefile,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/Makefile,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/configure,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/configure.in,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/nptl-aeabi_unwind_cpp_pr1.c,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/rt-aeabi_unwind_cpp_pr1.c,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/sysdep-cancel.h,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-forcedunwind.c,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-resume.c,
        sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h,
        sysdeps/unix/sysv/linux/arm/nptl/Versions,
        sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h,
        sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h,
        sysdeps/unix/sysv/linux/arm/nptl/clone.S,
        sysdeps/unix/sysv/linux/arm/nptl/createthread.c,
        sysdeps/unix/sysv/linux/arm/nptl/fork.c,
        sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.c,
        sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h,
        sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S,
        sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c,
        sysdeps/unix/sysv/linux/arm/nptl/vfork.S: New files.

Index: glibc/ports/sysdeps/arm/bits/setjmp.h
===================================================================
--- glibc.orig/ports/sysdeps/arm/bits/setjmp.h 2005-11-16 11:12:20.000000000 -0500
+++ glibc/ports/sysdeps/arm/bits/setjmp.h 2005-11-16 11:50:51.000000000 -0500
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 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
@@ -18,7 +18,10 @@
 
 /* Define the machine-dependent type `jmp_buf'.  ARM version. */
 
-#ifndef _SETJMP_H
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H 1
+
+#if !defined _SETJMP_H && !defined _PTHREAD_H
 # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
 #endif
 
@@ -34,3 +37,5 @@ typedef int __jmp_buf[10];
    containing a local variable at ADDRESS.  */
 #define _JMPBUF_UNWINDS(jmpbuf, address) \
   ((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
+
+#endif
Index: glibc/ports/sysdeps/arm/fpu/bits/setjmp.h
===================================================================
--- glibc.orig/ports/sysdeps/arm/fpu/bits/setjmp.h 2005-11-16 11:12:20.000000000 -0500
+++ glibc/ports/sysdeps/arm/fpu/bits/setjmp.h 2005-11-16 11:50:51.000000000 -0500
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 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
@@ -18,7 +18,10 @@
 
 /* Define the machine-dependent type `jmp_buf'.  ARM version. */
 
-#ifndef _SETJMP_H
+#ifndef _BITS_SETJMP_H
+#define _BITS_SETJMP_H 1
+
+#if !defined _SETJMP_H && !defined _PTHREAD_H
 # error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
 #endif
 
@@ -34,3 +37,5 @@ typedef int __jmp_buf[22];
    containing a local variable at ADDRESS.  */
 #define _JMPBUF_UNWINDS(jmpbuf, address) \
   ((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
+
+#endif
Index: glibc/ports/sysdeps/arm/nptl/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/Makefile 2005-11-16 13:26:58.000000000 -0500
@@ -0,0 +1,21 @@
+# 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.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
Index: glibc/ports/sysdeps/arm/nptl/jmpbuf-unwind.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/jmpbuf-unwind.h 2005-11-16 13:27:03.000000000 -0500
@@ -0,0 +1,30 @@
+/* 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 <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+
+#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) __libc_longjmp (buf, val)
Index: glibc/ports/sysdeps/arm/nptl/pthread_spin_lock.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/pthread_spin_lock.S 2005-11-16 13:27:25.000000000 -0500
@@ -0,0 +1,31 @@
+/* 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)
Index: glibc/ports/sysdeps/arm/nptl/pthread_spin_trylock.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/pthread_spin_trylock.S 2005-11-16 13:27:43.000000000 -0500
@@ -0,0 +1,34 @@
+/* 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)
Index: glibc/ports/sysdeps/arm/nptl/pthreaddef.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/pthreaddef.h 2005-11-16 13:28:10.000000000 -0500
@@ -0,0 +1,39 @@
+/* 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))
Index: glibc/ports/sysdeps/arm/nptl/tcb-offsets.sym
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/tcb-offsets.sym 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,11 @@
+#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)
Index: glibc/ports/sysdeps/arm/nptl/tls.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/arm/nptl/tls.h 2005-11-16 13:28:26.000000000 -0500
@@ -0,0 +1,137 @@
+/* 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
+
+#include <dl-sysdep.h>
+
+#ifndef __ASSEMBLER__
+# 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.  */
+#ifndef HAVE_TLS_SUPPORT
+# error "TLS support is required."
+#endif
+
+/* Signal that TLS support is available.  */
+# define USE_TLS 1
+
+#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 <nptl/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 */
Index: glibc/ports/sysdeps/unix/arm/sysdep.S
===================================================================
--- glibc.orig/ports/sysdeps/unix/arm/sysdep.S 2005-11-16 11:12:20.000000000 -0500
+++ glibc/ports/sysdeps/unix/arm/sysdep.S 2005-11-16 13:31:31.000000000 -0500
@@ -1,4 +1,6 @@
-/* Copyright (C) 1991,92,93,94,95,96,97,98,2002,03 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002, 2003,
+   2004, 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
@@ -20,8 +22,11 @@
 #define _ERRNO_H
 #include <bits/errno.h>
 
-.globl C_SYMBOL_NAME(errno)
-.globl syscall_error
+#ifdef IS_IN_rtld
+# include <dl-sysdep.h> /* Defines RTLD_PRIVATE_ERRNO.  */
+#endif
+
+#include <tls.h>
 
 #undef syscall_error
 #ifdef NO_UNDERSCORES
@@ -37,7 +42,29 @@ syscall_error:
  moveq r0, $EAGAIN /* Yes; translate it to EAGAIN.  */
 #endif
 
-#ifdef _LIBC_REENTRANT
+#if USE___THREAD
+ mov ip, lr
+ mov r1, r0
+
+ mov r0, #0xffff0fff
+ mov lr, pc
+ sub pc, r0, #31
+
+ ldr r2, 1f
+2: ldr r2, [pc, r2]
+ str r1, [r0, r2]
+ mvn r0, #0
+ RETINSTR (, ip)
+
+1: .word errno(gottpoff) + (. - 2b - 8)
+#elif RTLD_PRIVATE_ERRNO
+ ldr r1, 1f
+0: str r0, [pc, r1]
+ mvn r0, $0
+ DO_RET(r14)
+
+1: .word C_SYMBOL_NAME(rtld_errno) - 0b - 8
+#elif defined(_LIBC_REENTRANT)
  str lr, [sp, #-4]!
  str r0, [sp, #-4]!
  bl PLTJMP(C_SYMBOL_NAME(__errno_location))
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/clone.S
===================================================================
--- glibc.orig/ports/sysdeps/unix/sysv/linux/arm/clone.S 2005-11-16 11:19:16.000000000 -0500
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/clone.S 2005-11-16 11:50:51.000000000 -0500
@@ -25,7 +25,11 @@
 #define _ERRNO_H 1
 #include <bits/errno.h>
 
-/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+#define CLONE_VM      0x00000100
+#define CLONE_THREAD  0x00010000
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+     pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
 
         .text
 ENTRY(__clone)
@@ -42,16 +46,58 @@ ENTRY(__clone)
  @ do the system call
  @ get flags
  mov r0, r2
+#ifdef RESET_PID
+ mov ip, r2
+#endif
  @ new sp is already in r1
- DO_CALL (clone, 0)
- movs a1, a1
+#ifdef __ARM_EABI__
+ stmfd sp!, {r4, r7}
+#else
+ str r4, [sp, #-8]!
+#endif
+ ldr r2, [sp, #8]
+ ldr r3, [sp, #12]
+ ldr r4, [sp, #16]
+#ifdef __ARM_EABI__
+ ldr r7, =SYS_ify(clone)
+ swi 0x0
+#else
+ swi SYS_ify(clone)
+#endif
+ cmp r0, #0
+ beq 1f
+#ifdef __ARM_EABI__
+ ldmfd sp!, {r4, r7}
+#else
+ ldr r4, [sp], #8
+#endif
  blt PLTJMP(C_SYMBOL_NAME(__syscall_error))
- RETINSTR(ne, lr)
+ RETINSTR(, lr)
 
+1:
+#ifdef RESET_PID
+ tst ip, #CLONE_THREAD
+ bne 3f
+ mov r0, #0xffff0fff
+ mov lr, pc
+ sub pc, r0, #31
+ mov r1, r0
+ tst ip, #CLONE_VM
+ movne r0, #-1
+#ifdef __ARM_EABI__
+ ldr r7, =SYS_ify(getpid)
+ swieq 0x0
+#else
+ swieq SYS_ify(getpid)
+#endif
+ str r0, [r1, #PID_OFFSET]
+ str r0, [r1, #TID_OFFSET]
+3:
+#endif
  @ pick the function arg and call address off the stack and execute
  ldr r0, [sp, #4]
  mov lr, pc
- ldr pc, [sp]
+ ldr pc, [sp], #8
 
  @ and we are done, passing the return value through r0
  b PLTJMP(_exit)
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/Makefile 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,6 @@
+ifeq ($(subdir),csu)
+# In order for unwinding to fail when it falls out of main, we need a
+# cantunwind marker.  There's one in start.S.  To make sure we reach it, add
+# unwind tables for __libc_start_main.
+CFLAGS-libc-start.c += -fexceptions
+endif
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/Makefile
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/Makefile 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,17 @@
+ifeq ($(subdir),rt)
+librt-sysdep_routines += rt-aeabi_unwind_cpp_pr1
+librt-shared-only-routines += rt-aeabi_unwind_cpp_pr1
+endif
+
+ifeq ($(subdir),nptl)
+libpthread-sysdep_routines += nptl-aeabi_unwind_cpp_pr1
+libpthread-shared-only-routines += nptl-aeabi_unwind_cpp_pr1
+
+# This test relies on compiling part of the binary with EH information,
+# part without, and unwinding through.  The .ARM.exidx tables have
+# start addresses for EH regions, but no end addresses.  Every
+# region an exception needs to propogate through must have unwind
+# information, or a previous function's unwind table may be used
+# by mistake.
+tests := $(filter-out tst-cleanupx4,$(tests))
+endif
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure 2005-11-16 13:44:22.000000000 -0500
@@ -0,0 +1,4 @@
+# This file is generated from configure.in by Autoconf.  DO NOT EDIT!
+
+libc_cv_gcc_exceptions=yes
+exceptions=-fexceptions
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure.in
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure.in 2005-11-16 13:44:05.000000000 -0500
@@ -0,0 +1,8 @@
+dnl configure fragment for NPTL and ARM/Linux EABI.
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+
+dnl The normal configure check for gcc -fexecptions fails because it can't
+dnl find __aeabi_unwind_cpp_pr0.  Work around this here; our GCC definitely
+dnl has -fexceptions.
+libc_cv_gcc_exceptions=yes
+exceptions=-fexceptions
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/nptl-aeabi_unwind_cpp_pr1.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/nptl-aeabi_unwind_cpp_pr1.c 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1 @@
+#include <aeabi_unwind_cpp_pr1.c>
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/rt-aeabi_unwind_cpp_pr1.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/rt-aeabi_unwind_cpp_pr1.c 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1 @@
+#include <aeabi_unwind_cpp_pr1.c>
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/sysdep-cancel.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/sysdep-cancel.h 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,149 @@
+/* Copyright (C) 2003, 2004, 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>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <nptl/pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+/* NOTE: We do mark syscalls with unwind annotations, for the benefit of
+   cancellation; but they're really only accurate at the point of the
+   syscall.  The ARM unwind directives are not rich enough without adding
+   a custom personality function.  */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+  .section ".text"; \
+    PSEUDO_PROLOGUE; \
+  .type __##syscall_name##_nocancel,%function; \
+  .globl __##syscall_name##_nocancel; \
+  __##syscall_name##_nocancel: \
+    DO_CALL (syscall_name, args); \
+    PSEUDO_RET; \
+  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
+  ENTRY (name); \
+    SINGLE_THREAD_P; \
+    DOARGS_##args; \
+    bne .Lpseudo_cancel; \
+    DO_CALL (syscall_name, 0); \
+    UNDOARGS_##args; \
+    cmn r0, $4096; \
+    PSEUDO_RET; \
+  .Lpseudo_cancel: \
+    .fnstart; \
+    DOCARGS_##args; /* save syscall args etc. around CENABLE.  */ \
+    CENABLE; \
+    mov ip, r0; /* put mask in safe place.  */ \
+    UNDOCARGS_##args; /* restore syscall args.  */ \
+    ldr r7, =SYS_ify (syscall_name); \
+    swi 0x0; /* do the call.  */ \
+    .fnend; /* Past here we can't easily unwind.  */ \
+    mov r7, r0; /* save syscall return value.  */ \
+    mov r0, ip; /* get mask back.  */ \
+    CDISABLE; \
+    mov r0, r7; /* retrieve return value.  */ \
+    RESTORE_LR_##args; \
+    UNDOARGS_##args; \
+    cmn r0, $4096;
+
+/* DOARGS pushes four bytes on the stack for five arguments, and nothing
+   otherwise.  In order to preserve doubleword alignment, sometimes we must
+   save an extra register.  */
+
+# define RESTART_UNWIND .fnend; .fnstart; .save {r7, lr}
+
+# define DOCARGS_0 stmfd sp!, {r7, lr}; .save {r7, lr}
+# define UNDOCARGS_0
+# define RESTORE_LR_0 ldmfd sp!, {r7, lr};
+
+# define DOCARGS_1 stmfd sp!, {r0, r1, r7, lr}; .save {r7, lr}; .pad #8
+# define UNDOCARGS_1 ldr r0, [sp], #8; RESTART_UNWIND
+# define RESTORE_LR_1 RESTORE_LR_0
+
+# define DOCARGS_2 stmfd sp!, {r0, r1, r7, lr}; .save {r7, lr}; .pad #8
+# define UNDOCARGS_2 ldmfd sp!, {r0, r1}; RESTART_UNWIND
+# define RESTORE_LR_2 RESTORE_LR_0
+
+# define DOCARGS_3 stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16
+# define UNDOCARGS_3 ldmfd sp!, {r0, r1, r2, r3}; RESTART_UNWIND
+# define RESTORE_LR_3 RESTORE_LR_0
+
+# define DOCARGS_4 stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16
+# define UNDOCARGS_4 ldmfd sp!, {r0, r1, r2, r3}; RESTART_UNWIND
+# define RESTORE_LR_4 RESTORE_LR_0
+
+# define DOCARGS_5 .save {r4}; stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}; .save {r7, lr}; .pad #20
+# define UNDOCARGS_5 ldmfd sp!, {r0, r1, r2, r3}; .fnend; .fnstart; .save {r4}; .save {r7, lr}; .pad #4
+# define RESTORE_LR_5 ldmfd sp!, {r4, r7, lr}
+
+# ifdef IS_IN_libpthread
+#  define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
+#  define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
+#  define __local_multiple_threads __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define CENABLE bl PLTJMP(__libc_enable_asynccancel)
+#  define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
+#  define __local_multiple_threads __libc_multiple_threads
+# elif defined IS_IN_librt
+#  define CENABLE bl PLTJMP(__librt_enable_asynccancel)
+#  define CDISABLE bl PLTJMP(__librt_disable_asynccancel)
+# else
+#  error Unsupported library
+# endif
+
+# if defined IS_IN_libpthread || !defined NOT_IN_libc
+#  ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+#  else
+#   define SINGLE_THREAD_P \
+  ldr ip, 1b; \
+2: \
+  ldr ip, [pc, ip]; \
+  teq ip, #0;
+#   define PSEUDO_PROLOGUE \
+  1:  .word __local_multiple_threads - 2f - 8;
+#  endif
+# else
+/*  There is no __local_multiple_threads for librt, so use the TCB.  */
+#  ifndef __ASSEMBLER__
+#   define SINGLE_THREAD_P \
+  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+   header.multiple_threads) == 0, 1)
+#  else
+#   define PSEUDO_PROLOGUE
+#   define SINGLE_THREAD_P \
+  stmfd sp!, {r0, lr}; \
+  bl __aeabi_read_tp; \
+  ldr ip, [r0, #MULTIPLE_THREADS_OFFSET]; \
+  ldmfd sp!, {r0, lr}; \
+  teq ip, #0
+#   define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* For rtld, et cetera.  */
+# define SINGLE_THREAD_P 1
+# define NO_CANCELLATION 1
+
+#endif
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-forcedunwind.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-forcedunwind.c 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,113 @@
+/* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <[hidden email]>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unwind.h>
+#include <pthreadP.h>
+
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
+static _Unwind_Reason_Code (*libgcc_s_personality)
+  (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
+static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
+  (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
+static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *);
+
+void
+pthread_cancel_init (void)
+{
+  void *resume, *personality, *forcedunwind, *getcfa;
+  void *handle;
+
+  if (__builtin_expect (libgcc_s_getcfa != NULL, 1))
+    return;
+
+  handle = __libc_dlopen ("libgcc_s.so.1");
+
+  if (handle == NULL
+      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
+      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL
+      || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind"))
+ == NULL
+      || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL
+#ifdef ARCH_CANCEL_INIT
+      || ARCH_CANCEL_INIT (handle)
+#endif
+      )
+    __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n");
+
+  libgcc_s_resume = resume;
+  libgcc_s_personality = personality;
+  libgcc_s_forcedunwind = forcedunwind;
+  libgcc_s_getcfa = getcfa;
+}
+
+/* It's vitally important that _Unwind_Resume not have a stack frame; the
+   ARM unwinder relies on register state at entrance.  So we write this in
+   assembly.  */
+
+asm (
+" .globl _Unwind_Resume\n"
+" .type _Unwind_Resume, %function\n"
+"_Unwind_Resume:\n"
+" stmfd sp!, {r4, r5, r6, lr}\n"
+" ldr r4, 1f\n"
+" ldr r5, 2f\n"
+"3: add r4, pc, r4\n"
+" ldr r3, [r4, r5]\n"
+" mov r6, r0\n"
+" cmp r3, #0\n"
+" beq 4f\n"
+"5: mov r0, r6\n"
+" ldmfd sp!, {r4, r5, r6, lr}\n"
+" bx r3\n"
+"4: bl pthread_cancel_init\n"
+" ldr r3, [r4, r5]\n"
+" b 5b\n"
+"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8\n"
+"2: .word libgcc_s_resume(GOTOFF)\n"
+" .size _Unwind_Resume, .-_Unwind_Resume\n"
+);
+
+_Unwind_Reason_Code
+__gcc_personality_v0 (_Unwind_State state,
+      struct _Unwind_Exception *ue_header,
+      struct _Unwind_Context *context)
+{
+  if (__builtin_expect (libgcc_s_personality == NULL, 0))
+    pthread_cancel_init ();
+  return libgcc_s_personality (state, ue_header, context);
+}
+
+_Unwind_Reason_Code
+_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop,
+      void *stop_argument)
+{
+  if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0))
+    pthread_cancel_init ();
+  return libgcc_s_forcedunwind (exc, stop, stop_argument);
+}
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  if (__builtin_expect (libgcc_s_getcfa == NULL, 0))
+    pthread_cancel_init ();
+  return libgcc_s_getcfa (context);
+}
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-resume.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-resume.c 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,82 @@
+/* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <[hidden email]>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unwind.h>
+
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
+static _Unwind_Reason_Code (*libgcc_s_personality)
+  (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
+
+static void init (void) __attribute_used__;
+
+static void
+init (void)
+{
+  void *resume, *personality;
+  void *handle;
+
+  handle = __libc_dlopen ("libgcc_s.so.1");
+
+  if (handle == NULL
+      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
+      || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL)
+    __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n");
+
+  libgcc_s_resume = resume;
+  libgcc_s_personality = personality;
+}
+
+/* It's vitally important that _Unwind_Resume not have a stack frame; the
+   ARM unwinder relies on register state at entrance.  So we write this in
+   assembly.  */
+
+asm (
+" .globl _Unwind_Resume\n"
+" .type _Unwind_Resume, %function\n"
+"_Unwind_Resume:\n"
+" stmfd sp!, {r4, r5, r6, lr}\n"
+" ldr r4, 1f\n"
+" ldr r5, 2f\n"
+"3: add r4, pc, r4\n"
+" ldr r3, [r4, r5]\n"
+" mov r6, r0\n"
+" cmp r3, #0\n"
+" beq 4f\n"
+"5: mov r0, r6\n"
+" ldmfd sp!, {r4, r5, r6, lr}\n"
+" bx r3\n"
+"4: bl init\n"
+" ldr r3, [r4, r5]\n"
+" b 5b\n"
+"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8\n"
+"2: .word libgcc_s_resume(GOTOFF)\n"
+" .size _Unwind_Resume, .-_Unwind_Resume\n"
+);
+
+_Unwind_Reason_Code
+__gcc_personality_v0 (_Unwind_State state,
+      struct _Unwind_Exception *ue_header,
+      struct _Unwind_Context *context)
+{
+  if (__builtin_expect (libgcc_s_personality == NULL, 0))
+    init ();
+  return libgcc_s_personality (state, ue_header, context);
+}
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,274 @@
+/* Header file for the ARM EABI unwinder
+   Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
+   Contributed by Paul Brook
+
+   This file is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   In addition to the permissions in the GNU General Public License, the
+   Free Software Foundation gives you unlimited permission to link the
+   compiled version of this file into combinations with other programs,
+   and to distribute those combinations without any restriction coming
+   from the use of this file.  (The General Public License restrictions
+   do apply in other respects; for example, they cover modification of
+   the file, and distribution when not linked into a combine
+   executable.)
+
+   This file 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
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* Language-independent unwinder header public defines.  This contains both
+   ABI defined objects, and GNU support routines.  */
+
+#ifndef UNWIND_ARM_H
+#define UNWIND_ARM_H
+
+#define __ARM_EABI_UNWINDER__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
+  typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
+  typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
+  typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
+  typedef _Unwind_Word _uw;
+  typedef unsigned _uw64 __attribute__((mode(__DI__)));
+  typedef unsigned _uw16 __attribute__((mode(__HI__)));
+  typedef unsigned _uw8 __attribute__((mode(__QI__)));
+
+  typedef enum
+    {
+      _URC_OK = 0,       /* operation completed successfully */
+      _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+      _URC_END_OF_STACK = 5,
+      _URC_HANDLER_FOUND = 6,
+      _URC_INSTALL_CONTEXT = 7,
+      _URC_CONTINUE_UNWIND = 8,
+      _URC_FAILURE = 9   /* unspecified failure of some kind */
+    }
+  _Unwind_Reason_Code;
+
+  typedef enum
+    {
+      _US_VIRTUAL_UNWIND_FRAME = 0,
+      _US_UNWIND_FRAME_STARTING = 1,
+      _US_UNWIND_FRAME_RESUME = 2,
+      _US_ACTION_MASK = 3,
+      _US_FORCE_UNWIND = 8,
+      _US_END_OF_STACK = 16
+    }
+  _Unwind_State;
+
+  /* Provided only for for compatibility with existing code.  */
+  typedef int _Unwind_Action;
+#define _UA_SEARCH_PHASE 1
+#define _UA_CLEANUP_PHASE 2
+#define _UA_HANDLER_FRAME 4
+#define _UA_FORCE_UNWIND 8
+#define _UA_END_OF_STACK 16
+#define _URC_NO_REASON _URC_OK
+
+  typedef struct _Unwind_Control_Block _Unwind_Control_Block;
+  typedef struct _Unwind_Context _Unwind_Context;
+  typedef _uw _Unwind_EHT_Header;
+
+
+  /* UCB: */
+
+  struct _Unwind_Control_Block
+    {
+#ifdef _LIBC
+      /* For the benefit of code which assumes this is a scalar.  All
+ glibc ever does is clear it.  */
+      _uw64 exception_class;
+#else
+      char exception_class[8];
+#endif
+      void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
+      /* Unwinder cache, private fields for the unwinder's use */
+      struct
+ {
+  _uw reserved1;  /* Forced unwind stop fn, 0 if not forced */
+  _uw reserved2;  /* Personality routine address */
+  _uw reserved3;  /* Saved callsite address */
+  _uw reserved4;  /* Forced unwind stop arg */
+  _uw reserved5;
+ }
+      unwinder_cache;
+      /* Propagation barrier cache (valid after phase 1): */
+      struct
+ {
+  _uw sp;
+  _uw bitpattern[5];
+ }
+      barrier_cache;
+      /* Cleanup cache (preserved over cleanup): */
+      struct
+ {
+  _uw bitpattern[4];
+ }
+      cleanup_cache;
+      /* Pr cache (for pr's benefit): */
+      struct
+ {
+  _uw fnstart; /* function start address */
+  _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
+  _uw additional; /* additional data */
+  _uw reserved1;
+ }
+      pr_cache;
+      long long int :0; /* Force alignment to 8-byte boundary */
+    };
+
+  /* Virtual Register Set*/
+
+  typedef enum
+    {
+      _UVRSC_CORE = 0,      /* integer register */
+      _UVRSC_VFP = 1,       /* vfp */
+      _UVRSC_FPA = 2,       /* fpa */
+      _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
+      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
+    }
+  _Unwind_VRS_RegClass;
+
+  typedef enum
+    {
+      _UVRSD_UINT32 = 0,
+      _UVRSD_VFPX = 1,
+      _UVRSD_FPAX = 2,
+      _UVRSD_UINT64 = 3,
+      _UVRSD_FLOAT = 4,
+      _UVRSD_DOUBLE = 5
+    }
+  _Unwind_VRS_DataRepresentation;
+
+  typedef enum
+    {
+      _UVRSR_OK = 0,
+      _UVRSR_NOT_IMPLEMENTED = 1,
+      _UVRSR_FAILED = 2
+    }
+  _Unwind_VRS_Result;
+
+  /* Frame unwinding state.  */
+  typedef struct
+    {
+      /* The current word (bytes packed msb first).  */
+      _uw data;
+      /* Pointer to the next word of data.  */
+      _uw *next;
+      /* The number of bytes left in this word.  */
+      _uw8 bytes_left;
+      /* The number of words pointed to by ptr.  */
+      _uw8 words_left;
+    }
+  __gnu_unwind_state;
+
+  typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
+      _Unwind_Control_Block *, _Unwind_Context *);
+
+  _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
+                                     _uw, _Unwind_VRS_DataRepresentation,
+                                     void *);
+
+  _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
+                                     _uw, _Unwind_VRS_DataRepresentation,
+                                     void *);
+
+  _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
+                                     _uw, _Unwind_VRS_DataRepresentation);
+
+
+  /* Support functions for the PR.  */
+#define _Unwind_Exception _Unwind_Control_Block
+  typedef char _Unwind_Exception_Class[8];
+
+  void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
+  _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
+
+  /* These two should never be used.  */
+  _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
+  _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
+
+  /* Interface functions: */
+  _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
+  void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
+  _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
+
+  typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
+       (int, _Unwind_Action, _Unwind_Exception_Class,
+ _Unwind_Control_Block *, struct _Unwind_Context *, void *);
+  _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
+    _Unwind_Stop_Fn, void *);
+  _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
+  void _Unwind_Complete(_Unwind_Control_Block *ucbp);
+  void _Unwind_DeleteException (_Unwind_Exception *);
+
+  _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
+  _Unwind_Context *);
+  _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
+    __gnu_unwind_state *);
+
+  /* Decode an R_ARM_TARGET2 relocation.  */
+  static inline _Unwind_Word
+  _Unwind_decode_target2 (_Unwind_Word ptr)
+    {
+      _Unwind_Word tmp;
+
+      tmp = *(_Unwind_Word *) ptr;
+      /* Zero values are always NULL.  */
+      if (!tmp)
+ return 0;
+
+#if defined(linux) || defined(__NetBSD__)
+      /* Pc-relative indirect.  */
+      tmp += ptr;
+      tmp = *(_Unwind_Word *) tmp;
+#elif defined(__symbian__)
+      /* Absolute pointer.  Nothing more to do.  */
+#else
+      /* Pc-relative pointer.  */
+      tmp += ptr;
+#endif
+      return tmp;
+    }
+
+  static inline _Unwind_Word
+  _Unwind_GetGR (_Unwind_Context *context, int regno)
+    {
+      _uw val;
+      _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+      return val;
+    }
+
+  /* Return the address of the instruction, not the actual IP value.  */
+#define _Unwind_GetIP(context) \
+  (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+
+  static inline void
+  _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
+    {
+      _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+    }
+
+  /* The dwarf unwinder doesn't understand arm/thumb state.  We assume the
+     landing pad uses the same instruction set as the call site.  */
+#define _Unwind_SetIP(context, val) \
+  _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
+
+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
+#endif /* defined UNWIND_ARM_H */
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/sigrestorer.S
===================================================================
--- glibc.orig/ports/sysdeps/unix/sysv/linux/arm/eabi/sigrestorer.S 2005-11-16 11:41:14.000000000 -0500
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/sigrestorer.S 2005-11-16 11:54:38.000000000 -0500
@@ -20,16 +20,35 @@
 
 /* If no SA_RESTORER function was specified by the application we use
    one of these.  This avoids the need for the kernel to synthesise a return
-   instruction on the stack, which would involve expensive cache flushes. */
+   instruction on the stack, which would involve expensive cache flushes.
 
+   Nowadays (2.6 series, and somewhat earlier) the kernel uses a high page
+   for signal trampolines, so the cache flushes are not an issue.  But since
+   we do not have a vDSO, continue to use these so that we can provide
+   unwind information.
+
+   Start the unwind tables at least one instruction before the signal
+   trampoline, because the unwinder will assume we are returning after
+   a call site.  */
+
+ .fnstart
+ .save {r0-r15}
+ .pad #12
+ nop
 ENTRY(__default_sa_restorer)
  mov r7, $SYS_ify(sigreturn)
  swi 0x0
+ .fnend
 
 #ifdef __NR_rt_sigreturn
 
+ .fnstart
+ .save {r0-r15}
+ .pad #168
+ nop
 ENTRY(__default_rt_sa_restorer)
  mov r7, $SYS_ify(rt_sigreturn)
  swi 0x0
+ .fnend
 
 #endif
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/socket.S
===================================================================
--- glibc.orig/ports/sysdeps/unix/sysv/linux/arm/eabi/socket.S 2005-11-16 11:19:16.000000000 -0500
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/socket.S 2005-11-16 11:50:51.000000000 -0500
@@ -33,19 +33,19 @@
    The .S files for the other calls just #define socket and #include this.  */
 
 #ifndef __socket
-#ifndef NO_WEAK_ALIAS
-#define __socket P(__,socket)
-#else
-#define __socket socket
-#endif
+# ifndef NO_WEAK_ALIAS
+#  define __socket P(__,socket)
+# else
+#  define __socket socket
+# endif
 #endif
 
-#define PUSHARGS_1 str a1, [sp, $-8]!
-#define PUSHARGS_2 stmfd sp!, {a1, a2}
-#define PUSHARGS_3 stmfd sp!, {a1, a2, a3, a4} /* a4 pushed for padding */
-#define PUSHARGS_4 stmfd sp!, {a1, a2, a3, a4}
-#define PUSHARGS_5 stmfd sp!, {a1, a2, a3, a4} /* Caller has already pushed arg 5 */
-#define PUSHARGS_6 stmfd sp!, {a1, a2, a3, a4}
+#define PUSHARGS_1 str a1, [sp, $-8]!; .pad #8
+#define PUSHARGS_2 stmfd sp!, {a1, a2}; .pad #8
+#define PUSHARGS_3 stmfd sp!, {a1, a2, a3, a4}; .pad #16 /* a4 pushed for padding */
+#define PUSHARGS_4 stmfd sp!, {a1, a2, a3, a4}; .pad #16
+#define PUSHARGS_5 stmfd sp!, {a1, a2, a3, a4}; .pad #16 /* Caller has already pushed arg 5 */
+#define PUSHARGS_6 stmfd sp!, {a1, a2, a3, a4}; .pad #16
 
 #define POPARGS_1 add sp, sp, #8
 #define POPARGS_2 add sp, sp, #8
@@ -64,6 +64,8 @@
 
 .globl __socket
 ENTRY (__socket)
+ .fnstart
+
  /* This code previously moved sp into ip and stored the args using
    stmdb ip!, {a1-a4}.  It did not modify sp, so the stack never had
    to be restored after the syscall completed.  It saved an
@@ -98,11 +100,12 @@ ENTRY (__socket)
 #if defined NEED_CANCELLATION && defined CENABLE
 1:
  stmfd sp!, {r7, lr}
+ .save {r7, lr}
  CENABLE
  mov ip, r0
 
  mov r0, #P(SOCKOP_,socket)
- add r1, sp, #4
+ add r1, sp, #8
  mov r7, #SYS_ify(socketcall)
  swi 0x0
 
@@ -120,6 +123,7 @@ ENTRY (__socket)
  b PLTJMP(SYSCALL_ERROR)
 #endif
 
+ .fnend
 PSEUDO_END (__socket)
 
 #ifndef NO_WEAK_ALIAS
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h
===================================================================
--- glibc.orig/ports/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h 2005-11-16 11:19:16.000000000 -0500
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/eabi/sysdep.h 2005-11-16 11:50:51.000000000 -0500
@@ -48,6 +48,11 @@
      : "memory"); \
        _a1; })
 
+/* For EABI, non-constant syscalls are actually pretty easy...  */
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)          \
+  INTERNAL_SYSCALL_RAW (number, err, nr, args)
+
 /* We must save and restore r7 (call-saved) for the syscall number.
    We never make function calls from inside here (only potentially
    signal handlers), so we do not bother with doubleword alignment.
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/Versions
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/Versions 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,6 @@
+libc {
+  GLIBC_PRIVATE {
+    # A copy of sigaction lives in NPTL, and needs these.
+    __default_sa_restorer; __default_rt_sa_restorer;
+  }
+}
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h 2005-11-16 11:50:51.000000000 -0500
@@ -0,0 +1,95 @@
+/* Copyright (C) 2002, 2003, 2004, 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 <stdint.h>
+#include <sysdep.h>
+
+
+typedef int8_t atomic8_t;
+typedef uint8_t uatomic8_t;
+typedef int_fast8_t atomic_fast8_t;
+typedef uint_fast8_t uatomic_fast8_t;
+
+typedef int32_t atomic32_t;
+typedef uint32_t uatomic32_t;
+typedef int_fast32_t atomic_fast32_t;
+typedef uint_fast32_t uatomic_fast32_t;
+
+typedef intptr_t atomicptr_t;
+typedef uintptr_t uatomicptr_t;
+typedef intmax_t atomic_max_t;
+typedef uintmax_t uatomic_max_t;
+
+void __arm_link_error (void);
+
+#define atomic_exchange_acq(mem, newvalue)      \
+  ({ __typeof (*mem) result;      \
+     if (sizeof (*mem) == 1)      \
+       __asm__ __volatile__ ("swpb %0, %1, [%2]"      \
+     : "=&r,&r" (result)      \
+     : "r,0" (newvalue), "r,r" (mem) : "memory");     \
+     else if (sizeof (*mem) == 4)      \
+       __asm__ __volatile__ ("swp %0, %1, [%2]"      \
+     : "=&r,&r" (result)      \
+     : "r,0" (newvalue), "r,r" (mem) : "memory");     \
+     else      \
+       {      \
+ result = 0;      \
+ abort ();      \
+       }      \
+     result; })
+
+/* Atomic compare and exchange.  This sequence relies on the kernel to
+   provide a compare and exchange operation which is atomic on the
+   current architecture, either via cleverness on pre-ARMv6 or via
+   ldrex / strex on ARMv6.  */
+
+#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
+  ({ __arm_link_error (); oldval; })
+
+#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
+  ({ __arm_link_error (); oldval; })
+
+/* It doesn't matter what register is used for a_oldval2, but we must
+   specify one to work around GCC PR rtl-optimization/21223.  Otherwise
+   it may cause a_oldval or a_tmp to be moved to a different register.  */
+
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+  ({ register __typeof (oldval) a_oldval asm ("r0");      \
+     register __typeof (oldval) a_newval asm ("r1") = (newval);      \
+     register __typeof (mem) a_ptr asm ("r2") = (mem);      \
+     register __typeof (oldval) a_tmp asm ("r3");      \
+     register __typeof (oldval) a_oldval2 asm ("r4") = (oldval);      \
+     __asm__ __volatile__      \
+     ("0:\tldr\t%1,[%3]\n\t"      \
+      "cmp\t%1, %4\n\t"      \
+      "bne\t1f\n\t"      \
+      "mov\t%0, %4\n\t"      \
+      "mov\t%1, #0xffff0fff\n\t"      \
+      "mov\tlr, pc\n\t"      \
+      "add\tpc, %1, #(0xffff0fc0 - 0xffff0fff)\n\t"      \
+      "bcc\t0b\n\t"      \
+      "mov\t%1, %4\n\t"      \
+      "1:"      \
+      : "=&r" (a_oldval), "=&r" (a_tmp)      \
+      : "r" (a_newval), "r" (a_ptr), "r" (a_oldval2)      \
+      : "ip", "lr", "cc", "memory");      \
+     a_tmp; })
+
+#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
+  ({ __arm_link_error (); oldval; })
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h 2005-11-16 13:52:56.000000000 -0500
@@ -0,0 +1,157 @@
+/* Copyright (C) 2002, 2003, 2004, 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 _BITS_PTHREADTYPES_H
+#define _BITS_PTHREADTYPES_H 1
+
+#define __SIZEOF_PTHREAD_ATTR_T 36
+#define __SIZEOF_PTHREAD_MUTEX_T 24
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCK_T 32
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIER_T 20
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+
+/* Thread identifiers.  The structure of the attribute type is not
+   exposed on purpose.  */
+typedef unsigned long int pthread_t;
+
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_ATTR_T];
+  long int __align;
+} pthread_attr_t;
+
+
+/* Data structures for mutex handling.  The structure of the attribute
+   type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __count;
+    int __owner;
+    /* KIND must stay at this position in the structure to maintain
+       binary compatibility.  */
+    int __kind;
+    unsigned int __nusers;
+    int __spins;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_MUTEX_T];
+  long int __align;
+} pthread_mutex_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+  long int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __futex;
+    unsigned long long int __total_seq;
+    unsigned long long int __wakeup_seq;
+    unsigned long long int __woken_seq;
+    void *__mutex;
+    unsigned int __nwaiters;
+    unsigned int __broadcast_seq;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_COND_T];
+  long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+  long int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int pthread_once_t;
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Data structure for read-write lock variable handling.  The
+   structure of the attribute type is not exposed on purpose.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __nr_readers;
+    unsigned int __readers_wakeup;
+    unsigned int __writer_wakeup;
+    unsigned int __nr_readers_queued;
+    unsigned int __nr_writers_queued;
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned int __flags;
+    int __writer;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+  long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+  long int __align;
+} pthread_rwlockattr_t;
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* POSIX spinlock data type.  */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type.  The structure of the type is
+   deliberately not exposed.  */
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIER_T];
+  long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+  int __align;
+} pthread_barrierattr_t;
+#endif
+
+
+#endif /* bits/pthreadtypes.h */
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/semaphore.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/semaphore.h 2005-11-16 13:53:02.000000000 -0500
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002, 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 _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
+#endif
+
+
+#define __SIZEOF_SEM_T 16
+
+
+/* Value returned if `sem_open' failed.  */
+#define SEM_FAILED      ((sem_t *) 0)
+
+/* Maximum value the semaphore can have.  */
+#define SEM_VALUE_MAX   ((int) ((~0u) >> 1))
+
+
+typedef union
+{
+  char __size[__SIZEOF_SEM_T];
+  long int __align;
+} sem_t;
Index: glibc/ports/sysdeps/unix/sysv/linux/arm/nptl/clone.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/ports/sy