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/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.
-/* 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
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
+
+#endif
-/* 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
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
+
+#endif
--- /dev/null
+# 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
--- /dev/null
+/* 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)
--- /dev/null
+/* 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)
--- /dev/null
+/* 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)
--- /dev/null
+/* 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))
--- /dev/null
+#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)
--- /dev/null
+/* 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 */
-/* 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
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))
#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)
@ 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)
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+# This file is generated from configure.in by Autoconf. DO NOT EDIT!
+
+libc_cv_gcc_exceptions=yes
+exceptions=-fexceptions
--- /dev/null
+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
--- /dev/null
+#include <aeabi_unwind_cpp_pr1.c>
--- /dev/null
+#include <aeabi_unwind_cpp_pr1.c>
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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 */
/* 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
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
.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
#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
b PLTJMP(SYSCALL_ERROR)
#endif
+ .fnend
PSEUDO_END (__socket)
#ifndef NO_WEAK_ALIAS
: "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.
--- /dev/null
+libc {
+ GLIBC_PRIVATE {
+ # A copy of sigaction lives in NPTL, and needs these.
+ __default_sa_restorer; __default_rt_sa_restorer;
+ }
+}
--- /dev/null
+/* 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; })
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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;
--- /dev/null
+#define RESET_PID
+#include <tcb-offsets.h>
+#include "../clone.S"
--- /dev/null
+/* 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>
--- /dev/null
+/* 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>
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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"
--- /dev/null
+/* 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
--- /dev/null
+/* 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"
-/* 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
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
{
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
{
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]!
#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() */
.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
/* 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
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]!; \
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
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 */
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
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