* sysdeps/arm/bits/setjmp.h, sysdeps/arm/fpu/bits/setjmp.h: Update
authorDaniel Jacobowitz <dan@codesourcery.com>
Wed, 16 Nov 2005 19:03:42 +0000 (19:03 +0000)
committerDaniel Jacobowitz <dan@codesourcery.com>
Wed, 16 Nov 2005 19:03:42 +0000 (19:03 +0000)
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.

41 files changed:
ChangeLog.arm
sysdeps/arm/bits/setjmp.h
sysdeps/arm/fpu/bits/setjmp.h
sysdeps/arm/nptl/Makefile [new file with mode: 0644]
sysdeps/arm/nptl/jmpbuf-unwind.h [new file with mode: 0644]
sysdeps/arm/nptl/pthread_spin_lock.S [new file with mode: 0644]
sysdeps/arm/nptl/pthread_spin_trylock.S [new file with mode: 0644]
sysdeps/arm/nptl/pthreaddef.h [new file with mode: 0644]
sysdeps/arm/nptl/tcb-offsets.sym [new file with mode: 0644]
sysdeps/arm/nptl/tls.h [new file with mode: 0644]
sysdeps/unix/arm/sysdep.S
sysdeps/unix/sysv/linux/arm/clone.S
sysdeps/unix/sysv/linux/arm/eabi/Makefile [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/Makefile [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/configure [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/configure.in [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/nptl-aeabi_unwind_cpp_pr1.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/rt-aeabi_unwind_cpp_pr1.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/sysdep-cancel.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-forcedunwind.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-resume.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/eabi/sigrestorer.S
sysdeps/unix/sysv/linux/arm/eabi/socket.S
sysdeps/unix/sysv/linux/arm/eabi/sysdep.h
sysdeps/unix/sysv/linux/arm/nptl/Versions [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/bits/semaphore.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/clone.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/createthread.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/fork.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/nptl/vfork.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/arm/sigaction.c
sysdeps/unix/sysv/linux/arm/socket.S
sysdeps/unix/sysv/linux/arm/sysdep.h
sysdeps/unix/sysv/linux/arm/vfork.S

index 21e15ce..795b363 100644 (file)
@@ -1,5 +1,63 @@
 2005-11-16  Daniel Jacobowitz  <dan@codesourcery.com>
 
+       * 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.
+
+2005-11-16  Daniel Jacobowitz  <dan@codesourcery.com>
+
        * sysdeps/arm/dl-machine.h (CLEAR_CACHE): Use INTERNAL_SYSCALL_ARM.
        * sysdeps/unix/sysv/linux/arm/brk.c (__brk): Use INLINE_SYSCALL.
        * sysdeps/unix/sysv/linux/arm/clone.S (__clone): Use DO_CALL.
index e0a4657..9b74906 100644 (file)
@@ -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
 
 /* 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 dd85243..0a19d2c 100644 (file)
@@ -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
 
 /* 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
diff --git a/sysdeps/arm/nptl/Makefile b/sysdeps/arm/nptl/Makefile
new file mode 100644 (file)
index 0000000..0300693
--- /dev/null
@@ -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
diff --git a/sysdeps/arm/nptl/jmpbuf-unwind.h b/sysdeps/arm/nptl/jmpbuf-unwind.h
new file mode 100644 (file)
index 0000000..f05e27f
--- /dev/null
@@ -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)
diff --git a/sysdeps/arm/nptl/pthread_spin_lock.S b/sysdeps/arm/nptl/pthread_spin_lock.S
new file mode 100644 (file)
index 0000000..bd6adf7
--- /dev/null
@@ -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)
diff --git a/sysdeps/arm/nptl/pthread_spin_trylock.S b/sysdeps/arm/nptl/pthread_spin_trylock.S
new file mode 100644 (file)
index 0000000..8593150
--- /dev/null
@@ -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)
diff --git a/sysdeps/arm/nptl/pthreaddef.h b/sysdeps/arm/nptl/pthreaddef.h
new file mode 100644 (file)
index 0000000..783828a
--- /dev/null
@@ -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))
diff --git a/sysdeps/arm/nptl/tcb-offsets.sym b/sysdeps/arm/nptl/tcb-offsets.sym
new file mode 100644 (file)
index 0000000..92cc441
--- /dev/null
@@ -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)
diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h
new file mode 100644 (file)
index 0000000..26ef709
--- /dev/null
@@ -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 4810805..dcb427e 100644 (file)
@@ -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
 #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 b46281c..6c8f8e8 100644 (file)
 #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)
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/Makefile b/sysdeps/unix/sysv/linux/arm/eabi/Makefile
new file mode 100644 (file)
index 0000000..d3c02a2
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/Makefile b/sysdeps/unix/sysv/linux/arm/eabi/nptl/Makefile
new file mode 100644 (file)
index 0000000..ef8076c
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure b/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure
new file mode 100644 (file)
index 0000000..5182699
--- /dev/null
@@ -0,0 +1,4 @@
+# This file is generated from configure.in by Autoconf.  DO NOT EDIT!
+
+libc_cv_gcc_exceptions=yes
+exceptions=-fexceptions
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure.in b/sysdeps/unix/sysv/linux/arm/eabi/nptl/configure.in
new file mode 100644 (file)
index 0000000..22f6f4b
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/nptl-aeabi_unwind_cpp_pr1.c b/sysdeps/unix/sysv/linux/arm/eabi/nptl/nptl-aeabi_unwind_cpp_pr1.c
new file mode 100644 (file)
index 0000000..7b83522
--- /dev/null
@@ -0,0 +1 @@
+#include <aeabi_unwind_cpp_pr1.c>
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/rt-aeabi_unwind_cpp_pr1.c b/sysdeps/unix/sysv/linux/arm/eabi/nptl/rt-aeabi_unwind_cpp_pr1.c
new file mode 100644 (file)
index 0000000..7b83522
--- /dev/null
@@ -0,0 +1 @@
+#include <aeabi_unwind_cpp_pr1.c>
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/sysdep-cancel.h b/sysdeps/unix/sysv/linux/arm/eabi/nptl/sysdep-cancel.h
new file mode 100644 (file)
index 0000000..5e89399
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-forcedunwind.c
new file mode 100644 (file)
index 0000000..ca1cc8d
--- /dev/null
@@ -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 <jakub@redhat.com>.
+
+   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);
+}
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind-resume.c
new file mode 100644 (file)
index 0000000..a9c9d18
--- /dev/null
@@ -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 <jakub@redhat.com>.
+
+   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);
+}
diff --git a/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h b/sysdeps/unix/sysv/linux/arm/eabi/nptl/unwind.h
new file mode 100644 (file)
index 0000000..d625fb2
--- /dev/null
@@ -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 d68c8a5..543d48c 100644 (file)
 
 /* 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 7fa2b1e..f614213 100644 (file)
    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 84a4f04..7f5ded5 100644 (file)
                     : "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.
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/Versions b/sysdeps/unix/sysv/linux/arm/nptl/Versions
new file mode 100644 (file)
index 0000000..c74a06f
--- /dev/null
@@ -0,0 +1,6 @@
+libc {
+  GLIBC_PRIVATE {
+    # A copy of sigaction lives in NPTL, and needs these.
+    __default_sa_restorer; __default_rt_sa_restorer;
+  }
+}
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h b/sysdeps/unix/sysv/linux/arm/nptl/bits/atomic.h
new file mode 100644 (file)
index 0000000..71ed714
--- /dev/null
@@ -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; })
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h b/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h
new file mode 100644 (file)
index 0000000..fb0fe3f
--- /dev/null
@@ -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 */
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/bits/semaphore.h b/sysdeps/unix/sysv/linux/arm/nptl/bits/semaphore.h
new file mode 100644 (file)
index 0000000..3fc647d
--- /dev/null
@@ -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;
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/clone.S b/sysdeps/unix/sysv/linux/arm/nptl/clone.S
new file mode 100644 (file)
index 0000000..23750b3
--- /dev/null
@@ -0,0 +1,3 @@
+#define RESET_PID
+#include <tcb-offsets.h>
+#include "../clone.S"
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/createthread.c b/sysdeps/unix/sysv/linux/arm/nptl/createthread.c
new file mode 100644 (file)
index 0000000..01bd8ce
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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.  */
+
+/* Value passed to 'clone' for initialization of the thread register.  */
+#define TLS_VALUE (pd + 1)
+
+/* Get the real implementation.         */
+#include <nptl/sysdeps/pthread/createthread.c>
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/fork.c b/sysdeps/unix/sysv/linux/arm/nptl/fork.c
new file mode 100644 (file)
index 0000000..310676f
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Phil Blundell <pb@nexus.co.uk>, 2005
+
+   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 <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK()                                                    \
+  INLINE_SYSCALL (clone, 5,                                            \
+                 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,  \
+                 NULL, NULL, NULL, &THREAD_SELF->tid)
+
+#include <nptl/sysdeps/unix/sysv/linux/fork.c>
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.c b/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.c
new file mode 100644 (file)
index 0000000..e0643a9
--- /dev/null
@@ -0,0 +1,118 @@
+/* low level locking for pthread library.  Generic futex-using version.
+   Copyright (C) 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.  */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+
+int
+__lll_timedlock_wait (int *futex, const struct timespec *abstime)
+{
+  struct timespec rt;
+
+  /* Reject invalid timeouts.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  /* Upgrade the lock.  */
+  if (atomic_exchange_acq (futex, 2) == 0)
+    return 0;
+
+  do
+    {
+      struct timeval tv;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+       {
+         rt.tv_nsec += 1000000000;
+         --rt.tv_sec;
+       }
+
+      /* Already timed out?  */
+      if (rt.tv_sec < 0)
+       return ETIMEDOUT;
+
+      lll_futex_timed_wait (futex, 2, &rt);
+    }
+  while (atomic_exchange_acq (futex, 2) != 0);
+
+  return 0;
+}
+
+
+/* These don't get included in libc.so  */
+#ifdef IS_IN_libpthread
+int
+lll_unlock_wake_cb (int *futex)
+{
+  int val = atomic_exchange_rel (futex, 0);
+
+  if (__builtin_expect (val > 1, 0))
+    lll_futex_wake (futex, 1);
+
+  return 0;
+}
+
+
+int
+__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
+{
+  int tid;
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  /* Repeat until thread terminated.  */
+  while ((tid = *tidp) != 0)
+    {
+      struct timeval tv;
+      struct timespec rt;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+       {
+         rt.tv_nsec += 1000000000;
+         --rt.tv_sec;
+       }
+
+      /* Already timed out?  */
+      if (rt.tv_sec < 0)
+       return ETIMEDOUT;
+
+      /* Wait until thread terminates.  */
+      if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT)
+       return ETIMEDOUT;
+    }
+
+  return 0;
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h b/sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h
new file mode 100644 (file)
index 0000000..7f1c291
--- /dev/null
@@ -0,0 +1,268 @@
+/* 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 Libr   \ary; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H        1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+#include <sysdep.h>
+
+#define FUTEX_WAIT             0
+#define FUTEX_WAKE             1
+#define FUTEX_REQUEUE          3
+#define FUTEX_CMP_REQUEUE      4
+#define FUTEX_WAKE_OP          5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE  ((4 << 24) | 1)
+
+/* Initializer for compatibility lock. */
+#define LLL_MUTEX_LOCK_INITIALIZER (0)
+
+#define lll_futex_wait(futexp, val) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,                               \
+                             (futexp), FUTEX_WAIT, (val), 0);                \
+    __ret;                                                                   \
+  })
+
+#define lll_futex_timed_wait(futexp, val, timespec) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,                               \
+                             (futexp), FUTEX_WAIT, (val), (timespec));       \
+    __ret;                                                                   \
+  })
+
+#define lll_futex_wake(futexp, nr) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,                               \
+                             (futexp), FUTEX_WAKE, (nr), 0);                 \
+    __ret;                                                                   \
+  })
+
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,                               \
+                             (futexp), FUTEX_CMP_REQUEUE, (nr_wake),         \
+                             (nr_move), (mutex), (val));                     \
+    __ret;                                                                   \
+  })
+
+
+/* Returns non-zero if error happened, zero if success.  */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 6,                               \
+                             (futexp), FUTEX_WAKE_OP, (nr_wake),             \
+                             (nr_wake2), (futexp2),                          \
+                             FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
+    __ret;                                                                   \
+  })
+
+
+static inline int __attribute__((always_inline))
+__lll_mutex_trylock (int *futex)
+{
+  int flag = 1, old;
+  asm volatile (
+    "\tswp     %[old], %[flag], [%[futex]]     @ try to take the lock\n"
+    "\tcmp     %[old], #1                      @ check old lock value\n"
+    "\tmovlo   %[flag], #0                     @ if we got it, return 0\n"
+    "\tswphi   %[flag], %[old], [%[futex]]     @ if it was contested,\n"
+    "                                          @ restore the contested flag,\n"
+    "                                          @ and check whether that won."
+    : [futex] "+&r" (futex), [flag] "+&r" (flag), [old] "=&r" (old)
+    : : "memory" );
+
+  return flag;
+}
+#define lll_mutex_trylock(lock)        __lll_mutex_trylock (&(lock))
+
+
+static inline int __attribute__((always_inline))
+__lll_mutex_cond_trylock (int *futex)
+{
+  int flag = 2, old;
+  asm volatile (
+    "\tswp     %[old], %[flag], [%[futex]]     @ try to take the lock\n"
+    "\tcmp     %[old], #1                      @ check old lock value\n"
+    "\tmovlo   %[flag], #0                     @ if we got it, return 0\n"
+    "\tswphi   %[flag], %[old], [%[futex]]     @ if it was contested,\n"
+    "                                          @ restore the contested flag,\n"
+    "                                          @ and check whether that won."
+    : [futex] "+&r" (futex), [flag] "+&r" (flag), [old] "=&r" (old)
+    : : "memory" );
+
+  return flag;
+}
+#define lll_mutex_cond_trylock(lock)   __lll_mutex_cond_trylock (&(lock))
+
+
+extern void __lll_mutex_lock_outlined (int *futex) attribute_hidden;
+
+static inline void __attribute__((always_inline))
+__lll_mutex_lock (int *futex)
+{
+  int val = atomic_exchange_acq (futex, 1);
+
+  if (__builtin_expect (val != 0, 0))
+    {
+      while (atomic_exchange_acq (futex, 2) != 0)
+       lll_futex_wait (futex, 2);
+    }
+}
+#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
+
+
+static inline void __attribute__ ((always_inline))
+__lll_mutex_cond_lock (int *futex)
+{
+  int val = atomic_exchange_acq (futex, 2);
+
+  if (__builtin_expect (val != 0, 0))
+    {
+      while (atomic_exchange_acq (futex, 2) != 0)
+       lll_futex_wait (futex, 2);
+    }
+}
+#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *)
+       attribute_hidden;
+
+extern int __lll_mutex_timedlock_outlined (int *futex,
+                                          const struct timespec *)
+       attribute_hidden;
+
+static inline int __attribute__ ((always_inline))
+__lll_mutex_timedlock (int *futex, const struct timespec *abstime)
+{
+  int result = 0;
+  int val = atomic_exchange_acq (futex, 1);
+
+  if (__builtin_expect (val != 0, 0))
+    result = __lll_timedlock_wait (futex, abstime);
+  return result;
+}
+#define lll_mutex_timedlock(futex, abstime) \
+  __lll_mutex_timedlock (&(futex), abstime)
+
+
+static inline void __attribute__ ((always_inline))
+__lll_mutex_unlock (int *futex)
+{
+  int val = atomic_exchange_rel (futex, 0);
+  if (__builtin_expect (val > 1, 0))
+    lll_futex_wake (futex, 1);
+}
+#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex))
+
+
+static inline void __attribute__ ((always_inline))
+__lll_mutex_unlock_force (int *futex)
+{
+  (void) atomic_exchange_rel (futex, 0);
+  lll_futex_wake (futex, 1);
+}
+#define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex))
+
+
+#define lll_mutex_islocked(futex) \
+  (futex != 0)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+   mutex implementation. */
+
+/* Type for lock object.  */
+typedef int lll_lock_t;
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER           (0)
+#define LLL_LOCK_INITIALIZER_LOCKED    (1)
+
+extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
+
+/* The states of a lock are:
+    0  -  untaken
+    1  -  taken by one user
+   >1  -  taken by more users */
+
+#define lll_trylock(lock)      lll_mutex_trylock (lock)
+#define lll_lock(lock)         lll_mutex_lock (lock)
+#define lll_unlock(lock)       lll_mutex_unlock (lock)
+#define lll_islocked(lock)     lll_mutex_islocked (lock)
+
+/* The kernel notifies a process which uses CLONE_CLEARTID via futex
+   wakeup when the clone terminates.  The memory location contains the
+   thread ID while the clone is running and is reset to zero
+   afterwards. */
+#define lll_wait_tid(tid) \
+  do {                                 \
+    __typeof (tid) __tid;              \
+    while ((__tid = (tid)) != 0)       \
+      lll_futex_wait (&(tid), __tid);  \
+  } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+     attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+  ({                                                   \
+    int __res = 0;                                     \
+    if ((tid) != 0)                                    \
+      __res = __lll_timedwait_tid (&(tid), (abstime)); \
+    __res;                                             \
+  })
+
+
+/* Conditional variable handling.  */
+
+extern void __lll_cond_wait (pthread_cond_t *cond)
+     attribute_hidden;
+extern int __lll_cond_timedwait (pthread_cond_t *cond,
+                                const struct timespec *abstime)
+     attribute_hidden;
+extern void __lll_cond_wake (pthread_cond_t *cond)
+     attribute_hidden;
+extern void __lll_cond_broadcast (pthread_cond_t *cond)
+     attribute_hidden;
+
+#define lll_cond_wait(cond) \
+  __lll_cond_wait (cond)
+#define lll_cond_timedwait(cond, abstime) \
+  __lll_cond_timedwait (cond, abstime)
+#define lll_cond_wake(cond) \
+  __lll_cond_wake (cond)
+#define lll_cond_broadcast(cond) \
+  __lll_cond_broadcast (cond)
+
+#endif /* lowlevellock.h */
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S b/sysdeps/unix/sysv/linux/arm/nptl/pt-vfork.S
new file mode 100644 (file)
index 0000000..1c2e1f5
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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 <tcb-offsets.h>
+
+/* Save the PID value.  */
+#define SAVE_PID \
+       str     lr, [sp, #-4]!;         /* Save LR.  */                 \
+       mov     r0, #0xffff0fff;        /* Point to the high page.  */  \
+       mov     lr, pc;                 /* Save our return address.  */ \
+       sub     pc, r0, #31;            /* Jump to the TLS entry.  */   \
+       ldr     lr, [sp], #4;           /* Restore LR.  */              \
+       mov     r2, r0;                 /* Save the TLS addr in r2.  */ \
+       ldr     r3, [r2, #PID_OFFSET];  /* Load the saved PID.  */      \
+       rsb     r0, r3, #0;             /* Negate it.  */               \
+       str     r0, [r2, #PID_OFFSET]   /* Store the temporary PID.  */
+
+/* Restore the old PID value in the parent.  */
+#define RESTORE_PID \
+       cmp     r0, #0;                 /* If we are the parent... */   \
+       strne   r3, [r2, #PID_OFFSET]   /* ... restore the saved PID.  */
+
+#include "../vfork.S"
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c
new file mode 100644 (file)
index 0000000..c892581
--- /dev/null
@@ -0,0 +1,99 @@
+/* Copyright (C) 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 "pthreadP.h"
+#include <lowlevellock.h>
+
+unsigned long int __fork_generation attribute_hidden;
+
+static void
+clear_once_control (void *arg)
+{
+  pthread_once_t *once_control = (pthread_once_t *) arg;
+
+  *once_control = 0;
+  lll_futex_wake (once_control, INT_MAX);
+}
+
+int
+__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
+{
+  for (;;)
+    {
+      int oldval;
+      int newval;
+
+      /* Pseudo code:
+        newval = __fork_generation | 1;
+        oldval = *once_control;
+        if ((oldval & 2) == 0)
+          *once_control = newval;
+        Do this atomically.
+      */
+      do
+       {
+         newval = __fork_generation | 1;
+         oldval = *once_control;
+         if (oldval & 2)
+           break;
+       } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
+
+      /* Check if the initializer has already been done.  */
+      if ((oldval & 2) != 0)
+       return 0;
+
+      /* Check if another thread already runs the initializer. */
+      if ((oldval & 1) == 0)
+       break;
+
+      /* Check whether the initializer execution was interrupted by a fork.  */
+      if (oldval != newval)
+       break;
+
+      /* Same generation, some other thread was faster. Wait.  */
+      lll_futex_wait (once_control, oldval);
+    }
+
+  /* This thread is the first here.  Do the initialization.
+     Register a cleanup handler so that in case the thread gets
+     interrupted the initialization can be restarted.  */
+  pthread_cleanup_push (clear_once_control, once_control);
+
+  init_routine ();
+
+  pthread_cleanup_pop (0);
+
+  /* Say that the initialisation is done.  */
+  *once_control = __fork_generation | 2;
+
+  /* Wake up all other threads.  */
+  lll_futex_wake (once_control, INT_MAX);
+
+  return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)
+
+#if defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__PIC__)
+/* When statically linked, if pthread_create is used, this file
+   will be brought in.  The exception handling code in GCC assumes
+   that if pthread_create is available, so are these.  */
+const void *include_pthread_getspecific attribute_hidden = pthread_getspecific;
+const void *include_pthread_setspecific attribute_hidden = pthread_setspecific;
+const void *include_pthread_key_create attribute_hidden = pthread_key_create;
+#endif
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/vfork.S b/sysdeps/unix/sysv/linux/arm/nptl/vfork.S
new file mode 100644 (file)
index 0000000..87e055e
--- /dev/null
@@ -0,0 +1,39 @@
+/* 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 <tcb-offsets.h>
+
+/* Save the PID value.  */
+#define SAVE_PID \
+       str     lr, [sp, #-4]!;         /* Save LR.  */                 \
+       mov     r0, #0xffff0fff;        /* Point to the high page.  */  \
+       mov     lr, pc;                 /* Save our return address.  */ \
+       sub     pc, r0, #31;            /* Jump to the TLS entry.  */   \
+       ldr     lr, [sp], #4;           /* Restore LR.  */              \
+       mov     r2, r0;                 /* Save the TLS addr in r2.  */ \
+       ldr     r3, [r2, #PID_OFFSET];  /* Load the saved PID.  */      \
+       rsbs    r0, r3, #0;             /* Negate it.  */               \
+       moveq   r0, #0x80000000;        /* Use 0x80000000 if it was 0.  */ \
+       str     r0, [r2, #PID_OFFSET]   /* Store the temporary PID.  */
+
+/* Restore the old PID value in the parent.  */
+#define RESTORE_PID \
+       cmp     r0, #0;         /* If we are the parent... */           \
+       strne   r3, [r2, #PID_OFFSET]   /* ... restore the saved PID.  */
+
+#include "../vfork.S"
index 81b29ad..6dd189b 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1997,1998,1999,2000,2002,2003 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 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
@@ -78,14 +79,7 @@ __libc_sigaction (sig, act, oact)
          memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
          kact.sa_flags = act->sa_flags;
 # ifdef HAVE_SA_RESTORER
-         /* If the user specified SA_ONSTACK this means she is trying to
-            use the old-style stack switching.  Unfortunately this
-            requires the sa_restorer field so we cannot install our own
-            handler.  (In fact the user is likely to be out of luck anyway
-            since the kernel currently only supports stack switching via
-            the X/Open sigaltstack interface, but we allow for the
-            possibility that this might change in the future.)  */
-         if (kact.sa_flags & (SA_RESTORER | SA_ONSTACK))
+         if (kact.sa_flags & SA_RESTORER)
            kact.sa_restorer = act->sa_restorer;
          else
            {
@@ -131,8 +125,7 @@ __libc_sigaction (sig, act, oact)
       k_sigact.sa_mask = act->sa_mask.__val[0];
       k_sigact.sa_flags = act->sa_flags;
 # ifdef HAVE_SA_RESTORER
-      /* See the comments above for why we test SA_ONSTACK.  */
-      if (k_sigact.sa_flags & (SA_RESTORER | SA_ONSTACK))
+      if (k_sigact.sa_flags & SA_RESTORER)
        k_sigact.sa_restorer = act->sa_restorer;
       else
        {
index 4c0fdfb..22d0c1a 100644 (file)
    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, $-4]!
@@ -53,7 +53,7 @@
 #define POPARGS_3      add sp, sp, #12
 #define POPARGS_4      add sp, sp, #16
 #define POPARGS_5      add sp, sp, #16
-#define POPARGS_6      add sp, sp, #16 
+#define POPARGS_6      add sp, sp, #16
 
 #ifndef NARGS
 #define NARGS 3                        /* If we were called with no wrapper, this is really socket() */
@@ -66,8 +66,8 @@
 .globl __socket
 ENTRY (__socket)
        /* 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 
+          stmdb ip!, {a1-a4}.  It did not modify sp, so the stack never had
+          to be restored after the syscall completed.  It saved an
           instruction and meant no stack cleanup work was required.
 
           This will not work in the case of a socket call being interrupted
index 4df3e37..01b3717 100644 (file)
@@ -24,6 +24,9 @@
 /* There is some commonality.  */
 #include <ports/sysdeps/unix/arm/sysdep.h>
 
+/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
+#include <dl-sysdep.h>
+
 /* For Linux we can use the system call table in the header file
        /usr/include/asm/unistd.h
    of the kernel.  But these symbols do not follow the SYS_* syntax
@@ -43,7 +46,7 @@
    might return a large offset.  Therefore we must not anymore test
    for < 0, but test for a real error by making sure the value in R0
    is a real error number.  Linus said he will make sure the no syscall
-   returns a value in -1 .. -4095 as a valid result so we can savely
+   returns a value in -1 .. -4095 as a valid result so we can safely
    test with -4095.  */
 
 #undef PSEUDO
 
 #if NOT_IN_libc
 # define SYSCALL_ERROR __local_syscall_error
-# define SYSCALL_ERROR_HANDLER                                 \
+# if RTLD_PRIVATE_ERRNO
+#  define SYSCALL_ERROR_HANDLER                                        \
+__local_syscall_error:                                         \
+       ldr     r1, 1f;                                         \
+       rsb     r0, r0, #0;                                     \
+0:     str     r0, [pc, r1];                                   \
+       mvn     r0, #0;                                         \
+       DO_RET(lr);                                             \
+1:     .word C_SYMBOL_NAME(rtld_errno) - 0b - 8;
+# else
+#  define SYSCALL_ERROR_HANDLER                                        \
 __local_syscall_error:                                         \
        str     lr, [sp, #-4]!;                                 \
        str     r0, [sp, #-4]!;                                 \
@@ -106,6 +119,7 @@ __local_syscall_error:                                              \
        str     r1, [r0];                                       \
        mvn     r0, #0;                                         \
        ldr     pc, [sp], #4;
+# endif
 #else
 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used.  */
 # define SYSCALL_ERROR __syscall_error
@@ -239,6 +253,24 @@ __local_syscall_error:                                             \
   LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)
 #define ASM_ARGS_7     ASM_ARGS_6, "r" (_v3)
 
+/* We can't implement non-constant syscalls directly since the syscall
+   number is normally encoded in the instruction.  So use SYS_syscall.  */
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)         \
+       INTERNAL_SYSCALL_NCS_##nr (number, err, args)
+
+#define INTERNAL_SYSCALL_NCS_0(number, err, args...)           \
+       INTERNAL_SYSCALL (syscall, err, 1, number, args)
+#define INTERNAL_SYSCALL_NCS_1(number, err, args...)           \
+       INTERNAL_SYSCALL (syscall, err, 2, number, args)
+#define INTERNAL_SYSCALL_NCS_2(number, err, args...)           \
+       INTERNAL_SYSCALL (syscall, err, 3, number, args)
+#define INTERNAL_SYSCALL_NCS_3(number, err, args...)           \
+       INTERNAL_SYSCALL (syscall, err, 4, number, args)
+#define INTERNAL_SYSCALL_NCS_4(number, err, args...)           \
+       INTERNAL_SYSCALL (syscall, err, 5, number, args)
+#define INTERNAL_SYSCALL_NCS_5(number, err, args...)           \
+       INTERNAL_SYSCALL (syscall, err, 6, number, args)
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* linux/arm/sysdep.h */
index 0e267b3..a020658 100644 (file)
 ENTRY (__vfork)
 
 #ifdef __NR_vfork
+#ifdef SAVE_PID
+       SAVE_PID
+#endif
        DO_CALL (vfork, 0)
+#ifdef RESTORE_PID
+       RESTORE_PID
+#endif
        cmn     a1, #4096
        RETINSTR(cc, lr)
 
 # ifdef __ASSUME_VFORK_SYSCALL
-       b       PLTJMP(C_SYMBOL_NAME(__syscall_error))
+       b       PLTJMP(SYSCALL_ERROR)
 # else
        /* Check if vfork syscall is known at all.  */
-       cmn     a2, #ENOSYS
-       bne     PLTJMP(C_SYMBOL_NAME(__syscall_error))
+       cmn     a1, #ENOSYS
+       bne     PLTJMP(SYSCALL_ERROR)
 # endif
 #endif
 
@@ -48,7 +54,7 @@ ENTRY (__vfork)
        DO_CALL (fork, 0)
        cmn     a1, #4096
        RETINSTR(cc, lr)
-       b       PLTJMP(C_SYMBOL_NAME(__syscall_error))
+       b       PLTJMP(SYSCALL_ERROR)
 #elif !defined __NR_vfork
 # error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
 #endif