#include #include #include #include pthread_mutex_t my_mutex; unsigned long long stamp(void) { struct timeval tv; gettimeofday(&tv, NULL); return (unsigned long long)tv.tv_sec * 1000000 + tv.tv_usec; } void consume(int spin, int total) { unsigned long long begin, now; begin = stamp(); for (;;) { pthread_mutex_lock(&my_mutex); now = stamp(); if ((long long)(now - begin) > spin) { pthread_mutex_unlock(&my_mutex); usleep(total - spin); pthread_mutex_lock(&my_mutex); begin += total; } pthread_mutex_unlock(&my_mutex); } } struct my_data { int spin; int total; }; void *my_fn_sleepy(void *arg) { struct my_data *data = (struct my_data *)arg; consume(data->spin, data->total); return NULL; } void *my_fn_loop(void *arg) { while (1) {}; return NULL; } int main(int argc, char **argv) { int period = 100000; /* 100ms */ int frac; struct my_data data; pthread_t last_thread; int thread_num = sysconf(_SC_NPROCESSORS_ONLN) / 2; void *(*my_fn)(void *arg) = &my_fn_sleepy; if (thread_num <= 0 || thread_num > 1024) { fprintf(stderr, "insane processor(half) size %d\n", thread_num); return -1; } if (argc == 2 && !strcmp(argv[1], "-l")) { my_fn = &my_fn_loop; printf("loop mode enabled\n"); goto loop_mode; } if (argc < 2) { fprintf(stderr, "%s []\n" " frac -- [1-100] %% of time to burn\n" " period -- [usec] period of burn/sleep cycle\n", argv[0]); return -1; } frac = atoi(argv[1]); if (argc > 2) period = atoi(argv[2]); if (frac > 100) frac = 100; if (frac < 1) frac = 1; data.spin = (period * frac) / 100; data.total = period; loop_mode: pthread_mutex_init(&my_mutex, NULL); while (thread_num--) { if (pthread_create(&last_thread, NULL, my_fn, &data)) { fprintf(stderr, "Create thread failed\n"); return -1; } } printf("Threads never stop, CTRL + C to terminate\n"); pthread_join(last_thread, NULL); pthread_mutex_destroy(&my_mutex); //won't happen return 0; }