Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfutex_mac_p.h
Go to the documentation of this file.
1// Copyright (C) 2023 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QFUTEX_MAC_P_H
6#define QFUTEX_MAC_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <qdeadlinetimer.h>
20#include <qtsan_impl.h>
21#include <private/qglobal_p.h>
22
23// The Darwin kernel exposes a set of __ulock_{wait,wait2,wake} APIs in
24// https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.81.2/bsd/sys/ulock.h,
25// but these APIs are marked as private, so we cannot rely on them being
26// stable, nor we can use these APIs in builds of Qt intended for
27// the Apple App Store. By wholesale disabling the use of the APIs
28// in App Store compliant builds, and runtime checking availability
29// of the APIs when we do build them in, we should be safe, unless
30// the semantics of the APIs change in ways we haven't accounted for,
31// but that's a risk we're willing to take.
32
33#if QT_CONFIG(appstore_compliant)
34QT_BEGIN_NAMESPACE
35namespace QtFutex = QtDummyFutex;
36QT_END_NAMESPACE
37#else
38
39extern "C" {
40// -------- BEGIN OS Declarations --------
41// Source: https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.81.2/bsd/sys/ulock.h
42// Modification: added __attribute((__weak__))
43// Copyright (c) 2015 Apple Inc. All rights reserved.
44
45__attribute((__weak__))
46extern int __ulock_wait2(uint32_t operation, void *addr, uint64_t value,
47 uint64_t timeout, uint64_t value2);
48__attribute((__weak__))
49extern int __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value);
50
51/*
52 * operation bits [7, 0] contain the operation code.
53 */
54#define UL_COMPARE_AND_WAIT 1
55#define UL_COMPARE_AND_WAIT_SHARED 3
56#define UL_COMPARE_AND_WAIT64 5
57#define UL_COMPARE_AND_WAIT64_SHARED 6
58
59/*
60 * operation bits [15, 8] contain the flags for __ulock_wake
61 */
62#define ULF_WAKE_ALL 0x00000100
63#define ULF_WAKE_THREAD 0x00000200
64#define ULF_WAKE_ALLOW_NON_OWNER 0x00000400
65
66/*
67 * operation bits [15, 8] contain the flags for __ulock_wake
68 */
69#define ULF_WAKE_ALL 0x00000100
70#define ULF_WAKE_THREAD 0x00000200
71#define ULF_WAKE_ALLOW_NON_OWNER 0x00000400
72
73/*
74 * operation bits [31, 24] contain the generic flags
75 */
76#define ULF_NO_ERRNO 0x01000000
77
78// -------- END OS Declarations --------
79} // extern "C"
80
81QT_BEGIN_NAMESPACE
82
83namespace QtDarwinFutex {
84
85/*not constexpr*/ inline bool futexAvailable() { return __ulock_wake && __ulock_wait2; }
86
87template <typename Atomic>
88inline uint32_t baseOperation(Atomic &)
89{
90 static_assert(sizeof(Atomic) >= sizeof(quint32), "Can only operate on 32- or 64-bit atomics");
91
92 uint32_t operation = ULF_NO_ERRNO;
93 if (sizeof(Atomic) == sizeof(quint32))
94 operation |= UL_COMPARE_AND_WAIT;
95 else
96 operation |= UL_COMPARE_AND_WAIT64;
97 return operation;
98}
99
100template <typename Atomic> inline int
101do_wait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
102{
103 // source code inspection shows __ulock_wait2 uses nanoseconds for timeout
105 int ret = __ulock_wait2(baseOperation(futex), &futex, uint64_t(expectedValue),
106 timer.remainingTimeNSecs(), 0);
108 return ret;
109}
110
111template <typename Atomic>
112inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
113{
114 do_wait(futex, expectedValue, {});
115}
116
117template <typename Atomic>
118inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
119{
120 int r = do_wait(futex, expectedValue, timer);
121 return r == 0 || r != -ETIMEDOUT;
122}
123
124template <typename Atomic> inline void futexWakeAll(Atomic &futex)
125{
126 __ulock_wake(baseOperation(futex) | ULF_WAKE_ALL, &futex, 0);
127}
128
129template <typename Atomic> inline void futexWakeOne(Atomic &futex)
130{
131 __ulock_wake(baseOperation(futex), &futex, 0);
132}
133} //namespace QtDarwinMutex
134
135namespace QtFutex = QtDarwinFutex;
136
137QT_END_NAMESPACE
138
139#endif // QT_CONFIG(appstore_compliant)
140
141#endif // QFUTEX_MAC_P_H
void futexWakeOne(Atomic &futex)
void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
uint32_t baseOperation(Atomic &)
bool futexAvailable()
void futexWakeAll(Atomic &futex)
int do_wait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer timer)
void futexRelease(void *, void *=nullptr)
Definition qtsan_impl.h:75
void futexAcquire(void *, void *=nullptr)
Definition qtsan_impl.h:74
#define ULF_WAKE_ALL
#define ULF_NO_ERRNO
#define UL_COMPARE_AND_WAIT
#define UL_COMPARE_AND_WAIT64