| #include <utest/utest.h> | 
 | #include <pthread.h> | 
 | #include <parlib/pvcalarm.h> | 
 |  | 
 | TEST_SUITE("PVCALARMS"); | 
 |  | 
 | /* <--- Begin definition of test cases ---> */ | 
 | bool test_pvcalarms(void) { | 
 | 	const int INTERVAL = 10000; | 
 | 	const int ITERS = 100; | 
 | 	int count[max_vcores()]; | 
 | 	void pvcalarm_callback() | 
 | 	{ | 
 | 		__sync_fetch_and_add(&count[vcore_id()], 1); | 
 | 	} | 
 |  | 
 | 	parlib_never_yield = TRUE; | 
 | 	pthread_mcp_init(); | 
 | 	vcore_request_total(max_vcores()); | 
 | 	parlib_never_vc_request = TRUE; | 
 | 	for (int i = 0; i < max_vcores(); i++) | 
 | 		count[i] = 0; | 
 | 	 | 
 | 	uint64_t now, then; | 
 | 	now = tsc2usec(read_tsc()); | 
 | 	enable_pvcalarms(PVCALARM_PROF, INTERVAL, pvcalarm_callback); | 
 | 	for (int i = 0; i < max_vcores(); i++) | 
 | 		while(count[i] < ITERS) | 
 | 			cpu_relax(); | 
 | 	disable_pvcalarms(); | 
 | 	then = tsc2usec(read_tsc()); | 
 |  | 
 | 	UT_ASSERT_M("Alarms finished too soon", then > (now + INTERVAL*ITERS)); | 
 | 	UT_ASSERT_M("Alarms finished too late", then < (now + | 
 | 							2*INTERVAL*ITERS)); | 
 | 	return true; | 
 | } | 
 |  | 
 | bool test_sigperf(void) | 
 | { | 
 | 	const int INTERVAL = 10000; | 
 | 	const int ITERATIONS = 100; | 
 | 	const int NUM_PTHREADS = 10; | 
 | 	int count[NUM_PTHREADS]; | 
 | 	pthread_t threads[NUM_PTHREADS]; | 
 | 	static __thread int *__count; | 
 |  | 
 | 	void *thread_handler(void *arg) | 
 | 	{ | 
 | 		__count = (int*)arg; | 
 | 		sigset_t s; | 
 | 		sigemptyset(&s); | 
 | 		sigaddset(&s, SIGPROF); | 
 | 		pthread_sigmask(SIG_UNBLOCK, &s, NULL); | 
 | 		int old_count = 0, new_count = 0; | 
 | 		while(1) { | 
 | 			while ((new_count = atomic_read((atomic_t)__count)) <= | 
 | 			      old_count); | 
 | 			if (new_count >= ITERATIONS) | 
 | 				break; | 
 | 			old_count = new_count; | 
 | 			pthread_yield(); | 
 | 		} | 
 | 		return 0; | 
 | 	} | 
 | 	void signal_handler(int signo) | 
 | 	{ | 
 | 		assert(signo == SIGPROF); | 
 | 		__sync_fetch_and_add(__count, 1); | 
 | 	} | 
 |  | 
 | 	parlib_never_yield = FALSE; | 
 | 	parlib_never_vc_request = FALSE; | 
 |  | 
 | 	sigset_t s; | 
 | 	sigemptyset(&s); | 
 | 	sigaddset(&s, SIGPROF); | 
 | 	pthread_sigmask(SIG_BLOCK, &s, NULL); | 
 | 	struct sigaction sigact = {.sa_handler = signal_handler, 0}; | 
 |  | 
 | 	sigaction(SIGPROF, &sigact, 0); | 
 | 	for (int i = 0; i < NUM_PTHREADS; i++) | 
 | 		count[i] = 0; | 
 |  | 
 | 	enable_profalarm(INTERVAL); | 
 | 	for (int i = 0; i < NUM_PTHREADS; i++) | 
 | 		pthread_create(&threads[i], NULL, thread_handler, &count[i]); | 
 |  | 
 | 	for (int i = 0; i < NUM_PTHREADS; i++) | 
 | 		while (count[i] < ITERATIONS) | 
 | 			cpu_relax(); | 
 |  | 
 | 	disable_pvcalarms(); | 
 | 	return true; | 
 | } | 
 |  | 
 | /* <--- End definition of test cases ---> */ | 
 |  | 
 | struct utest utests[] = { | 
 | 	UTEST_REG(pvcalarms), | 
 | 	UTEST_REG(sigperf), | 
 | }; | 
 | int num_utests = sizeof(utests) / sizeof(struct utest); | 
 |  | 
 | int main(int argc, char *argv[]) { | 
 | 	char **whitelist = &argv[1]; | 
 | 	int whitelist_len = argc - 1; | 
 |  | 
 | 	RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len); | 
 | } |