Pthread sleep
[mirrors/Programs.git] / c / pthread_extra / pthread_sleep.c
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 }
This page took 0.277786 seconds and 4 git commands to generate.