aboutsummaryrefslogtreecommitdiffstats
path: root/core/wait.h
blob: 241eaef698f9e0086c6605f5ddd6f2cd1d4cb192 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef PURE_WAIT_H
#define PURE_WAIT_H
/* Timed waits that count on the monotonic clock. A deadline read from the
 * wall clock moves when the clock is set (by a person, or NTP): set back an
 * hour, a wait begun before lasts an hour more; set forward, it ends at once.
 * A condition made by pure_cond_monotonic waits until a time pure_wait_until
 * gives, and neither happens. (macOS has no clock for conditions: there both
 * keep to the wall clock.) */
#include <pthread.h>
#include <time.h>

#ifdef __APPLE__
#define PURE_WAIT_CLOCK CLOCK_REALTIME
#else
#define PURE_WAIT_CLOCK CLOCK_MONOTONIC
#endif

static inline int pure_cond_monotonic(pthread_cond_t *cond) {
#ifdef __APPLE__
    return pthread_cond_init(cond, NULL);
#else
    pthread_condattr_t attr;
    int result = pthread_condattr_init(&attr);
    if (result) return result;
    result = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    if (!result) result = pthread_cond_init(cond, &attr);
    pthread_condattr_destroy(&attr);
    return result;
#endif
}

/* The time ns from now, on the clock pure_cond_monotonic's conditions wait on. */
static inline struct timespec pure_wait_until(long long ns) {
    struct timespec t;
    clock_gettime(PURE_WAIT_CLOCK, &t);
    t.tv_sec += (time_t)(ns / 1000000000);
    t.tv_nsec += (long)(ns % 1000000000);
    if (t.tv_nsec >= 1000000000) {
        ++t.tv_sec;
        t.tv_nsec -= 1000000000;
    }
    return t;
}
#endif