7 /* OS dependent #incs */
12 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
13 #define printf_safe(...) {}
14 //#define printf_safe(...) \
15 pthread_mutex_lock(&lock); \
16 printf(__VA_ARGS__); \
17 pthread_mutex_unlock(&lock);
19 #define MAX_NR_TEST_THREADS 100000
20 int nr_yield_threads = 100;
21 int nr_yield_loops = 100;
23 int amt_fake_work = 0;
25 pthread_t my_threads[MAX_NR_TEST_THREADS];
26 void *my_retvals[MAX_NR_TEST_THREADS];
30 void *yield_thread(void* arg)
32 /* Wait til all threads are created */
35 for (int i = 0; i < nr_yield_loops; i++) {
36 printf_safe("[A] pthread %d %p on vcore %d, itr: %d\n", pthread_self()->id,
37 pthread_self(), vcore_id(), i);
38 /* Fakes some work by spinning a bit. Amount varies per uth/vcore,
39 * scaled by fake_work */
41 udelay(amt_fake_work * (pthread_self()->id * (vcore_id() + 1)));
43 printf_safe("[A] pthread %p returned from yield on vcore %d, itr: %d\n",
44 pthread_self(), vcore_id(), i);
46 return (void*)(pthread_self());
49 int main(int argc, char** argv)
51 struct timeval start_tv = {0};
52 struct timeval end_tv = {0};
57 nr_yield_threads = strtol(argv[1], 0, 10);
59 nr_yield_loops = strtol(argv[2], 0, 10);
61 nr_vcores = strtol(argv[3], 0, 10);
63 amt_fake_work = strtol(argv[4], 0, 10);
64 nr_yield_threads = MIN(nr_yield_threads, MAX_NR_TEST_THREADS);
65 printf("Making %d threads of %d loops each, on %d vcore(s), %d work\n",
66 nr_yield_threads, nr_yield_loops, nr_vcores, amt_fake_work);
68 /* OS dependent prep work */
70 /* Only do the vcore trickery if requested */
71 pthread_can_vcore_request(FALSE); /* 2LS won't manage vcores */
72 pthread_lib_init(); /* gives us one vcore */
73 vcore_request(nr_vcores - 1); /* ghetto incremental interface */
74 for (int i = 0; i < nr_vcores; i++) {
75 printf("Vcore %d mapped to pcore %d\n", i,
76 __procinfo.vcoremap[i].pcoreid);
80 /* create and join on yield */
81 for (int i = 0; i < nr_yield_threads; i++) {
82 printf_safe("[A] About to create thread %d\n", i);
83 if (pthread_create(&my_threads[i], NULL, &yield_thread, NULL))
84 perror("pth_create failed");
86 if (gettimeofday(&start_tv, 0))
87 perror("Start time error...");
88 ready = TRUE; /* signal to any spinning uthreads to start */
89 for (int i = 0; i < nr_yield_threads; i++) {
90 printf_safe("[A] About to join on thread %d(%p)\n", i, my_threads[i]);
91 pthread_join(my_threads[i], &my_retvals[i]);
92 printf_safe("[A] Successfully joined on thread %d (retval: %p)\n", i,
95 if (gettimeofday(&end_tv, 0))
96 perror("End time error...");
97 nr_ctx_switches = nr_yield_threads * nr_yield_loops;
98 usec_diff = (end_tv.tv_sec - start_tv.tv_sec) * 1000000 +
99 (end_tv.tv_usec - start_tv.tv_usec);
100 printf("Done: %d uthreads, %d loops, %d vcores, %d work\n",
101 nr_yield_threads, nr_yield_loops, nr_vcores, amt_fake_work);
102 printf("Nr context switches: %d\n", nr_ctx_switches);
103 printf("Time to run: %d usec\n", usec_diff);
105 printf("Context switch latency: %d nsec\n",
106 (int)(1000LL*usec_diff / nr_ctx_switches));
107 printf("Context switches / sec: %d\n\n",
108 (int)(1000000LL*nr_ctx_switches / usec_diff));