mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-28 02:26:07 +00:00
The way to Unity, pt.2 (#1671)
This commit is contained in:
parent
357b7829c3
commit
7ffa581d4b
|
@ -210,7 +210,10 @@ set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp
|
||||||
src/core/libraries/gnmdriver/gnm_error.h
|
src/core/libraries/gnmdriver/gnm_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(KERNEL_LIB src/core/libraries/kernel/threads/condvar.cpp
|
set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
||||||
|
src/core/libraries/kernel/sync/mutex.h
|
||||||
|
src/core/libraries/kernel/sync/semaphore.h
|
||||||
|
src/core/libraries/kernel/threads/condvar.cpp
|
||||||
src/core/libraries/kernel/threads/event_flag.cpp
|
src/core/libraries/kernel/threads/event_flag.cpp
|
||||||
src/core/libraries/kernel/threads/exception.cpp
|
src/core/libraries/kernel/threads/exception.cpp
|
||||||
src/core/libraries/kernel/threads/exception.h
|
src/core/libraries/kernel/threads/exception.h
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "ntapi.h"
|
#include "ntapi.h"
|
||||||
|
|
||||||
NtClose_t NtClose = nullptr;
|
NtClose_t NtClose = nullptr;
|
||||||
NtDelayExecution_t NtDelayExecution = nullptr;
|
|
||||||
NtSetInformationFile_t NtSetInformationFile = nullptr;
|
NtSetInformationFile_t NtSetInformationFile = nullptr;
|
||||||
NtCreateThread_t NtCreateThread = nullptr;
|
NtCreateThread_t NtCreateThread = nullptr;
|
||||||
NtTerminateThread_t NtTerminateThread = nullptr;
|
NtTerminateThread_t NtTerminateThread = nullptr;
|
||||||
|
@ -18,7 +17,6 @@ void Initialize() {
|
||||||
|
|
||||||
// http://stackoverflow.com/a/31411628/4725495
|
// http://stackoverflow.com/a/31411628/4725495
|
||||||
NtClose = (NtClose_t)GetProcAddress(nt_handle, "NtClose");
|
NtClose = (NtClose_t)GetProcAddress(nt_handle, "NtClose");
|
||||||
NtDelayExecution = (NtDelayExecution_t)GetProcAddress(nt_handle, "NtDelayExecution");
|
|
||||||
NtSetInformationFile =
|
NtSetInformationFile =
|
||||||
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
|
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
|
||||||
NtCreateThread = (NtCreateThread_t)GetProcAddress(nt_handle, "NtCreateThread");
|
NtCreateThread = (NtCreateThread_t)GetProcAddress(nt_handle, "NtCreateThread");
|
||||||
|
|
|
@ -408,7 +408,7 @@ typedef struct _TEB { /* win32/win64 */
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
PVOID SystemReserved1[30]; /* /0190 */
|
PVOID SystemReserved1[30]; /* /0190 */
|
||||||
#else
|
#else
|
||||||
PVOID SystemReserved1[26]; /* 10c/ used for krnl386 private data in Wine */
|
PVOID SystemReserved1[26]; /* 10c/ */
|
||||||
#endif
|
#endif
|
||||||
char PlaceholderCompatibilityMode; /* 174/0280 */
|
char PlaceholderCompatibilityMode; /* 174/0280 */
|
||||||
BOOLEAN PlaceholderHydrationAlwaysExplicit; /* 175/0281 */
|
BOOLEAN PlaceholderHydrationAlwaysExplicit; /* 175/0281 */
|
||||||
|
@ -430,13 +430,13 @@ typedef struct _TEB { /* win32/win64 */
|
||||||
BYTE SpareBytes1[23]; /* 1b9/ */
|
BYTE SpareBytes1[23]; /* 1b9/ */
|
||||||
ULONG TxFsContext; /* 1d0/ */
|
ULONG TxFsContext; /* 1d0/ */
|
||||||
#endif
|
#endif
|
||||||
GDI_TEB_BATCH GdiTebBatch; /* 1d4/02f0 used for ntdll private data in Wine */
|
GDI_TEB_BATCH GdiTebBatch; /* 1d4/02f0 */
|
||||||
CLIENT_ID RealClientId; /* 6b4/07d8 */
|
CLIENT_ID RealClientId; /* 6b4/07d8 */
|
||||||
HANDLE GdiCachedProcessHandle; /* 6bc/07e8 */
|
HANDLE GdiCachedProcessHandle; /* 6bc/07e8 */
|
||||||
ULONG GdiClientPID; /* 6c0/07f0 */
|
ULONG GdiClientPID; /* 6c0/07f0 */
|
||||||
ULONG GdiClientTID; /* 6c4/07f4 */
|
ULONG GdiClientTID; /* 6c4/07f4 */
|
||||||
PVOID GdiThreadLocaleInfo; /* 6c8/07f8 */
|
PVOID GdiThreadLocaleInfo; /* 6c8/07f8 */
|
||||||
ULONG_PTR Win32ClientInfo[62]; /* 6cc/0800 used for user32 private data in Wine */
|
ULONG_PTR Win32ClientInfo[62]; /* 6cc/0800 */
|
||||||
PVOID glDispatchTable[233]; /* 7c4/09f0 */
|
PVOID glDispatchTable[233]; /* 7c4/09f0 */
|
||||||
PVOID glReserved1[29]; /* b68/1138 */
|
PVOID glReserved1[29]; /* b68/1138 */
|
||||||
PVOID glReserved2; /* bdc/1220 */
|
PVOID glReserved2; /* bdc/1220 */
|
||||||
|
@ -511,8 +511,6 @@ static_assert(offsetof(TEB, DeallocationStack) ==
|
||||||
|
|
||||||
typedef u64(__stdcall* NtClose_t)(HANDLE Handle);
|
typedef u64(__stdcall* NtClose_t)(HANDLE Handle);
|
||||||
|
|
||||||
typedef u64(__stdcall* NtDelayExecution_t)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
|
|
||||||
|
|
||||||
typedef u64(__stdcall* NtSetInformationFile_t)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
|
typedef u64(__stdcall* NtSetInformationFile_t)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
PVOID FileInformation, ULONG Length,
|
PVOID FileInformation, ULONG Length,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass);
|
FILE_INFORMATION_CLASS FileInformationClass);
|
||||||
|
@ -525,7 +523,6 @@ typedef u64(__stdcall* NtCreateThread_t)(PHANDLE ThreadHandle, ACCESS_MASK Desir
|
||||||
typedef u64(__stdcall* NtTerminateThread_t)(HANDLE ThreadHandle, u64 ExitStatus);
|
typedef u64(__stdcall* NtTerminateThread_t)(HANDLE ThreadHandle, u64 ExitStatus);
|
||||||
|
|
||||||
extern NtClose_t NtClose;
|
extern NtClose_t NtClose;
|
||||||
extern NtDelayExecution_t NtDelayExecution;
|
|
||||||
extern NtSetInformationFile_t NtSetInformationFile;
|
extern NtSetInformationFile_t NtSetInformationFile;
|
||||||
extern NtCreateThread_t NtCreateThread;
|
extern NtCreateThread_t NtCreateThread;
|
||||||
extern NtTerminateThread_t NtTerminateThread;
|
extern NtTerminateThread_t NtTerminateThread;
|
||||||
|
|
|
@ -147,6 +147,10 @@ void SetCurrentThreadName(const char* name) {
|
||||||
SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data());
|
SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name) {
|
||||||
|
SetThreadDescription(thread, UTF8ToUTF16W(name).data());
|
||||||
|
}
|
||||||
|
|
||||||
#else // !MSVC_VER, so must be POSIX threads
|
#else // !MSVC_VER, so must be POSIX threads
|
||||||
|
|
||||||
// MinGW with the POSIX threading model does not support pthread_setname_np
|
// MinGW with the POSIX threading model does not support pthread_setname_np
|
||||||
|
@ -170,11 +174,19 @@ void SetCurrentThreadName(const char* name) {
|
||||||
pthread_setname_np(pthread_self(), name);
|
pthread_setname_np(pthread_self(), name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
void SetCurrentThreadName(const char*) {
|
void SetCurrentThreadName(const char*) {
|
||||||
// Do Nothing on MingW
|
// Do Nothing on MinGW
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name) {
|
||||||
|
// Do Nothing on MinGW
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority);
|
||||||
|
|
||||||
void SetCurrentThreadName(const char* name);
|
void SetCurrentThreadName(const char* name);
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name);
|
||||||
|
|
||||||
class AccurateTimer {
|
class AccurateTimer {
|
||||||
std::chrono::nanoseconds target_interval{};
|
std::chrono::nanoseconds target_interval{};
|
||||||
std::chrono::nanoseconds total_wait{};
|
std::chrono::nanoseconds total_wait{};
|
||||||
|
|
|
@ -15,6 +15,7 @@ s64 Logger::write(const void* buf, size_t nbytes) {
|
||||||
log(static_cast<const char*>(buf), nbytes);
|
log(static_cast<const char*>(buf), nbytes);
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
||||||
|
|
52
src/core/libraries/kernel/sync/mutex.cpp
Normal file
52
src/core/libraries/kernel/sync/mutex.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
|
||||||
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
TimedMutex::TimedMutex() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
mtx = CreateMutex(nullptr, false, nullptr);
|
||||||
|
ASSERT(mtx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TimedMutex::~TimedMutex() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
CloseHandle(mtx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimedMutex::lock() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
for (;;) {
|
||||||
|
u64 res = WaitForSingleObjectEx(mtx, INFINITE, true);
|
||||||
|
if (res == WAIT_OBJECT_0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mtx.lock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimedMutex::try_lock() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
return WaitForSingleObjectEx(mtx, 0, true) == WAIT_OBJECT_0;
|
||||||
|
#else
|
||||||
|
return mtx.try_lock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimedMutex::unlock() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
ReleaseMutex(mtx);
|
||||||
|
#else
|
||||||
|
mtx.unlock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Libraries::Kernel
|
80
src/core/libraries/kernel/sync/mutex.h
Normal file
80
src/core/libraries/kernel/sync/mutex.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <mutex>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
class TimedMutex {
|
||||||
|
public:
|
||||||
|
TimedMutex();
|
||||||
|
~TimedMutex();
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
bool try_lock();
|
||||||
|
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time) {
|
||||||
|
#ifdef _WIN64
|
||||||
|
constexpr auto zero = std::chrono::duration<Rep, Period>::zero();
|
||||||
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
std::chrono::steady_clock::time_point abs_time = now;
|
||||||
|
if (rel_time > zero) {
|
||||||
|
constexpr auto max = (std::chrono::steady_clock::time_point::max)();
|
||||||
|
if (abs_time < max - rel_time) {
|
||||||
|
abs_time += rel_time;
|
||||||
|
} else {
|
||||||
|
abs_time = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try_lock_until(abs_time);
|
||||||
|
#else
|
||||||
|
return mtx.try_lock_for(rel_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
bool try_lock_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
|
||||||
|
#ifdef _WIN64
|
||||||
|
for (;;) {
|
||||||
|
const auto now = Clock::now();
|
||||||
|
if (abs_time <= now) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto rel_ms = std::chrono::ceil<std::chrono::milliseconds>(abs_time - now);
|
||||||
|
u64 res = WaitForSingleObjectEx(mtx, static_cast<u64>(rel_ms.count()), true);
|
||||||
|
if (res == WAIT_OBJECT_0) {
|
||||||
|
return true;
|
||||||
|
} else if (res == WAIT_TIMEOUT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return mtx.try_lock_until(abs_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef _WIN64
|
||||||
|
HANDLE mtx;
|
||||||
|
#else
|
||||||
|
std::timed_mutex mtx;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Kernel
|
117
src/core/libraries/kernel/sync/semaphore.h
Normal file
117
src/core/libraries/kernel/sync/semaphore.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <semaphore>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
template <s64 max>
|
||||||
|
class Semaphore {
|
||||||
|
public:
|
||||||
|
Semaphore(s32 initialCount)
|
||||||
|
#ifndef _WIN64
|
||||||
|
: sem{initialCount}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef _WIN64
|
||||||
|
sem = CreateSemaphore(nullptr, initialCount, max, nullptr);
|
||||||
|
ASSERT(sem);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~Semaphore() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
CloseHandle(sem);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
ReleaseSemaphore(sem, 1, nullptr);
|
||||||
|
#else
|
||||||
|
sem.release();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void acquire() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
for (;;) {
|
||||||
|
u64 res = WaitForSingleObjectEx(sem, INFINITE, true);
|
||||||
|
if (res == WAIT_OBJECT_0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
sem.acquire();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_acquire() {
|
||||||
|
#ifdef _WIN64
|
||||||
|
return WaitForSingleObjectEx(sem, 0, true) == WAIT_OBJECT_0;
|
||||||
|
#else
|
||||||
|
return sem.try_acquire();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) {
|
||||||
|
#ifdef _WIN64
|
||||||
|
const auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
|
||||||
|
const u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
|
||||||
|
|
||||||
|
if (timeout_ms == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WaitForSingleObjectEx(sem, timeout_ms, true) == WAIT_OBJECT_0;
|
||||||
|
#else
|
||||||
|
return sem.try_acquire_for(rel_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
|
||||||
|
#ifdef _WIN64
|
||||||
|
const auto now = Clock::now();
|
||||||
|
if (now >= abs_time) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - now);
|
||||||
|
const u64 timeout_ms = static_cast<u64>(rel_time.count());
|
||||||
|
if (timeout_ms == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 res = WaitForSingleObjectEx(sem, static_cast<u64>(timeout_ms), true);
|
||||||
|
return res == WAIT_OBJECT_0;
|
||||||
|
#else
|
||||||
|
return sem.try_acquire_until(abs_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef _WIN64
|
||||||
|
HANDLE sem;
|
||||||
|
#else
|
||||||
|
std::counting_semaphore<max> sem;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
using BinarySemaphore = Semaphore<1>;
|
||||||
|
using CountingSemaphore = Semaphore<0x7FFFFFFF /*ORBIS_KERNEL_SEM_VALUE_MAX*/>;
|
||||||
|
|
||||||
|
} // namespace Libraries::Kernel
|
|
@ -191,7 +191,7 @@ int PthreadCond::Signal() {
|
||||||
PthreadMutex* mp = td->mutex_obj;
|
PthreadMutex* mp = td->mutex_obj;
|
||||||
has_user_waiters = SleepqRemove(sq, td);
|
has_user_waiters = SleepqRemove(sq, td);
|
||||||
|
|
||||||
std::binary_semaphore* waddr = nullptr;
|
BinarySemaphore* waddr = nullptr;
|
||||||
if (mp->m_owner == curthread) {
|
if (mp->m_owner == curthread) {
|
||||||
if (curthread->nwaiter_defer >= Pthread::MaxDeferWaiters) {
|
if (curthread->nwaiter_defer >= Pthread::MaxDeferWaiters) {
|
||||||
curthread->WakeAll();
|
curthread->WakeAll();
|
||||||
|
@ -211,7 +211,7 @@ int PthreadCond::Signal() {
|
||||||
|
|
||||||
struct BroadcastArg {
|
struct BroadcastArg {
|
||||||
Pthread* curthread;
|
Pthread* curthread;
|
||||||
std::binary_semaphore* waddrs[Pthread::MaxDeferWaiters];
|
BinarySemaphore* waddrs[Pthread::MaxDeferWaiters];
|
||||||
int count;
|
int count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bits |= bits;
|
m_bits |= bits;
|
||||||
|
|
||||||
m_cond_var.notify_all();
|
m_cond_var.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,6 +380,7 @@ int PS4_SYSV_ABI posix_sched_get_priority_min() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rename_np(PthreadT thread, const char* name) {
|
int PS4_SYSV_ABI posix_pthread_rename_np(PthreadT thread, const char* name) {
|
||||||
LOG_INFO(Kernel_Pthread, "name = {}", name);
|
LOG_INFO(Kernel_Pthread, "name = {}", name);
|
||||||
|
Common::SetThreadName(reinterpret_cast<void*>(thread->native_thr.GetHandle()), name);
|
||||||
thread->name = name;
|
thread->name = name;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
|
|
||||||
#include "common/enum.h"
|
#include "common/enum.h"
|
||||||
|
#include "core/libraries/kernel/sync/mutex.h"
|
||||||
|
#include "core/libraries/kernel/sync/semaphore.h"
|
||||||
#include "core/libraries/kernel/time.h"
|
#include "core/libraries/kernel/time.h"
|
||||||
#include "core/thread.h"
|
#include "core/thread.h"
|
||||||
#include "core/tls.h"
|
#include "core/tls.h"
|
||||||
|
@ -44,7 +46,7 @@ enum class PthreadMutexProt : u32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PthreadMutex {
|
struct PthreadMutex {
|
||||||
std::timed_mutex m_lock;
|
TimedMutex m_lock;
|
||||||
PthreadMutexFlags m_flags;
|
PthreadMutexFlags m_flags;
|
||||||
Pthread* m_owner;
|
Pthread* m_owner;
|
||||||
int m_count;
|
int m_count;
|
||||||
|
@ -288,14 +290,14 @@ struct Pthread {
|
||||||
int report_events;
|
int report_events;
|
||||||
int event_mask;
|
int event_mask;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::binary_semaphore wake_sema{0};
|
BinarySemaphore wake_sema{0};
|
||||||
SleepQueue* sleepqueue;
|
SleepQueue* sleepqueue;
|
||||||
void* wchan;
|
void* wchan;
|
||||||
PthreadMutex* mutex_obj;
|
PthreadMutex* mutex_obj;
|
||||||
bool will_sleep;
|
bool will_sleep;
|
||||||
bool has_user_waiters;
|
bool has_user_waiters;
|
||||||
int nwaiter_defer;
|
int nwaiter_defer;
|
||||||
std::binary_semaphore* defer_waiters[MaxDeferWaiters];
|
BinarySemaphore* defer_waiters[MaxDeferWaiters];
|
||||||
|
|
||||||
bool InCritical() const noexcept {
|
bool InCritical() const noexcept {
|
||||||
return locklevel > 0 || critical_count > 0;
|
return locklevel > 0 || critical_count > 0;
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <semaphore>
|
#include <semaphore>
|
||||||
|
|
||||||
|
#include "core/libraries/kernel/sync/semaphore.h"
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/kernel/kernel.h"
|
#include "core/libraries/kernel/kernel.h"
|
||||||
#include "core/libraries/kernel/orbis_error.h"
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
|
@ -21,7 +23,7 @@ constexpr int ORBIS_KERNEL_SEM_VALUE_MAX = 0x7FFFFFFF;
|
||||||
struct PthreadSem {
|
struct PthreadSem {
|
||||||
explicit PthreadSem(s32 value_) : semaphore{value_}, value{value_} {}
|
explicit PthreadSem(s32 value_) : semaphore{value_}, value{value_} {}
|
||||||
|
|
||||||
std::counting_semaphore<ORBIS_KERNEL_SEM_VALUE_MAX> semaphore;
|
CountingSemaphore semaphore;
|
||||||
std::atomic<s32> value;
|
std::atomic<s32> value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,7 +77,7 @@ public:
|
||||||
it = wait_list.erase(it);
|
it = wait_list.erase(it);
|
||||||
token_count -= waiter->need_count;
|
token_count -= waiter->need_count;
|
||||||
waiter->was_signaled = true;
|
waiter->was_signaled = true;
|
||||||
waiter->cv.notify_one();
|
waiter->sem.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -88,7 +90,7 @@ public:
|
||||||
}
|
}
|
||||||
for (auto* waiter : wait_list) {
|
for (auto* waiter : wait_list) {
|
||||||
waiter->was_cancled = true;
|
waiter->was_cancled = true;
|
||||||
waiter->cv.notify_one();
|
waiter->sem.release();
|
||||||
}
|
}
|
||||||
wait_list.clear();
|
wait_list.clear();
|
||||||
token_count = set_count < 0 ? init_count : set_count;
|
token_count = set_count < 0 ? init_count : set_count;
|
||||||
|
@ -99,21 +101,21 @@ public:
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
for (auto* waiter : wait_list) {
|
for (auto* waiter : wait_list) {
|
||||||
waiter->was_deleted = true;
|
waiter->was_deleted = true;
|
||||||
waiter->cv.notify_one();
|
waiter->sem.release();
|
||||||
}
|
}
|
||||||
wait_list.clear();
|
wait_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct WaitingThread {
|
struct WaitingThread {
|
||||||
std::condition_variable cv;
|
BinarySemaphore sem;
|
||||||
u32 priority;
|
u32 priority;
|
||||||
s32 need_count;
|
s32 need_count;
|
||||||
bool was_signaled{};
|
bool was_signaled{};
|
||||||
bool was_deleted{};
|
bool was_deleted{};
|
||||||
bool was_cancled{};
|
bool was_cancled{};
|
||||||
|
|
||||||
explicit WaitingThread(s32 need_count, bool is_fifo) : need_count{need_count} {
|
explicit WaitingThread(s32 need_count, bool is_fifo) : sem{0}, need_count{need_count} {
|
||||||
// Retrieve calling thread priority for sorting into waiting threads list.
|
// Retrieve calling thread priority for sorting into waiting threads list.
|
||||||
if (!is_fifo) {
|
if (!is_fifo) {
|
||||||
priority = g_curthread->attr.prio;
|
priority = g_curthread->attr.prio;
|
||||||
|
@ -134,24 +136,26 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int Wait(std::unique_lock<std::mutex>& lk, u32* timeout) {
|
int Wait(std::unique_lock<std::mutex>& lk, u32* timeout) {
|
||||||
|
lk.unlock();
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
// Wait indefinitely until we are woken up.
|
// Wait indefinitely until we are woken up.
|
||||||
cv.wait(lk);
|
sem.acquire();
|
||||||
|
lk.lock();
|
||||||
return GetResult(false);
|
return GetResult(false);
|
||||||
}
|
}
|
||||||
// Wait until timeout runs out, recording how much remaining time there was.
|
// Wait until timeout runs out, recording how much remaining time there was.
|
||||||
const auto start = std::chrono::high_resolution_clock::now();
|
const auto start = std::chrono::high_resolution_clock::now();
|
||||||
const auto signaled = cv.wait_for(lk, std::chrono::microseconds(*timeout),
|
sem.try_acquire_for(std::chrono::microseconds(*timeout));
|
||||||
[this] { return was_signaled; });
|
|
||||||
const auto end = std::chrono::high_resolution_clock::now();
|
const auto end = std::chrono::high_resolution_clock::now();
|
||||||
const auto time =
|
const auto time =
|
||||||
std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
|
std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
|
||||||
if (signaled) {
|
lk.lock();
|
||||||
|
if (was_signaled) {
|
||||||
*timeout -= time;
|
*timeout -= time;
|
||||||
} else {
|
} else {
|
||||||
*timeout = 0;
|
*timeout = 0;
|
||||||
}
|
}
|
||||||
return GetResult(!signaled);
|
return GetResult(!was_signaled);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,22 @@ u64 PS4_SYSV_ABI sceKernelReadTsc() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
|
int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
auto total_wait_time = std::chrono::microseconds(microseconds);
|
||||||
|
|
||||||
|
while (total_wait_time.count() > 0) {
|
||||||
|
auto wait_time = std::chrono::ceil<std::chrono::milliseconds>(total_wait_time).count();
|
||||||
|
u64 res = SleepEx(static_cast<u64>(wait_time), true);
|
||||||
|
if (res == WAIT_IO_COMPLETION) {
|
||||||
|
auto elapsedTime = std::chrono::high_resolution_clock::now() - start_time;
|
||||||
|
auto elapsedMicroseconds =
|
||||||
|
std::chrono::duration_cast<std::chrono::microseconds>(elapsedTime).count();
|
||||||
|
total_wait_time = std::chrono::microseconds(microseconds - elapsedMicroseconds);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
timespec start;
|
timespec start;
|
||||||
|
|
Loading…
Reference in a new issue