From: Rich Felker Date: Sat, 26 Mar 2011 02:13:57 +0000 (-0400) Subject: match glibc/lsb cancellation abi on i386 X-Git-Tag: v0.7.5~38 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ea343364a719add2cd8adf8a50c15bb5f9400dd8;p=oweals%2Fmusl.git match glibc/lsb cancellation abi on i386 glibc made the ridiculous choice to use pass-by-register calling convention for these functions, which is impossible to duplicate directly on non-gcc compilers. instead, we use ugly asm to wrap and convert the calling convention. presumably this works with every compiler anyone could potentially want to use. --- diff --git a/arch/i386/bits/pthread.h b/arch/i386/bits/pthread.h index 7d19065d..7690ea39 100644 --- a/arch/i386/bits/pthread.h +++ b/arch/i386/bits/pthread.h @@ -4,3 +4,22 @@ struct __ptcb { struct __ptcb *__next; void *__ptrs[3]; }; + +static inline void __pthread_register_cancel_2(struct __ptcb *__cb) +{ + __asm__ __volatile__( "call __pthread_register_cancel" : : "a"(__cb) ); +} + +static inline void __pthread_unregister_cancel_2(struct __ptcb *__cb) +{ + __asm__ __volatile__( "call __pthread_unregister_cancel" : : "a"(__cb) ); +} + +static inline void __pthread_unwind_next_2(struct __ptcb *__cb) +{ + __asm__ __volatile__( "call __pthread_unwind_next" : : "a"(__cb) ); +} + +#define __pthread_register_cancel __pthread_register_cancel_2 +#define __pthread_unregister_cancel __pthread_unregister_cancel_2 +#define __pthread_unwind_next __pthread_unwind_next_2 diff --git a/include/pthread.h b/include/pthread.h index e15f25bb..76333669 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -181,9 +181,11 @@ int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); #include 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); \ diff --git a/src/thread/cancellation.c b/src/thread/cancellation.c index ac1af30a..4976fedc 100644 --- a/src/thread/cancellation.c +++ b/src/thread/cancellation.c @@ -1,5 +1,12 @@ #include "pthread_impl.h" +#ifdef __pthread_register_cancel +#undef __pthread_register_cancel +#undef __pthread_unregister_cancel +#define __pthread_register_cancel __pthread_register_cancel_3 +#define __pthread_unregister_cancel __pthread_unregister_cancel_3 +#endif + void __pthread_register_cancel(struct __ptcb *cb) { struct pthread *self = pthread_self(); diff --git a/src/thread/cancellation2.c b/src/thread/cancellation2.c new file mode 100644 index 00000000..e69de29b diff --git a/src/thread/cancellation3.c b/src/thread/cancellation3.c new file mode 100644 index 00000000..e69de29b diff --git a/src/thread/i386/cancellation2.s b/src/thread/i386/cancellation2.s new file mode 100644 index 00000000..859aa239 --- /dev/null +++ b/src/thread/i386/cancellation2.s @@ -0,0 +1,16 @@ +.text +.global __pthread_register_cancel +.type __pthread_register_cancel,%function +__pthread_register_cancel: + pushl %eax + call __pthread_register_cancel_3 + popl %eax + ret + +.global __pthread_unregister_cancel +.type __pthread_unregister_cancel,%function +__pthread_unregister_cancel: + pushl %eax + call __pthread_unregister_cancel_3 + popl %eax + ret diff --git a/src/thread/i386/cancellation3.s b/src/thread/i386/cancellation3.s new file mode 100644 index 00000000..210293e2 --- /dev/null +++ b/src/thread/i386/cancellation3.s @@ -0,0 +1,8 @@ +.text +.global __pthread_unwind_next +.type __pthread_unwind_next,%function +__pthread_unwind_next: + pushl %eax + call __pthread_unwind_next_3 + popl %eax + ret diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 785a82b8..9f22b4cf 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -1,5 +1,10 @@ #include "pthread_impl.h" +#ifdef __pthread_unwind_next +#undef __pthread_unwind_next +#define __pthread_unwind_next __pthread_unwind_next_3 +#endif + void __pthread_unwind_next(struct __ptcb *cb) { int i, j, not_finished;