aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/Darwin-x86_64-swapcontext.c
blob: c29ddb5ee16e74c4f549477efa7d656ee2940f15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "threadimpl.h"

void
makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
{
	uintptr *sp;
	va_list arg;

//fprint(2, "makecontext %d\n", argc);
	if(argc != 2)
		sysfatal("libthread: makecontext misused");
	va_start(arg, argc);
	uc->mc.di = va_arg(arg, uint);
	uc->mc.si = va_arg(arg, uint);
//fprint(2, "%ux %ux\n", uc->mc.di, uc->mc.si);
	va_end(arg);

	sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size);
	/*
	 * Stack pointer at call instruction (before return address
	 * gets pushed) must be 16-byte aligned.
	 */
	if((uintptr)sp%4)
		abort();
	while((uintptr)sp%16 != 0)
		sp--;
	*--sp = 0;  // fn's return address
	*--sp = (uintptr)fn;  // return address of setcontext
	uc->mc.sp = (uintptr)sp;
}

int
swapcontext(ucontext_t *oucp, ucontext_t *ucp)
{
	if(getcontext(oucp) == 0)
		setcontext(ucp);
	return 0;
}