1*bbecb9d1SAndroid Build Coastguard Worker /*
2*bbecb9d1SAndroid Build Coastguard Worker * Copyright © 2015 Intel
3*bbecb9d1SAndroid Build Coastguard Worker *
4*bbecb9d1SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*bbecb9d1SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*bbecb9d1SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*bbecb9d1SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*bbecb9d1SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*bbecb9d1SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*bbecb9d1SAndroid Build Coastguard Worker *
11*bbecb9d1SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*bbecb9d1SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*bbecb9d1SAndroid Build Coastguard Worker * Software.
14*bbecb9d1SAndroid Build Coastguard Worker *
15*bbecb9d1SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*bbecb9d1SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*bbecb9d1SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*bbecb9d1SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*bbecb9d1SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*bbecb9d1SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*bbecb9d1SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*bbecb9d1SAndroid Build Coastguard Worker */
23*bbecb9d1SAndroid Build Coastguard Worker
24*bbecb9d1SAndroid Build Coastguard Worker #ifndef UTIL_FUTEX_H
25*bbecb9d1SAndroid Build Coastguard Worker #define UTIL_FUTEX_H
26*bbecb9d1SAndroid Build Coastguard Worker
27*bbecb9d1SAndroid Build Coastguard Worker #if defined(HAVE_LINUX_FUTEX_H)
28*bbecb9d1SAndroid Build Coastguard Worker #define UTIL_FUTEX_SUPPORTED 1
29*bbecb9d1SAndroid Build Coastguard Worker
30*bbecb9d1SAndroid Build Coastguard Worker #include <limits.h>
31*bbecb9d1SAndroid Build Coastguard Worker #include <stdint.h>
32*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
33*bbecb9d1SAndroid Build Coastguard Worker #include <linux/futex.h>
34*bbecb9d1SAndroid Build Coastguard Worker #include <sys/syscall.h>
35*bbecb9d1SAndroid Build Coastguard Worker #include <sys/time.h>
36*bbecb9d1SAndroid Build Coastguard Worker
sys_futex(void * addr1,int op,int val1,const struct timespec * timeout,void * addr2,int val3)37*bbecb9d1SAndroid Build Coastguard Worker static inline long sys_futex(void *addr1, int op, int val1, const struct timespec *timeout, void *addr2, int val3)
38*bbecb9d1SAndroid Build Coastguard Worker {
39*bbecb9d1SAndroid Build Coastguard Worker return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
40*bbecb9d1SAndroid Build Coastguard Worker }
41*bbecb9d1SAndroid Build Coastguard Worker
futex_wake(uint32_t * addr,int count)42*bbecb9d1SAndroid Build Coastguard Worker static inline int futex_wake(uint32_t *addr, int count)
43*bbecb9d1SAndroid Build Coastguard Worker {
44*bbecb9d1SAndroid Build Coastguard Worker return sys_futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
45*bbecb9d1SAndroid Build Coastguard Worker }
46*bbecb9d1SAndroid Build Coastguard Worker
futex_wait(uint32_t * addr,int32_t value,const struct timespec * timeout)47*bbecb9d1SAndroid Build Coastguard Worker static inline int futex_wait(uint32_t *addr, int32_t value, const struct timespec *timeout)
48*bbecb9d1SAndroid Build Coastguard Worker {
49*bbecb9d1SAndroid Build Coastguard Worker /* FUTEX_WAIT_BITSET with FUTEX_BITSET_MATCH_ANY is equivalent to
50*bbecb9d1SAndroid Build Coastguard Worker * FUTEX_WAIT, except that it treats the timeout as absolute. */
51*bbecb9d1SAndroid Build Coastguard Worker return sys_futex(addr, FUTEX_WAIT_BITSET, value, timeout, NULL,
52*bbecb9d1SAndroid Build Coastguard Worker FUTEX_BITSET_MATCH_ANY);
53*bbecb9d1SAndroid Build Coastguard Worker }
54*bbecb9d1SAndroid Build Coastguard Worker
55*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__FreeBSD__)
56*bbecb9d1SAndroid Build Coastguard Worker #define UTIL_FUTEX_SUPPORTED 1
57*bbecb9d1SAndroid Build Coastguard Worker
58*bbecb9d1SAndroid Build Coastguard Worker #include <assert.h>
59*bbecb9d1SAndroid Build Coastguard Worker #include <errno.h>
60*bbecb9d1SAndroid Build Coastguard Worker #include <fcntl.h>
61*bbecb9d1SAndroid Build Coastguard Worker #include <sys/types.h>
62*bbecb9d1SAndroid Build Coastguard Worker #include <sys/umtx.h>
63*bbecb9d1SAndroid Build Coastguard Worker #include <sys/time.h>
64*bbecb9d1SAndroid Build Coastguard Worker
futex_wake(uint32_t * addr,int count)65*bbecb9d1SAndroid Build Coastguard Worker static inline int futex_wake(uint32_t *addr, int count)
66*bbecb9d1SAndroid Build Coastguard Worker {
67*bbecb9d1SAndroid Build Coastguard Worker assert(count == (int)(uint32_t)count); /* Check that bits weren't discarded */
68*bbecb9d1SAndroid Build Coastguard Worker return _umtx_op(addr, UMTX_OP_WAKE, (uint32_t)count, NULL, NULL) == -1 ? errno : 0;
69*bbecb9d1SAndroid Build Coastguard Worker }
70*bbecb9d1SAndroid Build Coastguard Worker
futex_wait(uint32_t * addr,int32_t value,struct timespec * timeout)71*bbecb9d1SAndroid Build Coastguard Worker static inline int futex_wait(uint32_t *addr, int32_t value, struct timespec *timeout)
72*bbecb9d1SAndroid Build Coastguard Worker {
73*bbecb9d1SAndroid Build Coastguard Worker void *uaddr = NULL, *uaddr2 = NULL;
74*bbecb9d1SAndroid Build Coastguard Worker struct _umtx_time tmo = {
75*bbecb9d1SAndroid Build Coastguard Worker ._flags = UMTX_ABSTIME,
76*bbecb9d1SAndroid Build Coastguard Worker ._clockid = CLOCK_MONOTONIC
77*bbecb9d1SAndroid Build Coastguard Worker };
78*bbecb9d1SAndroid Build Coastguard Worker
79*bbecb9d1SAndroid Build Coastguard Worker assert(value == (int)(uint32_t)value); /* Check that bits weren't discarded */
80*bbecb9d1SAndroid Build Coastguard Worker
81*bbecb9d1SAndroid Build Coastguard Worker if (timeout != NULL) {
82*bbecb9d1SAndroid Build Coastguard Worker tmo._timeout = *timeout;
83*bbecb9d1SAndroid Build Coastguard Worker uaddr = (void *)(uintptr_t)sizeof(tmo);
84*bbecb9d1SAndroid Build Coastguard Worker uaddr2 = (void *)&tmo;
85*bbecb9d1SAndroid Build Coastguard Worker }
86*bbecb9d1SAndroid Build Coastguard Worker
87*bbecb9d1SAndroid Build Coastguard Worker return _umtx_op(addr, UMTX_OP_WAIT_UINT, (uint32_t)value, uaddr, uaddr2) == -1 ? errno : 0;
88*bbecb9d1SAndroid Build Coastguard Worker }
89*bbecb9d1SAndroid Build Coastguard Worker
90*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__OpenBSD__)
91*bbecb9d1SAndroid Build Coastguard Worker #define UTIL_FUTEX_SUPPORTED 1
92*bbecb9d1SAndroid Build Coastguard Worker
93*bbecb9d1SAndroid Build Coastguard Worker #include <sys/time.h>
94*bbecb9d1SAndroid Build Coastguard Worker #include <sys/futex.h>
95*bbecb9d1SAndroid Build Coastguard Worker
futex_wake(uint32_t * addr,int count)96*bbecb9d1SAndroid Build Coastguard Worker static inline int futex_wake(uint32_t *addr, int count)
97*bbecb9d1SAndroid Build Coastguard Worker {
98*bbecb9d1SAndroid Build Coastguard Worker return futex(addr, FUTEX_WAKE, count, NULL, NULL);
99*bbecb9d1SAndroid Build Coastguard Worker }
100*bbecb9d1SAndroid Build Coastguard Worker
futex_wait(uint32_t * addr,int32_t value,const struct timespec * timeout)101*bbecb9d1SAndroid Build Coastguard Worker static inline int futex_wait(uint32_t *addr, int32_t value, const struct timespec *timeout)
102*bbecb9d1SAndroid Build Coastguard Worker {
103*bbecb9d1SAndroid Build Coastguard Worker struct timespec tsnow, tsrel;
104*bbecb9d1SAndroid Build Coastguard Worker
105*bbecb9d1SAndroid Build Coastguard Worker if (timeout == NULL)
106*bbecb9d1SAndroid Build Coastguard Worker return futex(addr, FUTEX_WAIT, value, NULL, NULL);
107*bbecb9d1SAndroid Build Coastguard Worker
108*bbecb9d1SAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &tsnow);
109*bbecb9d1SAndroid Build Coastguard Worker if (timespeccmp(&tsnow, timeout, <))
110*bbecb9d1SAndroid Build Coastguard Worker timespecsub(timeout, &tsnow, &tsrel);
111*bbecb9d1SAndroid Build Coastguard Worker else
112*bbecb9d1SAndroid Build Coastguard Worker timespecclear(&tsrel);
113*bbecb9d1SAndroid Build Coastguard Worker return futex(addr, FUTEX_WAIT, value, &tsrel, NULL);
114*bbecb9d1SAndroid Build Coastguard Worker }
115*bbecb9d1SAndroid Build Coastguard Worker
116*bbecb9d1SAndroid Build Coastguard Worker #else
117*bbecb9d1SAndroid Build Coastguard Worker #define UTIL_FUTEX_SUPPORTED 0
118*bbecb9d1SAndroid Build Coastguard Worker #endif
119*bbecb9d1SAndroid Build Coastguard Worker
120*bbecb9d1SAndroid Build Coastguard Worker #endif /* UTIL_FUTEX_H */
121