1 /*
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
5 *
6 * (C) Copyright 2013 Tim Blechmann
7 * (C) Copyright 2013 Andrey Semashev
8 */
9 /*!
10 * \file futex.hpp
11 *
12 * \brief This header is the Boost.Sync library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
14 *
15 * This header contains Linux futex API declarations.
16 */
17
18 #ifndef BOOST_SYNC_DETAIL_FUTEX_HPP_INCLUDED_
19 #define BOOST_SYNC_DETAIL_FUTEX_HPP_INCLUDED_
20
21 #include <stddef.h>
22 #include <limits.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <sys/syscall.h>
26 #include <linux/futex.h>
27 #include <boost/sync/detail/config.hpp>
28 #include <boost/sync/detail/header.hpp>
29
30 #ifdef BOOST_HAS_PRAGMA_ONCE
31 #pragma once
32 #endif
33
34 // Some Android NDKs (Google NDK and older Crystax.NET NDK versions) don't define SYS_futex
35 #if defined(SYS_futex)
36 #define BOOST_SYNC_DETAIL_SYS_FUTEX SYS_futex
37 #else
38 #define BOOST_SYNC_DETAIL_SYS_FUTEX __NR_futex
39 #endif
40
41 namespace boost {
42
43 namespace sync {
44
45 namespace detail {
46
47 namespace linux_ {
48
49 //! Invokes an operation on the futex
futex_invoke(int * addr1,int op,int val1,const struct::timespec * timeout=NULL,int * addr2=NULL,int val3=0)50 BOOST_FORCEINLINE int futex_invoke(int* addr1, int op, int val1, const struct ::timespec* timeout = NULL, int* addr2 = NULL, int val3 = 0) BOOST_NOEXCEPT
51 {
52 return ::syscall(BOOST_SYNC_DETAIL_SYS_FUTEX, addr1, op, val1, timeout, addr2, val3);
53 }
54
55 //! Checks that the value \c pval is \c expected and blocks
futex_wait(int * pval,int expected)56 BOOST_FORCEINLINE int futex_wait(int* pval, int expected) BOOST_NOEXCEPT
57 {
58 return futex_invoke
59 (
60 pval,
61 #ifdef FUTEX_WAIT_PRIVATE
62 FUTEX_WAIT_PRIVATE,
63 #else
64 FUTEX_WAIT,
65 #endif
66 expected
67 );
68 }
69
70 //! Checks that the value \c pval is \c expected and blocks until \c timeout_nsec expires
futex_timedwait(int * pval,int expected,uint64_t timeout_nsec)71 BOOST_FORCEINLINE int futex_timedwait(int* pval, int expected, uint64_t timeout_nsec) BOOST_NOEXCEPT
72 {
73 struct ::timespec timeout;
74 timeout.tv_sec = timeout_nsec / 1000000000u;
75 timeout.tv_nsec = timeout_nsec % 1000000000u;
76 return futex_invoke
77 (
78 pval,
79 #ifdef FUTEX_WAIT_PRIVATE
80 FUTEX_WAIT_PRIVATE,
81 #else
82 FUTEX_WAIT,
83 #endif
84 expected,
85 &timeout
86 );
87 }
88
89 //! Wakes all threads waiting on the futex
futex_broadcast(int * pval)90 BOOST_FORCEINLINE int futex_broadcast(int* pval) BOOST_NOEXCEPT
91 {
92 return futex_invoke
93 (
94 pval,
95 #ifdef FUTEX_WAKE_PRIVATE
96 FUTEX_WAKE_PRIVATE,
97 #else
98 FUTEX_WAKE,
99 #endif
100 INT_MAX
101 );
102 }
103
104 //! Wakes the specified number of threads waiting on the futex
futex_signal(int * pval,int count=1)105 BOOST_FORCEINLINE int futex_signal(int* pval, int count = 1) BOOST_NOEXCEPT
106 {
107 return futex_invoke
108 (
109 pval,
110 #ifdef FUTEX_WAKE_PRIVATE
111 FUTEX_WAKE_PRIVATE,
112 #else
113 FUTEX_WAKE,
114 #endif
115 count
116 );
117 }
118
119 } // namespace linux_
120
121 } // namespace detail
122
123 } // namespace sync
124
125 } // namespace boost
126
127 #include <boost/sync/detail/footer.hpp>
128
129 #endif // BOOST_SYNC_DETAIL_FUTEX_HPP_INCLUDED_
130