Split qfutex_p.h per OS
Makes it cleaner when I add more OSes. Change-Id: I63b988479db546dabffcfffd1766bee2e6370b94 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
fc4fca6d9d
commit
585db639a4
@ -511,6 +511,7 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_animation
|
||||
# from the wrong DLL at runtime and crash!
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
|
||||
SOURCES
|
||||
thread/qfutex_win_p.h
|
||||
thread/qwaitcondition_win.cpp
|
||||
LIBRARIES
|
||||
synchronization
|
||||
@ -689,6 +690,11 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX AND NOT APPL
|
||||
thread/qmutex_unix.cpp
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND LINUX
|
||||
SOURCES
|
||||
thread/qfutex_linux_p.h
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_future
|
||||
SOURCES
|
||||
thread/qexception.cpp thread/qexception.h
|
||||
|
94
src/corelib/thread/qfutex_linux_p.h
Normal file
94
src/corelib/thread/qfutex_linux_p.h
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2023 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QFUTEX_LINUX_P_H
|
||||
#define QFUTEX_LINUX_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qcore_unix_p.h>
|
||||
#include <qtsan_impl.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <linux/futex.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// RISC-V does not supply __NR_futex
|
||||
#ifndef __NR_futex
|
||||
# define __NR_futex __NR_futex_time64
|
||||
#endif
|
||||
|
||||
#define QT_ALWAYS_USE_FUTEX
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtLinuxFutex {
|
||||
constexpr inline bool futexAvailable() { return true; }
|
||||
|
||||
inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
|
||||
int *addr2 = nullptr, int val3 = 0) noexcept
|
||||
{
|
||||
QtTsan::futexRelease(addr, addr2);
|
||||
|
||||
// we use __NR_futex because some libcs (like Android's bionic) don't
|
||||
// provide SYS_futex etc.
|
||||
int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
|
||||
|
||||
QtTsan::futexAcquire(addr, addr2);
|
||||
|
||||
return result;
|
||||
}
|
||||
template <typename T> int *addr(T *ptr)
|
||||
{
|
||||
int *int_addr = reinterpret_cast<int *>(ptr);
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||
if (sizeof(T) > sizeof(int))
|
||||
int_addr++; //We want a pointer to the least significant half
|
||||
#endif
|
||||
return int_addr;
|
||||
}
|
||||
|
||||
template <typename Atomic>
|
||||
inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue));
|
||||
}
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, std::chrono::nanoseconds timeout)
|
||||
{
|
||||
struct timespec ts = durationToTimespec(timeout);
|
||||
int r = _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue), quintptr(&ts));
|
||||
return r == 0 || errno != ETIMEDOUT;
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &futex)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAKE, 1);
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeAll(Atomic &futex)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAKE, INT_MAX);
|
||||
}
|
||||
template <typename Atomic> inline
|
||||
void futexWakeOp(Atomic &futex1, int wake1, int wake2, Atomic &futex2, quint32 op)
|
||||
{
|
||||
_q_futex(addr(&futex1), FUTEX_WAKE_OP, wake1, wake2, addr(&futex2), op);
|
||||
}} // namespace QtLinuxFutex
|
||||
namespace QtFutex = QtLinuxFutex;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QFUTEX_LINUX_P_H
|
@ -16,7 +16,6 @@
|
||||
//
|
||||
|
||||
#include <private/qglobal_p.h>
|
||||
#include <QtCore/qtsan_impl.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@ -36,114 +35,10 @@ namespace QtDummyFutex {
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
||||
# include <private/qcore_unix_p.h>
|
||||
// use Linux mutexes everywhere except for LSB builds
|
||||
# include <sys/syscall.h>
|
||||
# include <errno.h>
|
||||
# include <limits.h>
|
||||
# include <unistd.h>
|
||||
# include <asm/unistd.h>
|
||||
# include <linux/futex.h>
|
||||
# define QT_ALWAYS_USE_FUTEX
|
||||
|
||||
// if not defined in linux/futex.h
|
||||
# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
|
||||
|
||||
// RISC-V does not supply __NR_futex
|
||||
# ifndef __NR_futex
|
||||
# define __NR_futex __NR_futex_time64
|
||||
# endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QtLinuxFutex {
|
||||
constexpr inline bool futexAvailable() { return true; }
|
||||
inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
|
||||
int *addr2 = nullptr, int val3 = 0) noexcept
|
||||
{
|
||||
QtTsan::futexRelease(addr, addr2);
|
||||
|
||||
// we use __NR_futex because some libcs (like Android's bionic) don't
|
||||
// provide SYS_futex etc.
|
||||
int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
|
||||
|
||||
QtTsan::futexAcquire(addr, addr2);
|
||||
|
||||
return result;
|
||||
}
|
||||
template <typename T> int *addr(T *ptr)
|
||||
{
|
||||
int *int_addr = reinterpret_cast<int *>(ptr);
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||
if (sizeof(T) > sizeof(int))
|
||||
int_addr++; //We want a pointer to the least significant half
|
||||
#endif
|
||||
return int_addr;
|
||||
}
|
||||
|
||||
template <typename Atomic>
|
||||
inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue));
|
||||
}
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, std::chrono::nanoseconds timeout)
|
||||
{
|
||||
struct timespec ts= durationToTimespec(timeout);
|
||||
int r = _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue), quintptr(&ts));
|
||||
return r == 0 || errno != ETIMEDOUT;
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &futex)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAKE, 1);
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeAll(Atomic &futex)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAKE, INT_MAX);
|
||||
}
|
||||
template <typename Atomic> inline
|
||||
void futexWakeOp(Atomic &futex1, int wake1, int wake2, Atomic &futex2, quint32 op)
|
||||
{
|
||||
_q_futex(addr(&futex1), FUTEX_WAKE_OP, wake1, wake2, addr(&futex2), op);
|
||||
}
|
||||
}
|
||||
namespace QtFutex = QtLinuxFutex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
# include "qfutex_linux_p.h"
|
||||
#elif defined(Q_OS_WIN)
|
||||
# include <qt_windows.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QtWindowsFutex {
|
||||
#define QT_ALWAYS_USE_FUTEX
|
||||
constexpr inline bool futexAvailable() { return true; }
|
||||
|
||||
template <typename Atomic>
|
||||
inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
|
||||
{
|
||||
QtTsan::futexRelease(&futex);
|
||||
WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), INFINITE);
|
||||
QtTsan::futexAcquire(&futex);
|
||||
}
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, std::chrono::nanoseconds timeout)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
// Using ceil so that any non-zero timeout doesn't get trunated to 0ms
|
||||
auto msecs = ceil<milliseconds>(timeout);
|
||||
BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(msecs.count()));
|
||||
return r || GetLastError() != ERROR_TIMEOUT;
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeAll(Atomic &futex)
|
||||
{
|
||||
WakeByAddressAll(&futex);
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &futex)
|
||||
{
|
||||
WakeByAddressSingle(&futex);
|
||||
}
|
||||
}
|
||||
namespace QtFutex = QtWindowsFutex;
|
||||
QT_END_NAMESPACE
|
||||
# include "qfutex_win_p.h"
|
||||
#else
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
61
src/corelib/thread/qfutex_win_p.h
Normal file
61
src/corelib/thread/qfutex_win_p.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2023 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QFUTEX_WIN_P_H
|
||||
#define QFUTEX_WIN_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qglobal_p.h>
|
||||
#include <qtsan_impl.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#define QT_ALWAYS_USE_FUTEX
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtWindowsFutex {
|
||||
constexpr inline bool futexAvailable() { return true; }
|
||||
|
||||
template <typename Atomic>
|
||||
inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
|
||||
{
|
||||
QtTsan::futexRelease(&futex);
|
||||
WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), INFINITE);
|
||||
QtTsan::futexAcquire(&futex);
|
||||
}
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, std::chrono::nanoseconds timeout)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
// Using ceil so that any non-zero timeout doesn't get trunated to 0ms
|
||||
auto msecs = ceil<milliseconds>(timeout);
|
||||
BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(msecs.count()));
|
||||
return r || GetLastError() != ERROR_TIMEOUT;
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeAll(Atomic &futex)
|
||||
{
|
||||
WakeByAddressAll(&futex);
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &futex)
|
||||
{
|
||||
WakeByAddressSingle(&futex);
|
||||
}
|
||||
} // namespace QtWindowsFutex
|
||||
namespace QtFutex = QtWindowsFutex;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QFUTEX_WIN_P_H
|
Loading…
x
Reference in New Issue
Block a user