1 #include <pthread.h> 2 #include <stdlib.h> 3 #include <stddef.h> 4 #include <unistd.h> 5 #include <stdio.h> 6 #include <time.h> 7 8 int bench_nthread; 9 int bench_niter; 10 int grow_clock_var; 11 pthread_barrier_t glow_clock_barrier; 12 13 void bench(); // defined by user 14 void start_thread_group(int nth, void(*f)(int tid)); 15 void grow_clock_worker(int tid); 16 17 int main(int argc, char **argv) { 18 bench_nthread = 2; 19 if (argc > 1) 20 bench_nthread = atoi(argv[1]); 21 bench_niter = 100; 22 if (argc > 2) 23 bench_niter = atoi(argv[2]); 24 25 // Grow thread's clock. 26 int clock_size = 10; 27 if (argc > 1) 28 clock_size = 1000; 29 pthread_barrier_init(&glow_clock_barrier, 0, clock_size); 30 start_thread_group(clock_size, grow_clock_worker); 31 pthread_barrier_destroy(&glow_clock_barrier); 32 __atomic_load_n(&grow_clock_var, __ATOMIC_ACQUIRE); 33 34 timespec tp0; 35 clock_gettime(CLOCK_MONOTONIC, &tp0); 36 bench(); 37 timespec tp1; 38 clock_gettime(CLOCK_MONOTONIC, &tp1); 39 unsigned long long t = 40 (tp1.tv_sec * 1000000000ULL + tp1.tv_nsec) - 41 (tp0.tv_sec * 1000000000ULL + tp0.tv_nsec); 42 fprintf(stderr, "%llu ns/iter\n", t / bench_niter); 43 fprintf(stderr, "DONE\n"); 44 } 45 46 void start_thread_group(int nth, void(*f)(int tid)) { 47 pthread_t *th = (pthread_t*)malloc(nth * sizeof(pthread_t)); 48 for (int i = 0; i < nth; i++) 49 pthread_create(&th[i], 0, (void*(*)(void*))f, (void*)(long)i); 50 for (int i = 0; i < nth; i++) 51 pthread_join(th[i], 0); 52 } 53 54 void grow_clock_worker(int tid) { 55 int res = pthread_barrier_wait(&glow_clock_barrier); 56 if (res == PTHREAD_BARRIER_SERIAL_THREAD) 57 __atomic_store_n(&grow_clock_var, 0, __ATOMIC_RELEASE); 58 } 59 60