diff --git a/ChangeLog b/ChangeLog index 9f1eb446f1..57be8c46bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2003-04-11 Ulrich Drepper + + * 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 * csu/tst-empty.c: New file. diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 6ffe62314e..bbda8c591e 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,45 @@ +2003-04-11 Ulrich Drepper + + * pthread.h: Define new data structure for cleanup buffer. Declare + new cleanup handler interfaces. + * descr.h: Include 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 * Makefile ($(objpfx)multidir.mk): New target, generated makefile that diff --git a/nptl/Makefile b/nptl/Makefile index cd8ad98c38..79d28c9a30 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -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 diff --git a/nptl/Versions b/nptl/Versions index 5824108426..4f52eb66f3 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -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 { diff --git a/nptl/sysdeps/pthread/bits/libc-lock.h b/nptl/sysdeps/pthread/bits/libc-lock.h index 3a3d3cc6d3..945a81cb82 100644 --- a/nptl/sysdeps/pthread/bits/libc-lock.h +++ b/nptl/sysdeps/pthread/bits/libc-lock.h @@ -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; \ diff --git a/nptl/sysdeps/pthread/configure b/nptl/sysdeps/pthread/configure index 8999d37e5a..50293a4f1c 100755 --- a/nptl/sysdeps/pthread/configure +++ b/nptl/sysdeps/pthread/configure @@ -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 +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 diff --git a/nptl/sysdeps/pthread/configure.in b/nptl/sysdeps/pthread/configure.in index 8350f86dc0..e4ea6830d6 100644 --- a/nptl/sysdeps/pthread/configure.in +++ b/nptl/sysdeps/pthread/configure.in @@ -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 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 ], [ +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 diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h index 9f38e34053..93ba089982 100644 --- a/nptl/sysdeps/pthread/pthread-functions.h +++ b/nptl/sysdeps/pthread/pthread-functions.h @@ -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. */ diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h index 72673d11a6..5373b80dcf 100644 --- a/nptl/sysdeps/pthread/pthread.h +++ b/nptl/sysdeps/pthread/pthread.h @@ -26,6 +26,7 @@ #define __need_sigset_t #include #include +#include /* 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. */ diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h index c14f1b1ef6..0834894c25 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -149,4 +149,7 @@ typedef union #endif +/* Extra attributes for the cleanup functions. */ +#define __cleanup_fct_attribute __attribute ((regparm (1))) + #endif /* bits/pthreadtypes.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h index 35f05e1cc2..b7009d753f 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.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 \ diff --git a/nptl/unwind.c b/nptl/unwind.c new file mode 100644 index 0000000000..46c896d5b3 --- /dev/null +++ b/nptl/unwind.c @@ -0,0 +1,112 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper + and Richard Henderson , 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 +#include +#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); +} diff --git a/nptl/version.c b/nptl/version.c index d0658bac0c..f2fd25fd6d 100644 --- a/nptl/version.c +++ b/nptl/version.c @@ -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)); diff --git a/sysdeps/alpha/bits/setjmp.h b/sysdeps/alpha/bits/setjmp.h index fcd57d61d1..c603a35554 100644 --- a/sysdeps/alpha/bits/setjmp.h +++ b/sysdeps/alpha/bits/setjmp.h @@ -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 directly; use 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 */ diff --git a/sysdeps/generic/libc-start.c b/sysdeps/generic/libc-start.c index 351205d636..b98f0a2aa0 100644 --- a/sysdeps/generic/libc-start.c +++ b/sysdeps/generic/libc-start.c @@ -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); diff --git a/sysdeps/generic/unwind.h b/sysdeps/generic/unwind.h index ce43365a31..08d3381175 100644 --- a/sysdeps/generic/unwind.h +++ b/sysdeps/generic/unwind.h @@ -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 */ diff --git a/sysdeps/i386/bits/setjmp.h b/sysdeps/i386/bits/setjmp.h index e5e493bcae..107fe58b35 100644 --- a/sysdeps/i386/bits/setjmp.h +++ b/sysdeps/i386/bits/setjmp.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 directly; use 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 */ diff --git a/sysdeps/powerpc/bits/setjmp.h b/sysdeps/powerpc/bits/setjmp.h index e17bde1351..f849fe23ff 100644 --- a/sysdeps/powerpc/bits/setjmp.h +++ b/sysdeps/powerpc/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 directly; use 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 */ diff --git a/sysdeps/sh/bits/setjmp.h b/sysdeps/sh/bits/setjmp.h index 55bc66549b..22497703af 100644 --- a/sysdeps/sh/bits/setjmp.h +++ b/sysdeps/sh/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 directly; use 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 */ diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index 2e660c39fc..14984b64f2 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep.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__ */ diff --git a/sysdeps/unix/sysv/linux/ia64/bits/setjmp.h b/sysdeps/unix/sysv/linux/ia64/bits/setjmp.h index 3ef2396250..76625753d9 100644 --- a/sysdeps/unix/sysv/linux/ia64/bits/setjmp.h +++ b/sysdeps/unix/sysv/linux/ia64/bits/setjmp.h @@ -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 . @@ -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 directly; use 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 */ diff --git a/sysdeps/x86_64/bits/setjmp.h b/sysdeps/x86_64/bits/setjmp.h index ba5dd2c112..96646efdda 100644 --- a/sysdeps/x86_64/bits/setjmp.h +++ b/sysdeps/x86_64/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 directly; use instead." #endif @@ -72,3 +74,5 @@ typedef int __jmp_buf[6]; ((void *) (address) < (void *) (jmpbuf)[JB_SP]) # endif #endif + +#endif /* bits/setjmp.h */