diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-06-08 05:28:14 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-06-08 05:28:14 +0000 |
commit | 7726edc27354afe163f492c0e6a8d4354fddb494 (patch) | |
tree | 22a712872298767abf2b081d9f766a33cad8fa20 /nptl/sysdeps/pthread/pthread.h | |
parent | ede0f73aeabe62589f6ca19a6987f48aa0d06184 (diff) | |
download | glibc-7726edc27354afe163f492c0e6a8d4354fddb494.tar.gz |
Update.
2003-06-07 Ulrich Drepper <drepper@redhat.com>
* cleanup_routine.c: New file.
* Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine.
* sysdeps/pthread/pthread.h: Add support for fully exception-based
cleanup handling.
* Makefile (libpthread-routines): Add cleanup_routine.
Add more CFLAGS variables to compile with exceptions. Add comments
why which file needs unwind tables.
(tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx*
tests.
* tst-cancelx1.c: New file.
* tst-cancelx2.c: New file.
* tst-cancelx3.c: New file.
* tst-cancelx4.c: New file.
* tst-cancelx5.c: New file.
* tst-cancelx6.c: New file.
* tst-cancelx7.c: New file.
* tst-cancelx8.c: New file.
* tst-cancelx9.c: New file.
* tst-cancelx10.c: New file.
* tst-cancelx11.c: New file.
* tst-cancelx12.c: New file.
* tst-cancelx13.c: New file.
* tst-cancelx14.c: New file.
* tst-cancelx15.c: New file.
* tst-cleanupx0.c: New file.
* tst-cleanupx0.expect: New file.
* tst-cleanupx1.c: New file.
* tst-cleanupx2.c: New file.
* tst-cleanupx3.c: New file.
* tst-cleanup0.c: Make standard compliant.
* tst-cleanup1.c: Likewise.
* sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support.
* sysdeps/unix/sysv/linux/sem_wait.c: Likewise.
* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
* sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise.
* sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and
CLEANUP_JMP_BUF.
* sysdeps/x86_64/tcb-offsets.sym: Likewise.
* tst-cancel12.c: New file.
* tst-cancel13.c: New file.
* tst-cancel14.c: New file.
* tst-cancel15.c: New file.
* Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14,
and tst-cancel15.
* tst-cancel1.c: Add some comments.
* sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative
timeout correctly.
Diffstat (limited to 'nptl/sysdeps/pthread/pthread.h')
-rw-r--r-- | nptl/sysdeps/pthread/pthread.h | 137 |
1 files changed, 128 insertions, 9 deletions
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h index c0375ae223..1f0a34baa2 100644 --- a/nptl/sysdeps/pthread/pthread.h +++ b/nptl/sysdeps/pthread/pthread.h @@ -419,14 +419,132 @@ typedef struct #endif +/* Structure to hold the cleanup handler information. */ +struct __pthread_cleanup_frame +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; +}; + +#if defined __GNUC__ && defined __EXCEPTIONS +# ifdef __cplusplus +/* Class to handle cancellation handler invocation. */ +class __pthread_cleanup_class +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; + + public: + __pthread_cleanup_class (void (*__fct) (void *), void *__arg) + : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { } + ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); } + __setdoit (int __newval) { __do_it = __newval; } + __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, + &__cancel_type); + __restore () const { pthread_setcanceltype (__cancel_type, 0); +}; + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + 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) \ + do { \ + __pthread_cleanup_class __clframe (routine, arg) + +/* 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) \ + __clframe.__setdoit (execute); \ + } while (0) + +# 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) \ + do { \ + __pthread_cleanup_class __clframe (routine, arg); \ + __clframe.__defer () + +/* 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) \ + __clframe.__restore (); \ + __clframe.__setdoit (execute); \ + } while (0) +# endif +# else +/* Function called to call the cleanup handler. As an extern inline + function the compiler is free to decide inlining the change when + needed or fall back on the copy which must exist somewhere + else. */ +extern inline void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) +{ + if (__frame->__do_it) + __frame->__cancel_routine (__frame->__cancel_arg); +} + /* Install a cleanup handler: ROUTINE will be called with arguments ARG - when the thread is cancelled or calls pthread_exit. ROUTINE will also + when the thread is canceled or calls pthread_exit. ROUTINE will also be called with arguments ARG when the matching pthread_cleanup_pop is executed with non-zero EXECUTE argument. 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) \ +# define pthread_cleanup_push(routine, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \ + = { .__cancel_routine = (routine), .__cancel_arg = (arg), \ + .__do_it = 1 }; + +/* 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) \ + __clframe.__do_it = (execute); \ + } while (0) + +# 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) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \ + = { .__cancel_routine = (routine), .__cancel_arg = (arg), \ + .__do_it = 1 }; \ + (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \ + &__clframe.__cancel_type) + +/* 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) \ + (void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \ + __clframe.__do_it = (execute); \ + } while (0) +# endif +# endif +#else +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + 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) \ do { \ __pthread_unwind_buf_t __cancel_buf; \ void (*__cancel_routine) (void *) = (routine); \ @@ -447,7 +565,7 @@ extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) /* 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) \ +# define pthread_cleanup_pop(execute) \ } while (0); \ __pthread_unregister_cancel (&__cancel_buf); \ if (execute) \ @@ -456,11 +574,11 @@ extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) __cleanup_fct_attribute; -#ifdef __USE_GNU +# 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(routine, arg) \ +# define pthread_cleanup_push_defer_np(routine, arg) \ do { \ __pthread_unwind_buf_t __cancel_buf; \ void (*__cancel_routine) (void *) = (routine); \ @@ -482,7 +600,7 @@ extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf) /* 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_cleanup(execute) \ +# define pthread_cleanup_pop_restore_np(execute) \ } while (0); \ __pthread_unregister_cancel_restore (&__cancel_buf); \ if (execute) \ @@ -490,15 +608,16 @@ extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf) } while (0) extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf) __cleanup_fct_attribute; -#endif +# endif /* Internal interface to initiate cleanup. */ extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) __cleanup_fct_attribute __attribute ((__noreturn__)) -#ifndef SHARED +# ifndef SHARED __attribute ((__weak__)) -#endif +# endif ; +#endif /* Function used in the macros. */ struct __jmp_buf_tag; |