#include // printf, puts, perror #include // memset #include // sleep #include // sig* #include // sched_setscheduler #include // clock_gettime, timer_* #define ZERO(type, name) type name; memset(&name, 0, sizeof name) #define SIG_TIMER_EXPIRATION SIGRTMIN #define CLOCK_TYPE CLOCK_MONOTONIC void set_SCHED_RR(void) { ZERO(struct sched_param, param); param.sched_priority = 66; if (sched_setscheduler(0, SCHED_RR, ¶m) != 0) perror("sched_setscheduler"); } struct timespec get_time_stamp(void) { ZERO(struct timespec, now); if (clock_gettime(CLOCK_TYPE, &now) != 0) perror("clock_gettime"); printf("NOW=%ld.%09ld\n", now.tv_sec, now.tv_nsec); return now; } int main(void) { set_SCHED_RR(); sigset_t set; sigemptyset(&set); sigaddset(&set, SIG_TIMER_EXPIRATION); sigprocmask(SIG_BLOCK, &set, NULL); ZERO(struct timespec, reso); if (clock_getres(CLOCK_TYPE, &reso) != 0) perror("clock_getres"); printf("RESOLUTION=%ld ns\n", reso.tv_sec*1000000000+reso.tv_nsec); timer_t timer; ZERO(struct sigevent, event); event.sigev_notify = SIGEV_SIGNAL; event.sigev_signo = SIG_TIMER_EXPIRATION; if (timer_create(CLOCK_TYPE, &event, &timer) != 0) perror("timer_create"); sigset_t pending; struct timespec H = get_time_stamp(); puts("SLEEPING 1 SECOND..."); sleep(1); /* H is now 1 second in the past. */ get_time_stamp(); ZERO(struct itimerspec, spec); spec.it_value = H; if (timer_settime(timer, TIMER_ABSTIME, &spec, NULL) != 0) perror("timer_settime"); if (sigpending(&pending) != 0) perror("sigpending"); int res=sigismember(&pending, SIG_TIMER_EXPIRATION); if (res < 0) perror("sigismember"); else if (res) puts("TIMER HAS ALREADY FIRED."); struct timespec H1 = get_time_stamp(); sigwaitinfo(&set, NULL); struct timespec H2 = get_time_stamp(); int nsdiff = (H2.tv_sec-H1.tv_sec)*1000000000 + (H2.tv_nsec-H1.tv_nsec); printf("nsdiff=%d ns i.e. %d ms\n", nsdiff, nsdiff/1000000); return 0; }