diff options
author | Rich Felker <dalias@aerifal.cx> | 2012-02-09 02:33:08 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2012-02-09 02:33:08 -0500 |
commit | afc35d5efde48b82a7786d9c89b115965da6b637 (patch) | |
tree | d71e3007272b5eaa392feb84064459d8de9d82f5 /include | |
parent | ed2911a11317729c1a13e779237fed736c676c1b (diff) | |
download | musl-afc35d5efde48b82a7786d9c89b115965da6b637.tar.gz musl-afc35d5efde48b82a7786d9c89b115965da6b637.tar.xz musl-afc35d5efde48b82a7786d9c89b115965da6b637.zip |
replace bad cancellation cleanup abi with a sane one
the old abi was intended to duplicate glibc's abi at the expense of being ugly and slow, but it turns out glib was not even using that abi except on non-gcc-compatible compilers (which it doesn't even support) and was instead using an exceptions-in-c/unwind-based approach whose abi we could not duplicate anyway without nasty dwarf2/unwind integration. the new abi is copied from a very old glibc abi, which seems to still be supported/present in current glibc. it avoids all unwinding, whether by sjlj or exceptions, and merely maintains a linked list of cleanup functions to be called from the context of pthread_exit. i've made some care to ensure that longjmp out of a cleanup function should work, even though it is not required to. this change breaks abi compatibility with programs which were using pthread cancellation, which is unfortunate, but that's why i'm making the change now rather than later. considering that most pthread features have not been usable until recently anyway, i don't see it as a major issue at this point.
Diffstat (limited to 'include')
-rw-r--r-- | include/pthread.h | 25 |
1 files changed, 9 insertions, 16 deletions
diff --git a/include/pthread.h b/include/pthread.h index 44a71019..1b7f9fd3 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -186,24 +186,17 @@ int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); int pthread_getconcurrency(void); int pthread_setconcurrency(int); -#include <bits/pthread.h> +struct __ptcb { + void (*__f)(void *); + void *__x; + struct __ptcb *__next; +}; -int __setjmp(void *); -#ifndef __pthread_register_cancel -void __pthread_register_cancel(struct __ptcb *); -void __pthread_unregister_cancel(struct __ptcb *); -void __pthread_unwind_next(struct __ptcb *); -#endif - -#define pthread_cleanup_push(f, x) \ -do { struct __ptcb __cb; void (*__f)(void *) = (f); void *__x = (x); \ -if (__setjmp(__cb.__jb)) __f(__x), __pthread_unwind_next(&__cb); \ -__pthread_register_cancel(&__cb); { - -#define pthread_cleanup_pop(r) ; } \ -__pthread_unregister_cancel(&__cb); \ -if (r) __f(__x); } while (0) +void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *); +void _pthread_cleanup_pop(struct __ptcb *, int); +#define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); +#define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) #ifdef __cplusplus } |