| /* Copyright (c) 2017 Google Inc. | 
 |  * Barret Rhoden <brho@cs.berkeley.edu> | 
 |  * See LICENSE for details. | 
 |  * | 
 |  * vthread_test: mostly create/join/vmcalls */ | 
 |  | 
 | #include <vmm/vmm.h> | 
 | #include <vmm/vthread.h> | 
 | #include <parlib/stdio.h> | 
 | #include <parlib/uthread.h> | 
 |  | 
 | enum { | 
 | 	MY_VMCALL_TEST1 = VTH_VMCALL_NEXT, | 
 | 	MY_VMCALL_TEST2, | 
 | }; | 
 |  | 
 | /* Here's how you can make your own vmcalls and still use the vth vmcalls for | 
 |  * the stuff you don't want to reimplement. */ | 
 | static bool extended_handle_vmcall(struct guest_thread *gth, | 
 |                                    struct vm_trapframe *vm_tf) | 
 | { | 
 | 	switch (vm_tf->tf_rax) { | 
 | 	case MY_VMCALL_TEST1: | 
 | 		goto out_ok; | 
 | 	} | 
 | 	return vth_handle_vmcall(gth, vm_tf); | 
 | out_ok: | 
 | 	vm_tf->tf_rip += 3; | 
 | 	return TRUE; | 
 | }; | 
 |  | 
 | static struct virtual_machine vm = {.vmcall = extended_handle_vmcall, | 
 |                                     .mtx = UTH_MUTEX_INIT}; | 
 |  | 
 | static void thread_entry(void *arg) | 
 | { | 
 | 	const char nums[] = "123456789"; | 
 |  | 
 | 	for (int i = 0; i < sizeof(nums); i++) | 
 | 		vmcall(VTH_VMCALL_PRINTC, nums[i]); | 
 | 	vmcall(MY_VMCALL_TEST1); | 
 | 	vmcall(VTH_VMCALL_EXIT, arg, 0, 0, 0); | 
 | } | 
 |  | 
 | int main(int argc, char **argv) | 
 | { | 
 | 	#define NR_VTHS 5 | 
 | 	struct vthread *vths[NR_VTHS]; | 
 | 	void *retvals[NR_VTHS]; | 
 |  | 
 | 	/* Tests multiple threads at once */ | 
 | 	for (long i = 0; i < NR_VTHS; i++) | 
 | 		vths[i] = vthread_create(&vm, thread_entry, (void*)i); | 
 | 	for (long i = 0; i < NR_VTHS; i++) { | 
 | 		vthread_join(vths[i], &retvals[i]); | 
 | 		assert(retvals[i] == (void*)i); | 
 | 	} | 
 |  | 
 | 	/* Tests reuse / GPC leakage */ | 
 | 	for (long i = 0; i < NR_VTHS * 2; i++) { | 
 | 		vths[0] = vthread_create(&vm, thread_entry, (void*)i); | 
 | 		vthread_join(vths[0], &retvals[0]); | 
 | 		assert(retvals[0] == (void*)i); | 
 | 	} | 
 | 	assert(vm.nr_gpcs == NR_VTHS); | 
 |  | 
 | 	return 0; | 
 | } |