match glibc/lsb cancellation abi on i386
authorRich Felker <dalias@aerifal.cx>
Sat, 26 Mar 2011 02:13:57 +0000 (22:13 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 26 Mar 2011 02:13:57 +0000 (22:13 -0400)
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.

arch/i386/bits/pthread.h
include/pthread.h
src/thread/cancellation.c
src/thread/cancellation2.c [new file with mode: 0644]
src/thread/cancellation3.c [new file with mode: 0644]
src/thread/i386/cancellation2.s [new file with mode: 0644]
src/thread/i386/cancellation3.s [new file with mode: 0644]
src/thread/pthread_create.c

index 7d19065dedc1f4b144e6bbf807e96fad83e0f062..7690ea39b15c7d4d704b67bfee61d08b599264c6 100644 (file)
@@ -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
index e15f25bb9f7235accfef66bab05e617905780b3f..763336690e50c32916297d8d72b4f1bd4fd88f15 100644 (file)
@@ -181,9 +181,11 @@ int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
 #include <bits/pthread.h>
 
 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); \
index ac1af30aeaeb635725f0ceb59b0935f6493c5ffa..4976fedcb448bac52427a4dcb25bf59c333e1941 100644 (file)
@@ -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 (file)
index 0000000..e69de29
diff --git a/src/thread/cancellation3.c b/src/thread/cancellation3.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/thread/i386/cancellation2.s b/src/thread/i386/cancellation2.s
new file mode 100644 (file)
index 0000000..859aa23
--- /dev/null
@@ -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 (file)
index 0000000..210293e
--- /dev/null
@@ -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
index 785a82b87477e3afa91c033d7a53d0089b2fecfd..9f22b4cf1dab68a8bf8dc785935e830c1eeb52b8 100644 (file)
@@ -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;