futex.h
4.02 KB
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#ifndef FUTEXX_H
#define FUTEXX_H
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
static __always_inline int
futex(const int *uaddr, const int futex_op, const int val,
const struct timespec *timeout, const int *uaddr2, const unsigned int val3) {
return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
}
static __always_inline __attribute__ ((__noreturn__)) void
futex_fatal_error (const int err) {
fprintf(stderr, "The futex facility returned an unexpected error code. (%d, %d)\n", err, errno);
_exit (127);
}
static __always_inline int
futex_wait_bitset (const int *futex_word,
const int expected,
const struct timespec *abstime, const unsigned int bitset, const int priv) {
if (abstime != NULL && abstime->tv_sec < 0)
return ETIMEDOUT;
const int op = (FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME | (priv ? FUTEX_PRIVATE_FLAG : 0) );
const int err=futex(futex_word, op, expected, abstime, NULL, bitset);
if (err>=0)
return err;
switch (errno) {
case 0:
case EAGAIN:
case EINTR:
case ETIMEDOUT:
return err;
case EFAULT: /* Must have been caused by a glibc or application bug. */
case EINVAL: /* Either due to wrong alignment or due to the timeout not
being normalized. Must have been caused by a glibc or
application bug. */
case ENOSYS: /* Must have been caused by a glibc bug. */
default:
futex_fatal_error (err);
}
}
static __always_inline int
futex_wake_bitset (const int *futex_word, const int processes_to_wake, const unsigned int bitset, const int priv) {
const int op = (FUTEX_WAKE_BITSET | (priv ? FUTEX_PRIVATE_FLAG : 0) );
const int err=futex(futex_word, op, processes_to_wake, NULL, NULL, bitset);
if (err >= 0)
return err;
switch (errno) {
case EFAULT: /* Could have happened due to memory reuse. */
case EINVAL: /* Could be either due to incorrect alignment (a bug in
glibc or in the application) or due to memory being
reused for a PI futex. We cannot distinguish between the
two causes, and one of them is correct use, so we do not
act in this case. */
return err;
case ENOSYS: /* Must have been caused by a glibc bug. */
/* No other errors are documented at this time. */
default:
futex_fatal_error (err);
}
}
static __always_inline int
futex_wait (const int *futex_word,
const int expected,
const struct timespec *abstime, const int priv) {
if (abstime != NULL && abstime->tv_sec < 0)
return ETIMEDOUT;
const int op = (FUTEX_WAIT | (priv ? FUTEX_PRIVATE_FLAG : 0) );
const int err=futex(futex_word, op, expected, abstime, NULL, 0);
if (err>=0)
return err;
switch (errno) {
case 0:
case EAGAIN:
case EINTR:
case ETIMEDOUT:
return err;
case EFAULT: /* Must have been caused by a glibc or application bug. */
case EINVAL: /* Either due to wrong alignment or due to the timeout not
being normalized. Must have been caused by a glibc or
application bug. */
case ENOSYS: /* Must have been caused by a glibc bug. */
default:
futex_fatal_error (err);
}
}
static __always_inline int
futex_wake (const int *futex_word, const int processes_to_wake, const int priv) {
const int op = (FUTEX_WAKE | (priv ? FUTEX_PRIVATE_FLAG : 0) );
const int err=futex(futex_word, op, processes_to_wake, NULL, NULL, 0);
if (err >= 0)
return err;
switch (errno) {
case EFAULT: /* Could have happened due to memory reuse. */
case EINVAL: /* Could be either due to incorrect alignment (a bug in
glibc or in the application) or due to memory being
reused for a PI futex. We cannot distinguish between the
two causes, and one of them is correct use, so we do not
act in this case. */
return err;
case ENOSYS: /* Must have been caused by a glibc bug. */
/* No other errors are documented at this time. */
default:
futex_fatal_error (err);
}
}
#endif /*FUTEXX_H*/