xref: /openbsd-src/lib/libc/thread/synch.h (revision c7e8ea31cd41a963f06f0a8ba93948b06aa6b4a4)
1 /*	$OpenBSD: synch.h,v 1.1 2017/08/15 06:13:24 guenther Exp $ */
2 /*
3  * Copyright (c) 2017 Martin Pieuchot
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/atomic.h>
19 #include <sys/time.h>
20 #include <sys/futex.h>
21 
22 REDIRECT_SYSCALL(futex);
23 
24 static inline int
25 _wake(volatile uint32_t *p, int n)
26 {
27 	return futex(p, FUTEX_WAKE, n, NULL, NULL);
28 }
29 
30 static inline void
31 _wait(volatile uint32_t *p, int val)
32 {
33 	while (*p != (uint32_t)val)
34 		futex(p, FUTEX_WAIT, val, NULL, NULL);
35 }
36 
37 static inline int
38 _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs)
39 {
40 	struct timespec rel;
41 
42 	if (abs == NULL)
43 		return futex(p, FUTEX_WAIT, val, NULL, NULL);
44 
45 	if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
46 		return (EINVAL);
47 
48 	rel.tv_sec = abs->tv_sec - rel.tv_sec;
49 	if ((rel.tv_nsec = abs->tv_nsec - rel.tv_nsec) < 0) {
50 		rel.tv_sec--;
51 		rel.tv_nsec += 1000000000;
52 	}
53 	if (rel.tv_sec < 0)
54 		return (ETIMEDOUT);
55 
56 	return futex(p, FUTEX_WAIT, val, &rel, NULL);
57 }
58 
59 static inline int
60 _requeue(volatile uint32_t *p, int n, int m, volatile uint32_t *q)
61 {
62 	return futex(p, FUTEX_REQUEUE, n, (void *)(long)m, q);
63 }
64