1 /* Copyright (c) 2014 The Regents of the University of California
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * See LICENSE for details.
5 * Basic pthread switcher, bypassing the 2LS. Use for benchmarking and
13 #include "misc-compat.h"
16 int nr_switch_loops = 100;
18 bool should_exit = FALSE;
20 static void __pth_switch_cb(struct uthread *uthread, void *target)
22 /* by not returning, this bypasses vcore entry and event checks, though when
23 * we pop back out of the 2LS, we'll check notif pending. think about this
24 * if you put this into your 2LS. */
25 current_uthread = NULL;
26 run_uthread((struct uthread*)target);
30 static void pth_switch_to(struct pthread_tcb *target)
32 uthread_yield(TRUE, __pth_switch_cb, target);
35 void *switch_thread(void *arg)
37 pthread_t other_thr = *(pthread_t*)arg;
41 for (int i = 0; i < nr_switch_loops; i++) {
45 pth_switch_to(other_thr);
47 if (pthread_self() == th1) {
48 /* we need to break out of the switching cycle. when th2 runs again,
49 * it'll know to stop. but th1 needs to both exit and switch to th2.
50 * we do this by making th2 runnable by the pth schedop, then exiting */
52 /* we also need to do this to th2 before it tries to exit, o/w we'll PF
53 * in __pthread_generic_yield. */
54 sched_ops->thread_runnable((struct uthread*)th2);
59 int main(int argc, char** argv)
61 struct timeval start_tv = {0};
62 struct timeval end_tv = {0};
68 nr_switch_loops = strtol(argv[1], 0, 10);
69 printf("Making 2 threads of %d switches each\n", nr_switch_loops);
71 pthread_can_vcore_request(FALSE); /* 2LS won't manage vcores */
72 pthread_need_tls(FALSE);
73 pthread_lib_init(); /* gives us one vcore */
75 /* each is passed the other's pthread_t. th1 starts the switching. */
76 if (pthread_create(&th1, NULL, &switch_thread, &th2))
77 perror("pth_create 1 failed");
78 /* thread 2 is created, but not put on the runnable list */
79 if (__pthread_create(&th2, NULL, &switch_thread, &th1))
80 perror("pth_create 2 failed");
82 if (gettimeofday(&start_tv, 0))
83 perror("Start time error...");
85 ready = TRUE; /* signal to any spinning uthreads to start */
87 pthread_join(th1, &join_ret);
88 pthread_join(th2, &join_ret);
90 if (gettimeofday(&end_tv, 0))
91 perror("End time error...");
92 nr_ctx_switches = 2 * nr_switch_loops;
93 usec_diff = (end_tv.tv_sec - start_tv.tv_sec) * 1000000 +
94 (end_tv.tv_usec - start_tv.tv_usec);
95 printf("Done: %d loops\n", nr_switch_loops);
96 printf("Nr context switches: %ld\n", nr_ctx_switches);
97 printf("Time to run: %ld usec\n", usec_diff);
98 printf("Context switch latency: %d nsec\n",
99 (int)(1000LL*usec_diff / nr_ctx_switches));
100 printf("Context switches / sec: %d\n\n",
101 (int)(1000000LL*nr_ctx_switches / usec_diff));