rendered paste body#include <stdio.h>#include <time.h>#include <signal.h>#include <string.h>#include <sys/select.h>#include <unistd.h>#include <stdint.h>uint64_t my_get_time_us(){ struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;}uint64_t *records;int pos = 0;int iterations = 0;void record_time(){ if (pos < iterations) records[pos ++] = my_get_time_us();}void report(const char *name){ printf("'%s': [", name); int i; for (i = 0; i < iterations; ++i) { printf("%llu, ", (unsigned long long)records[i]); } printf("],\n"); memset(records, 0, iterations * sizeof(uint64_t)); pos = 0;}void my_sleep_1(uint64_t us){ struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = us * 1000; clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);}void my_sleep_2(uint64_t us){ struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = us * 1000; nanosleep(&ts, NULL);}void my_sleep_3(uint64_t us){ usleep(us);}void my_sleep_4(uint64_t us){ struct timeval tv; tv.tv_sec = 0; tv.tv_usec = us; select(0, NULL, NULL, NULL, &tv);}struct timespec abs_start;void my_sleep_abs_init(){ clock_gettime(CLOCK_MONOTONIC, &abs_start);}void my_sleep_abs(uint64_t us){ struct timespec ts = abs_start; ts.tv_sec += (us / 1000000); ts.tv_nsec += (us % 1000000 * 1000); if (ts.tv_nsec >= 1000000000) { ts.tv_sec += 1; ts.tv_nsec -= 1000000000; } clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL);}timer_t timer_id;void my_timer_handler(int sig, siginfo_t *si, void *uc){ record_time();}void my_timer_init(){ struct sigaction sa; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = my_timer_handler; sigemptyset(&sa.sa_mask); sigaction(SIGRTMIN, &sa, NULL); struct sigevent sig; sig.sigev_notify = SIGEV_SIGNAL; sig.sigev_signo = SIGRTMIN; sig.sigev_value.sival_ptr = &timer_id; timer_create(CLOCK_MONOTONIC, &sig, &timer_id);}void my_timer_set(uint64_t us){ struct itimerspec its; its.it_value.tv_sec = 0; its.it_value.tv_nsec = us * 1000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; timer_settime(timer_id, 0, &its, NULL);}void run_sleep(void (* sleep_func)(uint64_t us), uint64_t us){ uint64_t ts = my_get_time_us(); int i; for (i = 0; i < iterations; ++i) { ts += us; uint64_t now = my_get_time_us(); if (ts > now) sleep_func(ts - now); record_time(); }}void run_sleep_abs(uint64_t us){ uint64_t ts = 0; int i; my_sleep_abs_init(); for (i = 0; i < iterations; ++i) { ts += us; my_sleep_abs(ts); record_time(); }}void run_timer(uint64_t us){ my_timer_init(); my_timer_set(us); int i; for (i = 0; i < iterations; ++i) { pause(); } my_timer_set(0);}void run(int us){ run_sleep(my_sleep_1, us); report("clock_nanosleep"); run_sleep(my_sleep_2, us); report("nanosleep"); run_sleep(my_sleep_4, us); report("select"); run_sleep_abs(us); report("clock_nanosleep_TIMER_ABSTIME"); run_timer(us); report("signal");}int main(int argc, char **argv){ uint64_t interval = argc > 1 ? atoi(argv[1]) : 1000; iterations = argc > 2 ? atoi(argv[2]) : 1000; records = calloc(iterations, sizeof(uint64_t)); run(interval); return 0;}