From a032a6587011cbdac8c2f7e11f15dc4e592bbb55 Mon Sep 17 00:00:00 2001 From: Austin Foxley Date: Tue, 16 Feb 2010 12:27:18 -0800 Subject: mass sync with glibc nptl Signed-off-by: Austin Foxley --- .../unix/sysv/linux/arm/unwind-forcedunwind.c | 133 ++++++++++++--------- 1 file changed, 75 insertions(+), 58 deletions(-) (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c') diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c index 206202809..e19facfb8 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek . @@ -18,97 +18,94 @@ Boston, MA 02111-1307, USA. */ #include -#include +#include #include -#include #include -#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) -#define __libc_dlsym dlsym - +static void *libgcc_s_handle; static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); static _Unwind_Reason_Code (*libgcc_s_personality) - (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); + (int, _Unwind_Action, _Unwind_Exception_Class, 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 *); +static void (*libgcc_s_sjlj_register) (struct SjLj_Function_Context *); +static void (*libgcc_s_sjlj_unregister) (struct SjLj_Function_Context *); void +__attribute_noinline__ pthread_cancel_init (void) { void *resume, *personality, *forcedunwind, *getcfa; void *handle; + void *sjlj_register, *sjlj_unregister; - if (__builtin_expect (libgcc_s_getcfa != NULL, 1)) - return; + if (__builtin_expect (libgcc_s_handle != NULL, 1)) + { + /* Force gcc to reload all values. */ + asm volatile ("" ::: "memory"); + 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")) + || (sjlj_register = __libc_dlsym (handle, "_Unwind_SjLj_Register")) == NULL + || (sjlj_unregister = __libc_dlsym (handle, "_Unwind_SjLj_Unregister")) == NULL + || (resume = __libc_dlsym (handle, "_Unwind_SjLj_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_sj0")) == NULL + || (forcedunwind = __libc_dlsym (handle, "_Unwind_SjLj_ForcedUnwind")) == NULL || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL -#ifdef ARCH_CANCEL_INIT - || ARCH_CANCEL_INIT (handle) -#endif ) - { -# define STR_N_LEN(str) str, strlen (str) - INTERNAL_SYSCALL_DECL (err); - INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO, - STR_N_LEN ("libgcc_s.so.1 must be installed for pthread_cancel to work\n")); - abort (); - } + __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_sjlj_register = sjlj_register; + libgcc_s_sjlj_unregister = sjlj_unregister; libgcc_s_getcfa = getcfa; + /* Make sure libgcc_s_getcfa is written last. Otherwise, + pthread_cancel_init might return early even when the pointer the + caller is interested in is not initialized yet. */ + atomic_write_barrier (); + libgcc_s_handle = handle; +} + +void +__libc_freeres_fn_section +__unwind_freeres (void) +{ + void *handle = libgcc_s_handle; + if (handle != NULL) + { + libgcc_s_handle = NULL; + __libc_dlclose (handle); + } } -/* 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 ( -#ifdef __thumb__ -" .code 32" -#endif -" .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" -#ifdef __thumb__ -" .code 16" -#endif -); +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_resume (exc); +} _Unwind_Reason_Code -__gcc_personality_v0 (_Unwind_State state, - struct _Unwind_Exception *ue_header, - struct _Unwind_Context *context) +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + 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); + + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); } _Unwind_Reason_Code @@ -117,6 +114,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, { if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0)) pthread_cancel_init (); + return libgcc_s_forcedunwind (exc, stop, stop_argument); } @@ -125,5 +123,24 @@ _Unwind_GetCFA (struct _Unwind_Context *context) { if (__builtin_expect (libgcc_s_getcfa == NULL, 0)) pthread_cancel_init (); + return libgcc_s_getcfa (context); } + +void +_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) +{ + if (__builtin_expect (libgcc_s_sjlj_register == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_sjlj_register (fc); +} + +void +_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) +{ + if (__builtin_expect (libgcc_s_sjlj_unregister == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_sjlj_unregister (fc); +} -- cgit v1.2.3