#include #include #include #include #include #include int bench_nthread; int bench_niter; int grow_clock_var; pthread_barrier_t glow_clock_barrier; void bench(); // defined by user void start_thread_group(int nth, void(*f)(int tid)); void grow_clock_worker(int tid); int main(int argc, char **argv) { bench_nthread = 2; if (argc > 1) bench_nthread = atoi(argv[1]); bench_niter = 100; if (argc > 2) bench_niter = atoi(argv[2]); // Grow thread's clock. int clock_size = 10; if (argc > 1) clock_size = 1000; pthread_barrier_init(&glow_clock_barrier, 0, clock_size); start_thread_group(clock_size, grow_clock_worker); pthread_barrier_destroy(&glow_clock_barrier); __atomic_load_n(&grow_clock_var, __ATOMIC_ACQUIRE); timespec tp0; clock_gettime(CLOCK_MONOTONIC, &tp0); bench(); timespec tp1; clock_gettime(CLOCK_MONOTONIC, &tp1); unsigned long long t = (tp1.tv_sec * 1000000000ULL + tp1.tv_nsec) - (tp0.tv_sec * 1000000000ULL + tp0.tv_nsec); fprintf(stderr, "%llu ns/iter\n", t / bench_niter); fprintf(stderr, "DONE\n"); } void start_thread_group(int nth, void(*f)(int tid)) { pthread_t *th = (pthread_t*)malloc(nth * sizeof(pthread_t)); for (int i = 0; i < nth; i++) pthread_create(&th[i], 0, (void*(*)(void*))f, (void*)(long)i); for (int i = 0; i < nth; i++) pthread_join(th[i], 0); } void grow_clock_worker(int tid) { int res = pthread_barrier_wait(&glow_clock_barrier); if (res == PTHREAD_BARRIER_SERIAL_THREAD) __atomic_store_n(&grow_clock_var, 0, __ATOMIC_RELEASE); }