* 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.
This commit is contained in:
Daniel Jacobowitz 2005-11-16 19:03:42 +00:00
parent de96d1483f
commit 02a9f771e3
41 changed files with 2124 additions and 51 deletions

View file

@ -1,3 +1,61 @@
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.

View 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
@ -18,7 +18,10 @@
/* Define the machine-dependent type `jmp_buf'. ARM version. */
#ifndef _SETJMP_H
#ifndef _BITS_SETJMP_H
#define _BITS_SETJMP_H 1
#if !defined _SETJMP_H && !defined _PTHREAD_H
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
#endif
@ -34,3 +37,5 @@ typedef int __jmp_buf[10];
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
#endif

View 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
@ -18,7 +18,10 @@
/* Define the machine-dependent type `jmp_buf'. ARM version. */
#ifndef _SETJMP_H
#ifndef _BITS_SETJMP_H
#define _BITS_SETJMP_H 1
#if !defined _SETJMP_H && !defined _PTHREAD_H
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
#endif
@ -34,3 +37,5 @@ typedef int __jmp_buf[22];
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP]))
#endif

21
sysdeps/arm/nptl/Makefile Normal file
View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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))

View file

@ -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)

137
sysdeps/arm/nptl/tls.h Normal file
View file

@ -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 */

View 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
@ -20,8 +22,11 @@
#define _ERRNO_H
#include <bits/errno.h>
.globl C_SYMBOL_NAME(errno)
.globl syscall_error
#ifdef IS_IN_rtld
# include <dl-sysdep.h> /* Defines RTLD_PRIVATE_ERRNO. */
#endif
#include <tls.h>
#undef syscall_error
#ifdef NO_UNDERSCORES
@ -37,7 +42,29 @@ syscall_error:
moveq r0, $EAGAIN /* Yes; translate it to EAGAIN. */
#endif
#ifdef _LIBC_REENTRANT
#if USE___THREAD
mov ip, lr
mov r1, r0
mov r0, #0xffff0fff
mov lr, pc
sub pc, r0, #31
ldr r2, 1f
2: ldr r2, [pc, r2]
str r1, [r0, r2]
mvn r0, #0
RETINSTR (, ip)
1: .word errno(gottpoff) + (. - 2b - 8)
#elif RTLD_PRIVATE_ERRNO
ldr r1, 1f
0: str r0, [pc, r1]
mvn r0, $0
DO_RET(r14)
1: .word C_SYMBOL_NAME(rtld_errno) - 0b - 8
#elif defined(_LIBC_REENTRANT)
str lr, [sp, #-4]!
str r0, [sp, #-4]!
bl PLTJMP(C_SYMBOL_NAME(__errno_location))

View file

@ -25,7 +25,11 @@
#define _ERRNO_H 1
#include <bits/errno.h>
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
#define CLONE_VM 0x00000100
#define CLONE_THREAD 0x00010000
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
.text
ENTRY(__clone)
@ -42,16 +46,58 @@ ENTRY(__clone)
@ do the system call
@ get flags
mov r0, r2
#ifdef RESET_PID
mov ip, r2
#endif
@ new sp is already in r1
DO_CALL (clone, 0)
movs a1, a1
#ifdef __ARM_EABI__
stmfd sp!, {r4, r7}
#else
str r4, [sp, #-8]!
#endif
ldr r2, [sp, #8]
ldr r3, [sp, #12]
ldr r4, [sp, #16]
#ifdef __ARM_EABI__
ldr r7, =SYS_ify(clone)
swi 0x0
#else
swi SYS_ify(clone)
#endif
cmp r0, #0
beq 1f
#ifdef __ARM_EABI__
ldmfd sp!, {r4, r7}
#else
ldr r4, [sp], #8
#endif
blt PLTJMP(C_SYMBOL_NAME(__syscall_error))
RETINSTR(ne, lr)
RETINSTR(, lr)
1:
#ifdef RESET_PID
tst ip, #CLONE_THREAD
bne 3f
mov r0, #0xffff0fff
mov lr, pc
sub pc, r0, #31
mov r1, r0
tst ip, #CLONE_VM
movne r0, #-1
#ifdef __ARM_EABI__
ldr r7, =SYS_ify(getpid)
swieq 0x0
#else
swieq SYS_ify(getpid)
#endif
str r0, [r1, #PID_OFFSET]
str r0, [r1, #TID_OFFSET]
3:
#endif
@ pick the function arg and call address off the stack and execute
ldr r0, [sp, #4]
mov lr, pc
ldr pc, [sp]
ldr pc, [sp], #8
@ and we are done, passing the return value through r0
b PLTJMP(_exit)

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
# This file is generated from configure.in by Autoconf. DO NOT EDIT!
libc_cv_gcc_exceptions=yes
exceptions=-fexceptions

View file

@ -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

View file

@ -0,0 +1 @@
#include <aeabi_unwind_cpp_pr1.c>

View file

@ -0,0 +1 @@
#include <aeabi_unwind_cpp_pr1.c>

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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 */

View file

@ -20,16 +20,35 @@
/* If no SA_RESTORER function was specified by the application we use
one of these. This avoids the need for the kernel to synthesise a return
instruction on the stack, which would involve expensive cache flushes. */
instruction on the stack, which would involve expensive cache flushes.
Nowadays (2.6 series, and somewhat earlier) the kernel uses a high page
for signal trampolines, so the cache flushes are not an issue. But since
we do not have a vDSO, continue to use these so that we can provide
unwind information.
Start the unwind tables at least one instruction before the signal
trampoline, because the unwinder will assume we are returning after
a call site. */
.fnstart
.save {r0-r15}
.pad #12
nop
ENTRY(__default_sa_restorer)
mov r7, $SYS_ify(sigreturn)
swi 0x0
.fnend
#ifdef __NR_rt_sigreturn
.fnstart
.save {r0-r15}
.pad #168
nop
ENTRY(__default_rt_sa_restorer)
mov r7, $SYS_ify(rt_sigreturn)
swi 0x0
.fnend
#endif

View file

@ -33,19 +33,19 @@
The .S files for the other calls just #define socket and #include this. */
#ifndef __socket
#ifndef NO_WEAK_ALIAS
#define __socket P(__,socket)
#else
#define __socket socket
#endif
# ifndef NO_WEAK_ALIAS
# define __socket P(__,socket)
# else
# define __socket socket
# endif
#endif
#define PUSHARGS_1 str a1, [sp, $-8]!
#define PUSHARGS_2 stmfd sp!, {a1, a2}
#define PUSHARGS_3 stmfd sp!, {a1, a2, a3, a4} /* a4 pushed for padding */
#define PUSHARGS_4 stmfd sp!, {a1, a2, a3, a4}
#define PUSHARGS_5 stmfd sp!, {a1, a2, a3, a4} /* Caller has already pushed arg 5 */
#define PUSHARGS_6 stmfd sp!, {a1, a2, a3, a4}
#define PUSHARGS_1 str a1, [sp, $-8]!; .pad #8
#define PUSHARGS_2 stmfd sp!, {a1, a2}; .pad #8
#define PUSHARGS_3 stmfd sp!, {a1, a2, a3, a4}; .pad #16 /* a4 pushed for padding */
#define PUSHARGS_4 stmfd sp!, {a1, a2, a3, a4}; .pad #16
#define PUSHARGS_5 stmfd sp!, {a1, a2, a3, a4}; .pad #16 /* Caller has already pushed arg 5 */
#define PUSHARGS_6 stmfd sp!, {a1, a2, a3, a4}; .pad #16
#define POPARGS_1 add sp, sp, #8
#define POPARGS_2 add sp, sp, #8
@ -64,6 +64,8 @@
.globl __socket
ENTRY (__socket)
.fnstart
/* This code previously moved sp into ip and stored the args using
stmdb ip!, {a1-a4}. It did not modify sp, so the stack never had
to be restored after the syscall completed. It saved an
@ -98,11 +100,12 @@ ENTRY (__socket)
#if defined NEED_CANCELLATION && defined CENABLE
1:
stmfd sp!, {r7, lr}
.save {r7, lr}
CENABLE
mov ip, r0
mov r0, #P(SOCKOP_,socket)
add r1, sp, #4
add r1, sp, #8
mov r7, #SYS_ify(socketcall)
swi 0x0
@ -120,6 +123,7 @@ ENTRY (__socket)
b PLTJMP(SYSCALL_ERROR)
#endif
.fnend
PSEUDO_END (__socket)
#ifndef NO_WEAK_ALIAS

View file

@ -48,6 +48,11 @@
: "memory"); \
_a1; })
/* For EABI, non-constant syscalls are actually pretty easy... */
#undef INTERNAL_SYSCALL_NCS
#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
INTERNAL_SYSCALL_RAW (number, err, nr, args)
/* We must save and restore r7 (call-saved) for the syscall number.
We never make function calls from inside here (only potentially
signal handlers), so we do not bother with doubleword alignment.

View file

@ -0,0 +1,6 @@
libc {
GLIBC_PRIVATE {
# A copy of sigaction lives in NPTL, and needs these.
__default_sa_restorer; __default_rt_sa_restorer;
}
}

View file

@ -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; })

View file

@ -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 */

View file

@ -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;

View file

@ -0,0 +1,3 @@
#define RESET_PID
#include <tcb-offsets.h>
#include "../clone.S"

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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 */

View file

@ -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"

View file

@ -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

View file

@ -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"

View 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
{

View file

@ -34,11 +34,11 @@
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

View 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
@ -96,7 +99,17 @@
#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 */

View file

@ -30,16 +30,22 @@
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