glibc-2.7 makecontext issues on x86_64
Monday, December 28th, 2009Looks like passing 64 bit values(e.g pointers) into makecontext is not working properly on x86_64. We are using makecontext for coroutines implementation and its proper working is vital for us.
I’ve been struggling with this bug for a couple of days and have finally found a solution for it. Actually the solution is trivial it was the actual process of spotting this bug which took so much time. By the way, this issue was resolved in the latest releases of glibc, so nothing to worry about if you are using gcc older than 4.2.4.
Ok, here is the solution - pass your 64 bit pointer as two ints
Here it comes:
#include <stdlib.h> #include <ucontext.h> struct Foo{}; #if defined(__GNUC__) && defined(__x86_64__) && __GNUC__ < 5 && __GNUC_MINOR__ < 3 void thread(__uint32_t p1, __uint32_t p2) { Foo* foo = (Foo*)((__uint64_t)p2 | ((__uint64_t)p1) << 32); #else void thread(Foo* foo) { #endif ... } #define FIBER_STACK 1024*64 ucontext_t child int main() { getcontext (&child); // Modify the context to a new stack child.uc_link = 0; child.uc_stack.ss_sp = malloc (FIBER_STACK); child.uc_stack.ss_size = FIBER_STACK; child.uc_stack.ss_flags = 0; Foo foo; #if defined(__GNUC__) && defined(__x86_64__) && __GNUC__ < 5 && __GNUC_MINOR__ < 3 __uint32_t p1,p2; p1 = (__uint32_t)((0x00000000FFFFFFFF) & ((__uint64_t)&foo) >> 32); p2 = (__uint32_t)(0x00000000FFFFFFFF & (__uint64_t)&foo); makecontext (&child, (void (*)())&thread, 2, p1, p2); #else makecontext (&child, (void (*)())&thread, 1, &foo); #endif }
