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!
|
# from the wrong DLL at runtime and crash!
|
||||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
|
||||||
SOURCES
|
SOURCES
|
||||||
|
thread/qfutex_win_p.h
|
||||||
thread/qwaitcondition_win.cpp
|
thread/qwaitcondition_win.cpp
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
synchronization
|
synchronization
|
||||||
@ -689,6 +690,11 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND UNIX AND NOT APPL
|
|||||||
thread/qmutex_unix.cpp
|
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
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_future
|
||||||
SOURCES
|
SOURCES
|
||||||
thread/qexception.cpp thread/qexception.h
|
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 <private/qglobal_p.h>
|
||||||
#include <QtCore/qtsan_impl.h>
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@ -36,114 +35,10 @@ namespace QtDummyFutex {
|
|||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
||||||
# include <private/qcore_unix_p.h>
|
|
||||||
// use Linux mutexes everywhere except for LSB builds
|
// use Linux mutexes everywhere except for LSB builds
|
||||||
# include <sys/syscall.h>
|
# include "qfutex_linux_p.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
|
|
||||||
|
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
# include <qt_windows.h>
|
# include "qfutex_win_p.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
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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