|  | #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); | 
|  | } |