Commit | Line | Data |
---|---|---|
f6132c99 TM |
1 | #include <pthread_extra.h> |
2 | #include <time.h> | |
3 | #include <errno.h> | |
4 | ||
5 | #define NSEC_PER_SEC (1000*1000*1000) | |
6 | // timespec_normalise() from https://github.com/solemnwarning/timespec/ | |
7 | struct timespec timespec_normalise(struct timespec ts) | |
8 | { | |
9 | while(ts.tv_nsec >= NSEC_PER_SEC) { | |
10 | ++(ts.tv_sec); ts.tv_nsec -= NSEC_PER_SEC; | |
11 | } | |
12 | while(ts.tv_nsec <= -NSEC_PER_SEC) { | |
13 | --(ts.tv_sec); ts.tv_nsec += NSEC_PER_SEC; | |
14 | } | |
15 | if(ts.tv_nsec < 0) { // Negative nanoseconds isn't valid according to POSIX. | |
16 | --(ts.tv_sec); ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec); | |
17 | } | |
18 | return ts; | |
19 | } | |
20 | ||
21 | void pthread_nanosleep(struct timespec t) { | |
22 | //Sleep calls on Linux get interrupted by signals, causing premature wake | |
23 | //Pthread (un)pause is built using signals | |
24 | //Therefore we need self-restarting sleep implementation | |
25 | //IO timeouts are restarted by SA_RESTART, but sleeps do need explicit restart | |
26 | //We also need to sleep using absolute time, because relative time is paused | |
27 | //You should use this in any thread that gets (un)paused | |
28 | ||
29 | struct timespec wake; | |
30 | clock_gettime(CLOCK_MONOTONIC, &wake); | |
31 | ||
32 | t = timespec_normalise(t); | |
33 | wake.tv_sec += t.tv_sec; | |
34 | wake.tv_nsec += t.tv_nsec; | |
35 | wake = timespec_normalise(wake); | |
36 | ||
37 | while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake, NULL)) if(errno!=EINTR) break; | |
38 | return; | |
39 | } | |
40 | void pthread_nsleep(time_t s, long ns) { | |
41 | struct timespec t; | |
42 | t.tv_sec = s; | |
43 | t.tv_nsec = ns; | |
44 | pthread_nanosleep(t); | |
45 | } | |
46 | ||
47 | void pthread_sleep(time_t s) { | |
48 | pthread_nsleep(s, 0); | |
49 | } |