mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
Update.
2003-04-11 Ulrich Drepper <drepper@redhat.com> * sysdeps/generic/libc-start.c: Cleanup MAIN_AUXVEC_ARG handling. Remove HAVE_CANCELBUF code. Replace with code using the new initializers for unwind-based cleanup handling. * sysdeps/generic/unwind.h: Update from latest gcc version. * sysdeps/unix/sysv/linux/i386/sysdep.h: Define labels in a few places to allow unwind data generation. * sysdeps/i386/bits/setjmp.h: Allow file to be included multiple times. * sysdeps/x86_64/bits/setjmp.h: Likewise. * sysdeps/sh/bits/setjmp.h: Likewise. * sysdeps/powerpc/bits/setjmp.h: Likewise. * sysdeps/unix/sysv/linux/ia64/bits/setjmp.h: Likewise. * sysdeps/alpha/bits/setjmp.h: Likewise.
This commit is contained in:
parent
877e51b20f
commit
09d65ff393
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
||||
2003-04-11 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/generic/libc-start.c: Cleanup MAIN_AUXVEC_ARG handling.
|
||||
Remove HAVE_CANCELBUF code. Replace with code using the new
|
||||
initializers for unwind-based cleanup handling.
|
||||
* sysdeps/generic/unwind.h: Update from latest gcc version.
|
||||
* sysdeps/unix/sysv/linux/i386/sysdep.h: Define labels in a few
|
||||
places to allow unwind data generation.
|
||||
* sysdeps/i386/bits/setjmp.h: Allow file to be included multiple times.
|
||||
* sysdeps/x86_64/bits/setjmp.h: Likewise.
|
||||
* sysdeps/sh/bits/setjmp.h: Likewise.
|
||||
* sysdeps/powerpc/bits/setjmp.h: Likewise.
|
||||
* sysdeps/unix/sysv/linux/ia64/bits/setjmp.h: Likewise.
|
||||
* sysdeps/alpha/bits/setjmp.h: Likewise.
|
||||
|
||||
2003-04-11 Roland McGrath <roland@redhat.com>
|
||||
|
||||
* csu/tst-empty.c: New file.
|
||||
|
@ -1,3 +1,45 @@
|
||||
2003-04-11 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* pthread.h: Define new data structure for cleanup buffer. Declare
|
||||
new cleanup handler interfaces.
|
||||
* descr.h: Include <unwind.h> if necessary. Define pthread_unwind_buf.
|
||||
(struct pthread): Add cleanup_jmp_buf pointer. Define
|
||||
HAVE_CLEANUP_JMP_BUF and not HAVE_CANCELBUF.
|
||||
* pthreadP.h: Declare __pthread_unwind. Define __do_cancel to use
|
||||
it. Declare old cleanup handler installation functions.
|
||||
* cleanup.c: Rewrite. Install handler for unwind-based cleanup
|
||||
handling.
|
||||
* cleanup_defer.c: Likewise.
|
||||
* cleanup_compat.c: New file. Old cleanup code.
|
||||
* cleanup_def_compat.c: New file. Old cleanup code.
|
||||
* pthread_create.c (start_thread): Initialize cleanup_jmp_buf element
|
||||
if own thread descriptor.
|
||||
* unwind.c: New file.
|
||||
* forward.c: Add __pthread_unwind.
|
||||
* init.c (pthread_functions): Add __pthread_unwind.
|
||||
* sysdeps/pthread/pthread-functions.s (struct pthread_functions):
|
||||
Add ptr___pthread_unwind.
|
||||
* Versions [GLIBC_2.3.3] (libpthread): Export new cleanup handling
|
||||
and unwind function.
|
||||
* Makefile (libpthread-routines): Add cleanup_compat,
|
||||
cleanup_def_compat, and unwind. Define CFLAGS to enable unwind
|
||||
table generation if necessary.
|
||||
* version.c: Record whether unwind support is compiled in.
|
||||
* sysdeps/pthread/configure.in: Add checks for unwind unterfaces.
|
||||
* sysdeps/pthread/bits/libc-lock.h: Add prototypes of the old cleanup
|
||||
handler interfaces.
|
||||
* sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add quite a bit of
|
||||
complication to generate unwind information for syscall wrappers.
|
||||
* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define
|
||||
__cleanup_fct_attribute.
|
||||
|
||||
* Makefile: Add rules to build and run tst-cleanup0.
|
||||
* tst-cleanup0.c: New file.
|
||||
* tst-cleanup0.expect: New file.
|
||||
|
||||
* pthread_create.c (deallocate_tsd): Don't take parameter. Adjust
|
||||
caller. Optimize to avoid often unecessary local variable.
|
||||
|
||||
2003-04-11 Roland McGrath <roland@redhat.com>
|
||||
|
||||
* Makefile ($(objpfx)multidir.mk): New target, generated makefile that
|
||||
|
@ -98,7 +98,8 @@ libpthread-routines = init events version \
|
||||
sem_open sem_close sem_unlink \
|
||||
sem_getvalue \
|
||||
sem_wait sem_trywait sem_timedwait sem_post \
|
||||
cleanup cleanup_defer \
|
||||
cleanup cleanup_defer cleanup_compat \
|
||||
cleanup_defer_compat unwind \
|
||||
pt-longjmp \
|
||||
cancellation \
|
||||
lowlevellock lowlevelmutex \
|
||||
@ -122,6 +123,10 @@ libpthread-static-only-routines = pthread_atfork
|
||||
libpthread-nonshared = pthread_atfork
|
||||
|
||||
CFLAGS-pthread_atfork.c = -DNOT_IN_libc
|
||||
CFLAGS-init.c = -fexceptions -fasynchronous-unwind-tables
|
||||
CFLAGS-unwind.c = -fexceptions
|
||||
CFLAGS-cancellation.c = -fasynchronous-unwind-tables
|
||||
CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables
|
||||
|
||||
# Don't generate deps for calls with no sources. See sysdeps/unix/Makefile.
|
||||
omit-deps = $(unix-syscalls:%=ptw-%)
|
||||
@ -153,7 +158,7 @@ tests = tst-attr1 tst-attr2 \
|
||||
tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
|
||||
tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
|
||||
tst-cancel11 \
|
||||
tst-cleanup1 tst-cleanup2 tst-cleanup3 \
|
||||
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
|
||||
tst-flock1 tst-flock2 \
|
||||
tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
|
||||
tst-exec1 tst-exec2 tst-exec3 \
|
||||
@ -208,6 +213,9 @@ CFLAGS-flockfile.c = -D_IO_MTSAFE_IO
|
||||
CFLAGS-ftrylockfile.c = -D_IO_MTSAFE_IO
|
||||
CFLAGS-funlockfile.c = -D_IO_MTSAFE_IO
|
||||
|
||||
# Ugly, ugly. We have to link with libgcc_eh but how?
|
||||
link-libc-static := $(common-objpfx)libc.a $(gnulib) -lgcc_eh $(common-objpfx)libc.a
|
||||
|
||||
ifeq ($(build-static),yes)
|
||||
tests-static += tst-locale1 tst-locale2
|
||||
endif
|
||||
@ -220,7 +228,6 @@ ifeq (yes,$(build-shared))
|
||||
# Make sure these things are built in the `make lib' pass so they can be used
|
||||
# to run programs during the `make others' pass.
|
||||
lib-noranlib: $(addprefix $(objpfx),$(extra-objs))
|
||||
endif
|
||||
|
||||
# What we install as libpthread.so for programs to link against is in fact a
|
||||
# link script. It contains references for the various libraries we need.
|
||||
@ -229,6 +236,7 @@ endif
|
||||
# We need to use absolute paths since otherwise local copies (if they exist)
|
||||
# of the files are taken by the linker.
|
||||
install: $(inst_libdir)/libpthread.so
|
||||
|
||||
$(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \
|
||||
$(objpfx)libpthread.so$(libpthread.so-version) \
|
||||
$(inst_libdir)/$(patsubst %,$(libtype.oS),\
|
||||
@ -245,6 +253,8 @@ $(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \
|
||||
mv -f $@.new $@
|
||||
$(inst_libdir)/libpthread_nonshared.a: $(objpfx)libpthread_nonshared.a
|
||||
$(do-install)
|
||||
endif
|
||||
|
||||
|
||||
# 'pthread_self' is a simple memory or register load. Setting up the
|
||||
# stack frame is more work than the actual operation. Disable the
|
||||
@ -313,6 +323,9 @@ $(objpfx)pt-initfini.s: pt-initfini.c
|
||||
$(compile.c) -S $(CFLAGS-pt-initfini.s) -finhibit-size-directive \
|
||||
$(patsubst -f%,-fno-%,$(exceptions)) -o $@
|
||||
|
||||
$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0
|
||||
$(make-test-out) 2>&1 | cmp - tst-cleanup0.expect >& $@
|
||||
|
||||
# We only have one kind of startup code files. Static binaries and
|
||||
# shared libraries are build using the PIC version.
|
||||
$(objpfx)crti.S: $(objpfx)pt-initfini.s
|
||||
|
@ -211,6 +211,11 @@ libpthread {
|
||||
|
||||
# Proposed API extensions.
|
||||
pthread_tryjoin_np; pthread_timedjoin_np;
|
||||
|
||||
# New cancellation cleanup handling.
|
||||
__pthread_register_cancel; __pthread_unregister_cancel;
|
||||
__pthread_register_cancel_defer; __pthread_unregister_cancel_restore;
|
||||
__pthread_unwind_next;
|
||||
}
|
||||
|
||||
GLIBC_PRIVATE {
|
||||
|
@ -345,6 +345,19 @@ typedef pthread_key_t __libc_key_t;
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Note that for I/O cleanup handling we are using the old-style
|
||||
cancel handling. It does not have to be integrated with C++ snce
|
||||
no C++ code is called in the middle. The old-style handling is
|
||||
faster and the support is not going away. */
|
||||
extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
|
||||
void (*routine) (void *), void *arg);
|
||||
extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
|
||||
int execute);
|
||||
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
|
||||
void (*routine) (void *), void *arg);
|
||||
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
|
||||
int execute);
|
||||
|
||||
/* Start critical region with cleanup. */
|
||||
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
|
55
nptl/sysdeps/pthread/configure
vendored
55
nptl/sysdeps/pthread/configure
vendored
@ -5,3 +5,58 @@ if test "x$libc_cv_gcc___thread" != xyes; then
|
||||
echo "$as_me: error: compiler support for __thread is required" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
|
||||
echo "$as_me:$LINENO: checking for forced unwind support" >&5
|
||||
echo $ECHO_N "checking for forced unwind support... $ECHO_C" >&6
|
||||
if test "${libc_cv_forced_unwind+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
#line $LINENO "configure"
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <unwind.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
struct _Unwind_Exception exc;
|
||||
struct _Unwind_Context *context;
|
||||
_Unwind_GetCFA (context)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
libc_cv_forced_unwind=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
libc_cv_forced_unwind=no
|
||||
fi
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $libc_cv_forced_unwind" >&5
|
||||
echo "${ECHO_T}$libc_cv_forced_unwind" >&6
|
||||
if test $libc_cv_forced_unwind = yes; then
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_FORCED_UNWIND 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
@ -4,3 +4,16 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
|
||||
if test "x$libc_cv_gcc___thread" != xyes; then
|
||||
AC_MSG_ERROR(compiler support for __thread is required)
|
||||
fi
|
||||
|
||||
dnl Iff <unwind.h> is available, make sure it is the right one and it
|
||||
dnl contains struct _Unwind_Exception.
|
||||
AC_CACHE_CHECK(dnl
|
||||
for forced unwind support, libc_cv_forced_unwind, [dnl
|
||||
AC_TRY_LINK([#include <unwind.h>], [
|
||||
struct _Unwind_Exception exc;
|
||||
struct _Unwind_Context *context;
|
||||
_Unwind_GetCFA (context)],
|
||||
libc_cv_forced_unwind=yes, libc_cv_forced_unwind=no)])
|
||||
if test $libc_cv_forced_unwind = yes; then
|
||||
AC_DEFINE(HAVE_FORCED_UNWIND)
|
||||
fi
|
||||
|
@ -85,6 +85,8 @@ struct pthread_functions
|
||||
int);
|
||||
#define HAVE_PTR_NTHREADS
|
||||
int *ptr_nthreads;
|
||||
void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *)
|
||||
__attribute ((noreturn)) __cleanup_fct_attribute;
|
||||
};
|
||||
|
||||
/* Variable in libc.so. */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define __need_sigset_t
|
||||
#include <signal.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
#include <bits/setjmp.h>
|
||||
|
||||
|
||||
/* Detach state. */
|
||||
@ -380,6 +381,24 @@ extern int pthread_cancel (pthread_t __th) __THROW;
|
||||
extern void pthread_testcancel (void) __THROW;
|
||||
|
||||
|
||||
/* Cancellation handling with integration into exception handling. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *__pad[16];
|
||||
struct
|
||||
{
|
||||
__jmp_buf __cancel_jmp_buf;
|
||||
int __mask_was_saved;
|
||||
} __cancel_jmp_buf[1];
|
||||
} __pthread_unwind_buf_t __attribute__ ((__aligned__));
|
||||
|
||||
/* No special attributes by default. */
|
||||
#ifndef __cleanup_fct_attribute
|
||||
# define __cleanup_fct_attribute
|
||||
#endif
|
||||
|
||||
|
||||
/* Install a cleanup handler: ROUTINE will be called with arguments ARG
|
||||
when the thread is cancelled or calls pthread_exit. ROUTINE will also
|
||||
be called with arguments ARG when the matching pthread_cleanup_pop
|
||||
@ -387,44 +406,84 @@ extern void pthread_testcancel (void) __THROW;
|
||||
|
||||
pthread_cleanup_push and pthread_cleanup_pop are macros and must always
|
||||
be used in matching pairs at the same nesting level of braces. */
|
||||
#define pthread_cleanup_push(routine,arg) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
_pthread_cleanup_push (&_buffer, (routine), (arg));
|
||||
|
||||
extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
|
||||
void (*__routine) (void *), void *__arg)
|
||||
__THROW;
|
||||
#define pthread_cleanup_push(routine, arg) \
|
||||
do { \
|
||||
__pthread_unwind_buf_t __cancel_buf; \
|
||||
void (*__cancel_routine) (void *) = (routine); \
|
||||
void *__cancel_arg = (arg); \
|
||||
int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) \
|
||||
__cancel_buf.__cancel_jmp_buf, 0); \
|
||||
if (__builtin_expect (not_first_call, 0)) \
|
||||
{ \
|
||||
__cancel_routine (__cancel_arg); \
|
||||
__pthread_unwind_next (&__cancel_buf); \
|
||||
/* NOTREACHED */ \
|
||||
} \
|
||||
\
|
||||
__pthread_register_cancel (&__cancel_buf); \
|
||||
do {
|
||||
extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
|
||||
__cleanup_fct_attribute;
|
||||
|
||||
/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
|
||||
If EXECUTE is non-zero, the handler function is called. */
|
||||
#define pthread_cleanup_pop(execute) \
|
||||
_pthread_cleanup_pop (&_buffer, (execute)); }
|
||||
|
||||
extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
|
||||
int __execute) __THROW;
|
||||
} while (0); \
|
||||
__pthread_unregister_cancel (&__cancel_buf); \
|
||||
if (execute) \
|
||||
__cancel_routine (__cancel_arg); \
|
||||
} while (0)
|
||||
extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
|
||||
__cleanup_fct_attribute;
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Install a cleanup handler as pthread_cleanup_push does, but also
|
||||
saves the current cancellation type and sets it to deferred
|
||||
cancellation. */
|
||||
# define pthread_cleanup_push_defer_np(routine,arg) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
_pthread_cleanup_push_defer (&_buffer, (routine), (arg));
|
||||
|
||||
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
|
||||
void (*__routine) (void *),
|
||||
void *__arg) __THROW;
|
||||
# define pthread_cleanup_push_defer(routine, arg) \
|
||||
do { \
|
||||
__pthread_unwind_buf_t __cancel_buf; \
|
||||
void (*__cancel_routine) (void *) = (routine); \
|
||||
void *__cancel_arg = (arg); \
|
||||
int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) \
|
||||
__cancel_buf.__cancel_jmp_buf, 0); \
|
||||
if (__builtin_expect (not_first_call, 0)) \
|
||||
{ \
|
||||
__cancel_routine (__cancel_arg); \
|
||||
__pthread_unwind_next (&__cancel_buf); \
|
||||
/* NOTREACHED */ \
|
||||
} \
|
||||
\
|
||||
__pthread_register_cancel_defer (&__cancel_buf); \
|
||||
do {
|
||||
extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
|
||||
__cleanup_fct_attribute;
|
||||
|
||||
/* Remove a cleanup handler as pthread_cleanup_pop does, but also
|
||||
restores the cancellation type that was in effect when the matching
|
||||
pthread_cleanup_push_defer was called. */
|
||||
# define pthread_cleanup_pop_restore_np(execute) \
|
||||
_pthread_cleanup_pop_restore (&_buffer, (execute)); }
|
||||
|
||||
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
|
||||
int __execute) __THROW;
|
||||
# define pthread_cleanup_pop_cleanup(execute) \
|
||||
} while (0); \
|
||||
__pthread_unregister_cancel_restore (&__cancel_buf); \
|
||||
if (execute) \
|
||||
__cancel_routine (__cancel_arg); \
|
||||
} while (0)
|
||||
extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf)
|
||||
__cleanup_fct_attribute;
|
||||
#endif
|
||||
|
||||
/* Internal interface to initiate cleanup. */
|
||||
extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
|
||||
__cleanup_fct_attribute __attribute ((__noreturn__))
|
||||
#ifndef SHARED
|
||||
__attribute ((__weak__))
|
||||
#endif
|
||||
;
|
||||
|
||||
/* Function used in the macros. */
|
||||
struct __jmp_buf_tag;
|
||||
extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROW;
|
||||
|
||||
|
||||
/* Mutex handling. */
|
||||
|
||||
|
@ -149,4 +149,7 @@ typedef union
|
||||
#endif
|
||||
|
||||
|
||||
/* Extra attributes for the cleanup functions. */
|
||||
#define __cleanup_fct_attribute __attribute ((regparm (1)))
|
||||
|
||||
#endif /* bits/pthreadtypes.h */
|
||||
|
@ -29,6 +29,7 @@
|
||||
# define PSEUDO(name, syscall_name, args) \
|
||||
.text; \
|
||||
ENTRY (name) \
|
||||
L(name##START): \
|
||||
cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \
|
||||
jne L(pseudo_cancel); \
|
||||
DO_CALL (syscall_name, args); \
|
||||
@ -38,29 +39,262 @@
|
||||
L(pseudo_cancel): \
|
||||
CENABLE \
|
||||
SAVE_OLDTYPE_##args \
|
||||
PUSHARGS_##args \
|
||||
PUSHCARGS_##args \
|
||||
DOCARGS_##args \
|
||||
movl $SYS_ify (syscall_name), %eax; \
|
||||
ENTER_KERNEL \
|
||||
POPARGS_##args; \
|
||||
POPCARGS_##args \
|
||||
/* Until we can handle unwinding from the sysenter page the kernel \
|
||||
provides we cannot use ENTER_KERNEL here. */ \
|
||||
int $0x80; \
|
||||
POPCARGS_##args; \
|
||||
POPSTATE_##args \
|
||||
cmpl $-4095, %eax; \
|
||||
jae SYSCALL_ERROR_LABEL; \
|
||||
L(pseudo_end):
|
||||
L(pseudo_end): \
|
||||
\
|
||||
/* Create unwinding information for the syscall wrapper. */ \
|
||||
.section .eh_frame,"a",@progbits; \
|
||||
L(STARTFRAME): \
|
||||
/* Length of the CIE. */ \
|
||||
.long L(ENDCIE)-L(STARTCIE); \
|
||||
L(STARTCIE): \
|
||||
/* CIE ID. */ \
|
||||
.long 0; \
|
||||
/* Version number. */ \
|
||||
.byte 1; \
|
||||
/* NUL-terminated augmentation string. Note "z" means there is an \
|
||||
augmentation value later on. */ \
|
||||
.string "zR"; \
|
||||
/* Code alignment factor. */ \
|
||||
.uleb128 1; \
|
||||
/* Data alignment factor. */ \
|
||||
.sleb128 -4; \
|
||||
/* Return address register column. */ \
|
||||
.byte 8; \
|
||||
/* Augmentation value length. */ \
|
||||
.uleb128 1; \
|
||||
/* Encoding: DW_EH_PE_pcrel + DW_EH_PE_sdata4. */ \
|
||||
.byte 0x1b; \
|
||||
/* Start of the table initialization. */ \
|
||||
.byte 0xc; \
|
||||
.uleb128 4; \
|
||||
.uleb128 4; \
|
||||
.byte 0x88; \
|
||||
.uleb128 1; \
|
||||
.align 4; \
|
||||
L(ENDCIE): \
|
||||
/* Length of the FDE. */ \
|
||||
.long L(ENDFDE)-L(STARTFDE); \
|
||||
L(STARTFDE): \
|
||||
/* CIE pointer. */ \
|
||||
.long L(STARTFDE)-L(STARTFRAME); \
|
||||
/* PC-relative start address of the code. */ \
|
||||
.long L(name##START)-.; \
|
||||
/* Length of the code. */ \
|
||||
.long L(name##END)-L(name##START); \
|
||||
/* No augmentation data. */ \
|
||||
.uleb128 0; \
|
||||
/* The rest of the code depends on the number of parameters the syscall \
|
||||
takes. */ \
|
||||
EH_FRAME_##args(name); \
|
||||
.align 4; \
|
||||
L(ENDFDE): \
|
||||
.previous
|
||||
|
||||
/* Callframe description for syscalls without parameters. This is very
|
||||
simple. The only place the stack pointer is changed is when the old
|
||||
cancellation state value is saved. */
|
||||
# define EH_FRAME_0(name) \
|
||||
.byte 4; \
|
||||
.long L(PUSHSTATE)-name; \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPSTATE)-L(PUSHSTATE); \
|
||||
.byte 14; \
|
||||
.uleb128 4
|
||||
|
||||
/* For syscalls with one and two parameters the code is the same as for
|
||||
those which take no parameter. */
|
||||
# define EH_FRAME_1(name) EH_FRAME_0 (name)
|
||||
# define EH_FRAME_2(name) EH_FRAME_1 (name)
|
||||
|
||||
/* For syscalls with three parameters the stack pointer is changed
|
||||
also to save the content of the %ebx register. */
|
||||
# define EH_FRAME_3(name) \
|
||||
.byte 4; \
|
||||
.long L(PUSHBX1)-name; \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPBX1)-L(PUSHBX1); \
|
||||
.byte 14; \
|
||||
.uleb128 4; \
|
||||
.byte 4; \
|
||||
.long L(PUSHSTATE)-L(POPBX1); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(PUSHBX2)-L(PUSHSTATE); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(POPBX2)-L(PUSHBX2); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPSTATE)-L(POPBX2); \
|
||||
.byte 14; \
|
||||
.uleb128 4
|
||||
|
||||
/* With four parameters the syscall wrappers have to save %ebx and %esi. */
|
||||
# define EH_FRAME_4(name) \
|
||||
.byte 4; \
|
||||
.long L(PUSHSI1)-name; \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(PUSHBX1)-L(PUSHSI1); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(POPBX1)-L(PUSHBX1); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPSI1)-L(POPBX1); \
|
||||
.byte 14; \
|
||||
.uleb128 4; \
|
||||
.byte 4; \
|
||||
.long L(PUSHSTATE)-L(POPSI1); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(PUSHSI2)-L(PUSHSTATE); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(PUSHBX2)-L(PUSHSI2); \
|
||||
.byte 14; \
|
||||
.uleb128 16; \
|
||||
.byte 4; \
|
||||
.long L(POPBX2)-L(PUSHBX2); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(POPSI2)-L(POPBX2); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPSTATE)-L(POPSI2); \
|
||||
.byte 14; \
|
||||
.uleb128 4
|
||||
|
||||
/* With five parameters the syscall wrappers have to save %ebx, %esi,
|
||||
and %edi. */
|
||||
# define EH_FRAME_5(name) \
|
||||
.byte 4; \
|
||||
.long L(PUSHDI1)-name; \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(PUSHSI1)-L(PUSHDI1); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(PUSHBX1)-L(PUSHSI1); \
|
||||
.byte 14; \
|
||||
.uleb128 16; \
|
||||
.byte 4; \
|
||||
.long L(POPBX1)-L(PUSHBX1); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(POPSI1)-L(POPBX1); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPDI1)-L(POPSI1); \
|
||||
.byte 14; \
|
||||
.uleb128 4; \
|
||||
.byte 4; \
|
||||
.long L(PUSHSTATE)-L(POPDI1); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(PUSHDI2)-L(PUSHSTATE); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(PUSHSI2)-L(PUSHDI2); \
|
||||
.byte 14; \
|
||||
.uleb128 16; \
|
||||
.byte 4; \
|
||||
.long L(PUSHBX2)-L(PUSHSI2); \
|
||||
.byte 14; \
|
||||
.uleb128 20; \
|
||||
.byte 4; \
|
||||
.long L(POPBX2)-L(PUSHBX2); \
|
||||
.byte 14; \
|
||||
.uleb128 16; \
|
||||
.byte 4; \
|
||||
.long L(POPSI2)-L(POPBX2); \
|
||||
.byte 14; \
|
||||
.uleb128 12; \
|
||||
.byte 4; \
|
||||
.long L(POPDI2)-L(POPSI2); \
|
||||
.byte 14; \
|
||||
.uleb128 8; \
|
||||
.byte 4; \
|
||||
.long L(POPSTATE)-L(POPDI2); \
|
||||
.byte 14; \
|
||||
.uleb128 4
|
||||
|
||||
|
||||
# undef ASM_SIZE_DIRECTIVE
|
||||
# define ASM_SIZE_DIRECTIVE(name) L(name##END): .size name,.-name;
|
||||
|
||||
# define SAVE_OLDTYPE_0 movl %eax, %edx;
|
||||
# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0
|
||||
# define SAVE_OLDTYPE_2 pushl %eax;
|
||||
# define SAVE_OLDTYPE_2 pushl %eax; L(PUSHSTATE):
|
||||
# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2
|
||||
# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2
|
||||
# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2
|
||||
|
||||
# define DOCARGS_0 DOARGS_0
|
||||
# define DOCARGS_1 DOARGS_1
|
||||
# define PUSHCARGS_0 /* No arguments to push. */
|
||||
# define DOCARGS_0 /* No arguments to frob. */
|
||||
# define POPCARGS_0 /* No arguments to pop. */
|
||||
# define _PUSHCARGS_0 /* No arguments to push. */
|
||||
# define _POPCARGS_0 /* No arguments to pop. */
|
||||
|
||||
# define PUSHCARGS_1 movl %ebx, %edx; PUSHCARGS_0
|
||||
# define DOCARGS_1 _DOARGS_1 (4)
|
||||
# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx
|
||||
# define _PUSHCARGS_1 pushl %ebx; L(PUSHBX2): _PUSHCARGS_0
|
||||
# define _POPCARGS_1 _POPCARGS_0; popl %ebx; L(POPBX2):
|
||||
|
||||
# define PUSHCARGS_2 PUSHCARGS_1
|
||||
# define DOCARGS_2 _DOARGS_2 (12)
|
||||
# define POPCARGS_2 POPCARGS_1
|
||||
# define _PUSHCARGS_2 _PUSHCARGS_1
|
||||
# define _POPCARGS_2 _POPCARGS_1
|
||||
|
||||
# define PUSHCARGS_3 _PUSHCARGS_2
|
||||
# define DOCARGS_3 _DOARGS_3 (20)
|
||||
# define POPCARGS_3 _POPCARGS_3
|
||||
# define _PUSHCARGS_3 _PUSHCARGS_2
|
||||
# define _POPCARGS_3 _POPCARGS_2
|
||||
|
||||
# define PUSHCARGS_4 _PUSHCARGS_4
|
||||
# define DOCARGS_4 _DOARGS_4 (28)
|
||||
# define POPCARGS_4 _POPCARGS_4
|
||||
# define _PUSHCARGS_4 pushl %esi; L(PUSHSI2): _PUSHCARGS_3
|
||||
# define _POPCARGS_4 _POPCARGS_3; popl %esi; L(POPSI2):
|
||||
|
||||
# define PUSHCARGS_5 _PUSHCARGS_5
|
||||
# define DOCARGS_5 _DOARGS_5 (36)
|
||||
# define POPCARGS_5 _POPCARGS_5
|
||||
# define _PUSHCARGS_5 pushl %edi; L(PUSHDI2): _PUSHCARGS_4
|
||||
# define _POPCARGS_5 _POPCARGS_4; popl %edi; L(POPDI2):
|
||||
|
||||
# ifdef IS_IN_libpthread
|
||||
# define CENABLE call __pthread_enable_asynccancel;
|
||||
@ -69,12 +303,13 @@
|
||||
# define CENABLE call __libc_enable_asynccancel;
|
||||
# define CDISABLE call __libc_disable_asynccancel
|
||||
# endif
|
||||
# define POPCARGS_0 pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax;
|
||||
# define POPCARGS_1 POPCARGS_0
|
||||
# define POPCARGS_2 xchgl (%esp), %eax; CDISABLE; popl %eax;
|
||||
# define POPCARGS_3 POPCARGS_2
|
||||
# define POPCARGS_4 POPCARGS_2
|
||||
# define POPCARGS_5 POPCARGS_2
|
||||
# define POPSTATE_0 \
|
||||
pushl %eax; L(PUSHSTATE): movl %ecx, %eax; CDISABLE; popl %eax; L(POPSTATE):
|
||||
# define POPSTATE_1 POPSTATE_0
|
||||
# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; L(POPSTATE):
|
||||
# define POPSTATE_3 POPSTATE_2
|
||||
# define POPSTATE_4 POPSTATE_3
|
||||
# define POPSTATE_5 POPSTATE_4
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
# define SINGLE_THREAD_P \
|
||||
|
112
nptl/unwind.c
Normal file
112
nptl/unwind.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>
|
||||
and Richard Henderson <rth@redhat.com>, 2003.
|
||||
|
||||
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 <stdlib.h>
|
||||
#include "pthreadP.h"
|
||||
|
||||
|
||||
#ifdef HAVE_FORCED_UNWIND
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
unwind_stop (int version, _Unwind_Action actions,
|
||||
_Unwind_Exception_Class exc_class,
|
||||
struct _Unwind_Exception *exc_obj,
|
||||
struct _Unwind_Context *context, void *stop_parameter)
|
||||
{
|
||||
struct pthread_unwind_buf *buf = stop_parameter;
|
||||
|
||||
/* Do longjmp if we're at "end of stack", aka "end of unwind data".
|
||||
We assume there are only C frame without unwind data in between
|
||||
here and the jmp_buf target. Otherwise simply note that the CFA
|
||||
of a function is NOT within it's stack frame; it's the SP of the
|
||||
previous frame. */
|
||||
if ((actions & _UA_END_OF_STACK)
|
||||
|| ! _JMPBUF_UNWINDS (buf->cancel_jmp_buf[0].jmp_buf,
|
||||
_Unwind_GetCFA (context)))
|
||||
__libc_longjmp ((struct __jmp_buf_tag *) buf->cancel_jmp_buf, 1);
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
unwind_cleanup (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
#endif /* have forced unwind */
|
||||
|
||||
|
||||
void
|
||||
__cleanup_fct_attribute __attribute ((noreturn))
|
||||
__pthread_unwind (__pthread_unwind_buf_t *buf)
|
||||
{
|
||||
struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
|
||||
struct pthread *self = THREAD_SELF;
|
||||
|
||||
/* Handle the compatibility stuff first. Execute all handlers
|
||||
registered with the old method. We don't execute them in order,
|
||||
instead, they will run first. */
|
||||
struct _pthread_cleanup_buffer *oldp = ibuf->priv.data.cleanup;
|
||||
struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup);
|
||||
|
||||
while (curp != oldp)
|
||||
{
|
||||
/* Pointer to the next element. */
|
||||
struct _pthread_cleanup_buffer *nextp = curp->__prev;
|
||||
|
||||
/* Call the handler. */
|
||||
curp->__routine (curp->__arg);
|
||||
|
||||
/* To the next. */
|
||||
curp = nextp;
|
||||
}
|
||||
|
||||
/* Mark the current element as handled. */
|
||||
THREAD_SETMEM (self, cleanup, curp);
|
||||
|
||||
#ifdef HAVE_FORCED_UNWIND
|
||||
/* This is not a catchable exception, so don't provide any details about
|
||||
the exception type. We do need to initialize the field though. */
|
||||
ibuf->priv.data.exc.exception_class = 0;
|
||||
ibuf->priv.data.exc.exception_cleanup = unwind_cleanup;
|
||||
|
||||
_Unwind_ForcedUnwind (&ibuf->priv.data.exc, unwind_stop, ibuf);
|
||||
#else
|
||||
/* We simply jump to the registered setjmp buffer. */
|
||||
__libc_longjmp ((struct __jmp_buf_tag *) ibuf->cancel_jmp_buf, 1);
|
||||
#endif
|
||||
/* NOTREACHED */
|
||||
|
||||
/* We better do not get here. */
|
||||
abort ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__cleanup_fct_attribute __attribute ((noreturn))
|
||||
__pthread_unwind_next (__pthread_unwind_buf_t *buf)
|
||||
{
|
||||
struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
|
||||
|
||||
__pthread_unwind (ibuf->priv.data.prev);
|
||||
}
|
@ -26,7 +26,11 @@ static const char banner[] =
|
||||
"Copyright (C) 2003 Free Software Foundation, Inc.\n\
|
||||
This is free software; see the source for copying conditions.\n\
|
||||
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
|
||||
PARTICULAR PURPOSE.\n";
|
||||
PARTICULAR PURPOSE.\n"
|
||||
#ifdef HAVE_FORCED_UNWIND
|
||||
"Forced unwind support included.\n"
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
extern void __nptl_main (void) __attribute__ ((noreturn));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Define the machine-dependent type `jmp_buf'. Alpha version.
|
||||
Copyright (C) 1992, 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1997, 2003 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
|
||||
@ -17,7 +17,10 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#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
|
||||
|
||||
@ -80,3 +83,5 @@ typedef long int __jmp_buf[17];
|
||||
#define _JMPBUF_UNWINDS(_jmpbuf, _address) \
|
||||
((void *)(_address) < (void *)((_jmpbuf)[JB_SP]))
|
||||
#endif
|
||||
|
||||
#endif /* bits/setjmp.h */
|
||||
|
@ -51,12 +51,17 @@ extern void __pthread_initialize_minimal (void)
|
||||
# define LIBC_START_MAIN BP_SYM (__libc_start_main)
|
||||
#endif
|
||||
|
||||
STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
|
||||
#ifdef MAIN_AUXVEC_ARG
|
||||
, void *
|
||||
/* main gets passed a pointer to the auxiliary. */
|
||||
# define MAIN_AUXVEC_DECL , void *
|
||||
# define MAIN_AUXVEC_PARAM , auxvec
|
||||
#else
|
||||
# define MAIN_AUXVEC_DECL
|
||||
# define MAIN_AUXVEC_PARAM
|
||||
#endif
|
||||
|
||||
),
|
||||
STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
|
||||
MAIN_AUXVEC_DECL),
|
||||
int argc,
|
||||
char *__unbounded *__unbounded ubp_av,
|
||||
#ifdef LIBC_START_MAIN_AUXVEC_ARG
|
||||
@ -73,11 +78,7 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
|
||||
__attribute__ ((noreturn));
|
||||
|
||||
STATIC int
|
||||
LIBC_START_MAIN (int (*main) (int, char **, char **
|
||||
#ifdef MAIN_AUXVEC_ARG
|
||||
, void *
|
||||
#endif
|
||||
),
|
||||
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||
int argc, char *__unbounded *__unbounded ubp_av,
|
||||
#ifdef LIBC_START_MAIN_AUXVEC_ARG
|
||||
ElfW(auxv_t) *__unbounded auxvec,
|
||||
@ -172,10 +173,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char **
|
||||
if (init)
|
||||
(*init) (
|
||||
#ifdef INIT_MAIN_ARGS
|
||||
argc, argv, __environ
|
||||
# ifdef MAIN_AUXVEC_ARG
|
||||
, auxvec
|
||||
# endif
|
||||
argc, argv, __environ MAIN_AUXVEC_PARAM
|
||||
#endif
|
||||
);
|
||||
|
||||
@ -184,38 +182,45 @@ LIBC_START_MAIN (int (*main) (int, char **, char **
|
||||
_dl_debug_printf ("\ntransferring control: %s\n\n", argv[0]);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CANCELBUF
|
||||
if (setjmp (THREAD_SELF->cancelbuf) == 0)
|
||||
#endif
|
||||
#ifdef HAVE_CLEANUP_JMP_BUF
|
||||
/* Memory for the cancellation buffer. */
|
||||
struct pthread_unwind_buf unwind_buf;
|
||||
|
||||
int not_first_call;
|
||||
not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
|
||||
if (__builtin_expect (! not_first_call, 1))
|
||||
{
|
||||
/* XXX This is where the try/finally handling must be used. */
|
||||
struct pthread *self = THREAD_SELF;
|
||||
|
||||
result = main (argc, argv, __environ
|
||||
#ifdef MAIN_AUXVEC_ARG
|
||||
, auxvec
|
||||
#endif
|
||||
/* Store old info. */
|
||||
unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
|
||||
unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
|
||||
|
||||
);
|
||||
/* Store the new cleanup handler info. */
|
||||
THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
|
||||
|
||||
/* Run the program. */
|
||||
result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
|
||||
}
|
||||
#ifdef HAVE_CANCELBUF
|
||||
else
|
||||
{
|
||||
# ifdef HAVE_PTR_NTHREADS
|
||||
/* One less thread. Decrement the counter. If it is zero we
|
||||
terminate the entire process. */
|
||||
result = 0;
|
||||
# ifdef SHARED
|
||||
# ifdef SHARED
|
||||
int *const ptr = __libc_pthread_functions.ptr_nthreads;
|
||||
# else
|
||||
# else
|
||||
extern int __nptl_nthreads __attribute ((weak));
|
||||
int *const ptr = &__nptl_nthreads;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
if (! atomic_decrement_and_test (ptr))
|
||||
# endif
|
||||
/* Not much left to do but to exit the thread, not the process. */
|
||||
__exit_thread (0);
|
||||
}
|
||||
#else
|
||||
/* Nothing fancy, just call the function. */
|
||||
result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
|
||||
#endif
|
||||
|
||||
exit (result);
|
||||
|
@ -1,26 +1,36 @@
|
||||
/* Exception handling and frame unwind runtime interface routines.
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
This file is part of GCC.
|
||||
|
||||
GNU CC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
GCC 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.
|
||||
|
||||
GNU CC 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.
|
||||
GCC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
/* As a special exception, if you include this header file into source
|
||||
files compiled by GCC, this header file does not by itself cause
|
||||
the resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License. */
|
||||
|
||||
/* This is derived from the C++ ABI for IA-64. Where we diverge
|
||||
for cross-architecture compatibility are noted with "@@@". */
|
||||
|
||||
#ifndef _UNWIND_H
|
||||
#define _UNWIND_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -31,7 +41,12 @@ extern "C" {
|
||||
inefficient for 32-bit and smaller machines. */
|
||||
typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
|
||||
typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
|
||||
#if defined(__ia64__) && defined(__hpux__)
|
||||
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__)));
|
||||
#else
|
||||
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
|
||||
#endif
|
||||
typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
|
||||
|
||||
/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and
|
||||
consumer of an exception. We'll go along with this for now even on
|
||||
@ -87,6 +102,7 @@ typedef int _Unwind_Action;
|
||||
#define _UA_CLEANUP_PHASE 2
|
||||
#define _UA_HANDLER_FRAME 4
|
||||
#define _UA_FORCE_UNWIND 8
|
||||
#define _UA_END_OF_STACK 16
|
||||
|
||||
/* This is an opaque type used to refer to a system-specific data
|
||||
structure used by the system unwinder. This context is created and
|
||||
@ -125,6 +141,9 @@ extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
|
||||
extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
|
||||
extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
|
||||
|
||||
/* @@@ Retrieve the CFA of the given context. */
|
||||
extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
|
||||
|
||||
extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *);
|
||||
|
||||
extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *);
|
||||
@ -135,15 +154,15 @@ extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *);
|
||||
library and language-specific exception handling semantics. It is
|
||||
specific to the code fragment described by an unwind info block, and
|
||||
it is always referenced via the pointer in the unwind info block, and
|
||||
hence it has no ABI-specified name.
|
||||
hence it has no ABI-specified name.
|
||||
|
||||
Note that this implies that two different C++ implementations can
|
||||
use different names, and have different contents in the language
|
||||
specific data area. Moreover, that the language specific data
|
||||
specific data area. Moreover, that the language specific data
|
||||
area contains no version info because name of the function invoked
|
||||
provides more effective versioning by detecting at link time the
|
||||
lack of code to handle the different data format. */
|
||||
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)
|
||||
(int, _Unwind_Action, _Unwind_Exception_Class,
|
||||
struct _Unwind_Exception *, struct _Unwind_Context *);
|
||||
@ -186,6 +205,12 @@ extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *);
|
||||
extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *);
|
||||
#endif
|
||||
|
||||
/* @@@ Given an address, return the entry point of the function that
|
||||
contains it. */
|
||||
extern void * _Unwind_FindEnclosingFunction (void *pc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* unwind.h */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1997, 1998, 2000, 2001, 2003 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
|
||||
@ -17,8 +17,10 @@
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Define the machine-dependent type `jmp_buf'. Intel 386 version. */
|
||||
#ifndef _BITS_SETJMP_H
|
||||
#define _BITS_SETJMP_H 1
|
||||
|
||||
#ifndef _SETJMP_H
|
||||
#if !defined _SETJMP_H && !defined _PTHREAD_H
|
||||
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
|
||||
#endif
|
||||
|
||||
@ -40,3 +42,5 @@ typedef int __jmp_buf[6];
|
||||
containing a local variable at ADDRESS. */
|
||||
#define _JMPBUF_UNWINDS(jmpbuf, address) \
|
||||
((void *) (address) < (void *) (jmpbuf)[JB_SP])
|
||||
|
||||
#endif /* bits/setjmp.h */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1997, 1998, 2000, 2003 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
|
||||
@ -17,8 +17,10 @@
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Define the machine-dependent type `jmp_buf'. PowerPC version. */
|
||||
#ifndef _BITS_SETJMP_H
|
||||
#define _BITS_SETJMP_H 1
|
||||
|
||||
#ifndef _SETJMP_H
|
||||
#if !defined _SETJMP_H && !defined _PTHREAD_H
|
||||
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
|
||||
#endif
|
||||
|
||||
@ -43,7 +45,7 @@
|
||||
# define JB_CR 21 /* Condition code registers. */
|
||||
# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total. */
|
||||
# define JB_SIZE (58*4)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _ASM
|
||||
@ -58,3 +60,5 @@ typedef long int __jmp_buf[58];
|
||||
containing a local variable at ADDRESS. */
|
||||
#define _JMPBUF_UNWINDS(jmpbuf, address) \
|
||||
((void *) (address) < (void *) (jmpbuf)[JB_GPR1])
|
||||
|
||||
#endif /* bits/setjmp.h */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999, 2000, 2003 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
|
||||
@ -17,8 +17,10 @@
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Define the machine-dependent type `jmp_buf'. SH version. */
|
||||
#ifndef _BITS_SETJMP_H
|
||||
#define _BITS_SETJMP_H 1
|
||||
|
||||
#ifndef _SETJMP_H
|
||||
#if !defined _SETJMP_H && !defined _PTHREAD_H
|
||||
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
|
||||
#endif
|
||||
|
||||
@ -43,10 +45,12 @@ typedef struct
|
||||
#endif
|
||||
|
||||
#if defined __USE_MISC || defined _ASM
|
||||
#define JB_SIZE (4 * 15)
|
||||
# define JB_SIZE (4 * 15)
|
||||
#endif
|
||||
|
||||
/* Test if longjmp to JMPBUF would unwind the frame
|
||||
containing a local variable at ADDRESS. */
|
||||
#define _JMPBUF_UNWINDS(jmpbuf, address) \
|
||||
((void *) (address) < &(jmpbuf)[0].__regs[7])
|
||||
|
||||
#endif /* bits/setjmp.h */
|
||||
|
@ -164,7 +164,7 @@ __i686.get_pc_thunk.reg: \
|
||||
# else
|
||||
/* Store (- %eax) into errno through the GOT. */
|
||||
# define SYSCALL_ERROR_HANDLER \
|
||||
0:SETUP_PIC_REG(cx); \
|
||||
0:SETUP_PIC_REG(cx); \
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %ecx; \
|
||||
xorl %edx, %edx; \
|
||||
subl %eax, %edx; \
|
||||
@ -250,9 +250,9 @@ __i686.get_pc_thunk.reg: \
|
||||
#define PUSHARGS_1 movl %ebx, %edx; PUSHARGS_0
|
||||
#define DOARGS_1 _DOARGS_1 (4)
|
||||
#define POPARGS_1 POPARGS_0; movl %edx, %ebx
|
||||
#define _PUSHARGS_1 pushl %ebx; _PUSHARGS_0
|
||||
#define _PUSHARGS_1 pushl %ebx; L(PUSHBX1): _PUSHARGS_0
|
||||
#define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4)
|
||||
#define _POPARGS_1 _POPARGS_0; popl %ebx
|
||||
#define _POPARGS_1 _POPARGS_0; popl %ebx; L(POPBX1):
|
||||
|
||||
#define PUSHARGS_2 PUSHARGS_1
|
||||
#define DOARGS_2 _DOARGS_2 (8)
|
||||
@ -271,16 +271,16 @@ __i686.get_pc_thunk.reg: \
|
||||
#define PUSHARGS_4 _PUSHARGS_4
|
||||
#define DOARGS_4 _DOARGS_4 (24)
|
||||
#define POPARGS_4 _POPARGS_4
|
||||
#define _PUSHARGS_4 pushl %esi; _PUSHARGS_3
|
||||
#define _PUSHARGS_4 pushl %esi; L(PUSHSI1): _PUSHARGS_3
|
||||
#define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4)
|
||||
#define _POPARGS_4 _POPARGS_3; popl %esi
|
||||
#define _POPARGS_4 _POPARGS_3; popl %esi; L(POPSI1):
|
||||
|
||||
#define PUSHARGS_5 _PUSHARGS_5
|
||||
#define DOARGS_5 _DOARGS_5 (32)
|
||||
#define POPARGS_5 _POPARGS_5
|
||||
#define _PUSHARGS_5 pushl %edi; _PUSHARGS_4
|
||||
#define _PUSHARGS_5 pushl %edi; L(PUSHDI1): _PUSHARGS_4
|
||||
#define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4)
|
||||
#define _POPARGS_5 _POPARGS_4; popl %edi
|
||||
#define _POPARGS_5 _POPARGS_4; popl %edi; L(POPDI1):
|
||||
|
||||
#else /* !__ASSEMBLER__ */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version.
|
||||
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
|
||||
|
||||
@ -18,7 +18,10 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#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
|
||||
|
||||
@ -33,3 +36,5 @@ typedef long __jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128
|
||||
variable at ADDRESS. */
|
||||
#define _JMPBUF_UNWINDS(_jmpbuf, _address) \
|
||||
((void *)(_address) < (void *)(((long *)_jmpbuf)[0]))
|
||||
|
||||
#endif /* bits/setjmp.h */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001, 2002, 2003 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
|
||||
@ -17,8 +17,10 @@
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Define the machine-dependent type `jmp_buf'. x86-64 version. */
|
||||
#ifndef _BITS_SETJMP_H
|
||||
#define _BITS_SETJMP_H 1
|
||||
|
||||
#ifndef _SETJMP_H
|
||||
#if !defined _SETJMP_H && !defined _PTHREAD_H
|
||||
# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
|
||||
#endif
|
||||
|
||||
@ -72,3 +74,5 @@ typedef int __jmp_buf[6];
|
||||
((void *) (address) < (void *) (jmpbuf)[JB_SP])
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* bits/setjmp.h */
|
||||
|
Loading…
Reference in New Issue
Block a user