Commit Diff


commit - ded42a6ea9fe737c4a6ce18f318086740401cc16
commit + 86502504820d9626542a310fd48b50ff760ec279
blob - 6c31cb76ba8d1f0107b0ebe008f30e4b3937e5be
blob + dfc0acdfa6f37dfa8a26e7317f3b3489664d5454
--- src/libthread/thread.c
+++ src/libthread/thread.c
@@ -77,11 +77,16 @@ procalloc(void)
 }
 
 static void
-threadstart(void *v)
+threadstart(uint y, uint x)
 {
 	_Thread *t;
+	ulong z;
 
-	t = v;
+	z = x<<16;	/* hide undefined 32-bit shift from 32-bit compilers */
+	z <<= 16;
+	z |= y;
+	t = (_Thread*)z;
+
 //print("threadstart %p\n", v);
 	t->startfn(t->startarg);
 //print("threadexits %p\n", v);
@@ -94,6 +99,8 @@ threadalloc(void (*fn)(void*), void *arg, uint stack)
 {
 	_Thread *t;
 	sigset_t zero;
+	uint x, y;
+	ulong z;
 
 	/* allocate the task and stack together */
 	t = malloc(sizeof *t+stack);
@@ -125,7 +132,16 @@ threadalloc(void (*fn)(void*), void *arg, uint stack)
 		(char*)t->context.uc.uc_stack.ss_sp
 		+t->context.uc.uc_stack.ss_size;
 #endif
-	makecontext(&t->context.uc, (void(*)())threadstart, 1, t);
+	/*
+	 * All this magic is because you have to pass makecontext a
+	 * function that takes some number of word-sized variables,
+	 * and on 64-bit machines pointers are bigger than words.
+	 */
+	z = (ulong)t;
+	y = z;
+	z >>= 16;	/* hide undefined 32-bit shift from 32-bit compilers */
+	x = z>>16;
+	makecontext(&t->context.uc, (void(*)())threadstart, 2, y, x);
 
 	return t;
 }