Skip to content

Commit 99d28ea

Browse files
polybiusproxyXcedf
authored andcommitted
The way to Unity, pt.2 (shadps4-emu#1671)
1 parent 4be7d04 commit 99d28ea

File tree

15 files changed

+311
-28
lines changed

15 files changed

+311
-28
lines changed

CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,10 @@ set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp
210210
src/core/libraries/gnmdriver/gnm_error.h
211211
)
212212

213-
set(KERNEL_LIB src/core/libraries/kernel/threads/condvar.cpp
213+
set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
214+
src/core/libraries/kernel/sync/mutex.h
215+
src/core/libraries/kernel/sync/semaphore.h
216+
src/core/libraries/kernel/threads/condvar.cpp
214217
src/core/libraries/kernel/threads/event_flag.cpp
215218
src/core/libraries/kernel/threads/exception.cpp
216219
src/core/libraries/kernel/threads/exception.h

src/common/ntapi.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include "ntapi.h"
77

88
NtClose_t NtClose = nullptr;
9-
NtDelayExecution_t NtDelayExecution = nullptr;
109
NtSetInformationFile_t NtSetInformationFile = nullptr;
1110
NtCreateThread_t NtCreateThread = nullptr;
1211
NtTerminateThread_t NtTerminateThread = nullptr;
@@ -18,7 +17,6 @@ void Initialize() {
1817

1918
// http://stackoverflow.com/a/31411628/4725495
2019
NtClose = (NtClose_t)GetProcAddress(nt_handle, "NtClose");
21-
NtDelayExecution = (NtDelayExecution_t)GetProcAddress(nt_handle, "NtDelayExecution");
2220
NtSetInformationFile =
2321
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
2422
NtCreateThread = (NtCreateThread_t)GetProcAddress(nt_handle, "NtCreateThread");

src/common/ntapi.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ typedef struct _TEB { /* win32/win64 */
408408
#ifdef _WIN64
409409
PVOID SystemReserved1[30]; /* /0190 */
410410
#else
411-
PVOID SystemReserved1[26]; /* 10c/ used for krnl386 private data in Wine */
411+
PVOID SystemReserved1[26]; /* 10c/ */
412412
#endif
413413
char PlaceholderCompatibilityMode; /* 174/0280 */
414414
BOOLEAN PlaceholderHydrationAlwaysExplicit; /* 175/0281 */
@@ -430,13 +430,13 @@ typedef struct _TEB { /* win32/win64 */
430430
BYTE SpareBytes1[23]; /* 1b9/ */
431431
ULONG TxFsContext; /* 1d0/ */
432432
#endif
433-
GDI_TEB_BATCH GdiTebBatch; /* 1d4/02f0 used for ntdll private data in Wine */
433+
GDI_TEB_BATCH GdiTebBatch; /* 1d4/02f0 */
434434
CLIENT_ID RealClientId; /* 6b4/07d8 */
435435
HANDLE GdiCachedProcessHandle; /* 6bc/07e8 */
436436
ULONG GdiClientPID; /* 6c0/07f0 */
437437
ULONG GdiClientTID; /* 6c4/07f4 */
438438
PVOID GdiThreadLocaleInfo; /* 6c8/07f8 */
439-
ULONG_PTR Win32ClientInfo[62]; /* 6cc/0800 used for user32 private data in Wine */
439+
ULONG_PTR Win32ClientInfo[62]; /* 6cc/0800 */
440440
PVOID glDispatchTable[233]; /* 7c4/09f0 */
441441
PVOID glReserved1[29]; /* b68/1138 */
442442
PVOID glReserved2; /* bdc/1220 */
@@ -511,8 +511,6 @@ static_assert(offsetof(TEB, DeallocationStack) ==
511511

512512
typedef u64(__stdcall* NtClose_t)(HANDLE Handle);
513513

514-
typedef u64(__stdcall* NtDelayExecution_t)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
515-
516514
typedef u64(__stdcall* NtSetInformationFile_t)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
517515
PVOID FileInformation, ULONG Length,
518516
FILE_INFORMATION_CLASS FileInformationClass);
@@ -525,7 +523,6 @@ typedef u64(__stdcall* NtCreateThread_t)(PHANDLE ThreadHandle, ACCESS_MASK Desir
525523
typedef u64(__stdcall* NtTerminateThread_t)(HANDLE ThreadHandle, u64 ExitStatus);
526524

527525
extern NtClose_t NtClose;
528-
extern NtDelayExecution_t NtDelayExecution;
529526
extern NtSetInformationFile_t NtSetInformationFile;
530527
extern NtCreateThread_t NtCreateThread;
531528
extern NtTerminateThread_t NtTerminateThread;

src/common/thread.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ void SetCurrentThreadName(const char* name) {
147147
SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data());
148148
}
149149

150+
void SetThreadName(void* thread, const char* name) {
151+
SetThreadDescription(thread, UTF8ToUTF16W(name).data());
152+
}
153+
150154
#else // !MSVC_VER, so must be POSIX threads
151155

152156
// MinGW with the POSIX threading model does not support pthread_setname_np
@@ -170,11 +174,19 @@ void SetCurrentThreadName(const char* name) {
170174
pthread_setname_np(pthread_self(), name);
171175
#endif
172176
}
177+
178+
void SetThreadName(void* thread, const char* name) {
179+
// TODO
180+
}
173181
#endif
174182

175183
#if defined(_WIN32)
176184
void SetCurrentThreadName(const char*) {
177-
// Do Nothing on MingW
185+
// Do Nothing on MinGW
186+
}
187+
188+
void SetThreadName(void* thread, const char* name) {
189+
// Do Nothing on MinGW
178190
}
179191
#endif
180192

src/common/thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority);
2323

2424
void SetCurrentThreadName(const char* name);
2525

26+
void SetThreadName(void* thread, const char* name);
27+
2628
class AccurateTimer {
2729
std::chrono::nanoseconds target_interval{};
2830
std::chrono::nanoseconds total_wait{};

src/core/devices/logger.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ s64 Logger::write(const void* buf, size_t nbytes) {
1515
log(static_cast<const char*>(buf), nbytes);
1616
return nbytes;
1717
}
18+
1819
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
1920
for (int i = 0; i < iovcnt; i++) {
2021
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2+
// SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
#include "mutex.h"
5+
6+
#include "common/assert.h"
7+
8+
namespace Libraries::Kernel {
9+
10+
TimedMutex::TimedMutex() {
11+
#ifdef _WIN64
12+
mtx = CreateMutex(nullptr, false, nullptr);
13+
ASSERT(mtx);
14+
#endif
15+
}
16+
17+
TimedMutex::~TimedMutex() {
18+
#ifdef _WIN64
19+
CloseHandle(mtx);
20+
#endif
21+
}
22+
23+
void TimedMutex::lock() {
24+
#ifdef _WIN64
25+
for (;;) {
26+
u64 res = WaitForSingleObjectEx(mtx, INFINITE, true);
27+
if (res == WAIT_OBJECT_0) {
28+
return;
29+
}
30+
}
31+
#else
32+
mtx.lock();
33+
#endif
34+
}
35+
36+
bool TimedMutex::try_lock() {
37+
#ifdef _WIN64
38+
return WaitForSingleObjectEx(mtx, 0, true) == WAIT_OBJECT_0;
39+
#else
40+
return mtx.try_lock();
41+
#endif
42+
}
43+
44+
void TimedMutex::unlock() {
45+
#ifdef _WIN64
46+
ReleaseMutex(mtx);
47+
#else
48+
mtx.unlock();
49+
#endif
50+
}
51+
52+
} // namespace Libraries::Kernel
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2+
// SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
#pragma once
5+
6+
#include <chrono>
7+
8+
#include "common/types.h"
9+
10+
#ifdef _WIN64
11+
#include <windows.h>
12+
#else
13+
#include <mutex>
14+
#endif
15+
16+
namespace Libraries::Kernel {
17+
18+
class TimedMutex {
19+
public:
20+
TimedMutex();
21+
~TimedMutex();
22+
23+
void lock();
24+
bool try_lock();
25+
26+
void unlock();
27+
28+
template <class Rep, class Period>
29+
bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time) {
30+
#ifdef _WIN64
31+
constexpr auto zero = std::chrono::duration<Rep, Period>::zero();
32+
const auto now = std::chrono::steady_clock::now();
33+
34+
std::chrono::steady_clock::time_point abs_time = now;
35+
if (rel_time > zero) {
36+
constexpr auto max = (std::chrono::steady_clock::time_point::max)();
37+
if (abs_time < max - rel_time) {
38+
abs_time += rel_time;
39+
} else {
40+
abs_time = max;
41+
}
42+
}
43+
44+
return try_lock_until(abs_time);
45+
#else
46+
return mtx.try_lock_for(rel_time);
47+
#endif
48+
}
49+
50+
template <class Clock, class Duration>
51+
bool try_lock_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
52+
#ifdef _WIN64
53+
for (;;) {
54+
const auto now = Clock::now();
55+
if (abs_time <= now) {
56+
return false;
57+
}
58+
59+
const auto rel_ms = std::chrono::ceil<std::chrono::milliseconds>(abs_time - now);
60+
u64 res = WaitForSingleObjectEx(mtx, static_cast<u64>(rel_ms.count()), true);
61+
if (res == WAIT_OBJECT_0) {
62+
return true;
63+
} else if (res == WAIT_TIMEOUT) {
64+
return false;
65+
}
66+
}
67+
#else
68+
return mtx.try_lock_until(abs_time);
69+
#endif
70+
}
71+
72+
private:
73+
#ifdef _WIN64
74+
HANDLE mtx;
75+
#else
76+
std::timed_mutex mtx;
77+
#endif
78+
};
79+
80+
} // namespace Libraries::Kernel
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2+
// SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
#pragma once
5+
6+
#include <atomic>
7+
#include <chrono>
8+
9+
#include "common/assert.h"
10+
#include "common/types.h"
11+
12+
#ifdef _WIN64
13+
#include <windows.h>
14+
#else
15+
#include <semaphore>
16+
#endif
17+
18+
namespace Libraries::Kernel {
19+
20+
template <s64 max>
21+
class Semaphore {
22+
public:
23+
Semaphore(s32 initialCount)
24+
#ifndef _WIN64
25+
: sem{initialCount}
26+
#endif
27+
{
28+
#ifdef _WIN64
29+
sem = CreateSemaphore(nullptr, initialCount, max, nullptr);
30+
ASSERT(sem);
31+
#endif
32+
}
33+
34+
~Semaphore() {
35+
#ifdef _WIN64
36+
CloseHandle(sem);
37+
#endif
38+
}
39+
40+
void release() {
41+
#ifdef _WIN64
42+
ReleaseSemaphore(sem, 1, nullptr);
43+
#else
44+
sem.release();
45+
#endif
46+
}
47+
48+
void acquire() {
49+
#ifdef _WIN64
50+
for (;;) {
51+
u64 res = WaitForSingleObjectEx(sem, INFINITE, true);
52+
if (res == WAIT_OBJECT_0) {
53+
return;
54+
}
55+
}
56+
#else
57+
sem.acquire();
58+
#endif
59+
}
60+
61+
bool try_acquire() {
62+
#ifdef _WIN64
63+
return WaitForSingleObjectEx(sem, 0, true) == WAIT_OBJECT_0;
64+
#else
65+
return sem.try_acquire();
66+
#endif
67+
}
68+
69+
template <class Rep, class Period>
70+
bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) {
71+
#ifdef _WIN64
72+
const auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
73+
const u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
74+
75+
if (timeout_ms == 0) {
76+
return false;
77+
}
78+
79+
return WaitForSingleObjectEx(sem, timeout_ms, true) == WAIT_OBJECT_0;
80+
#else
81+
return sem.try_acquire_for(rel_time);
82+
#endif
83+
}
84+
85+
template <class Clock, class Duration>
86+
bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
87+
#ifdef _WIN64
88+
const auto now = Clock::now();
89+
if (now >= abs_time) {
90+
return false;
91+
}
92+
93+
const auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - now);
94+
const u64 timeout_ms = static_cast<u64>(rel_time.count());
95+
if (timeout_ms == 0) {
96+
return false;
97+
}
98+
99+
u64 res = WaitForSingleObjectEx(sem, static_cast<u64>(timeout_ms), true);
100+
return res == WAIT_OBJECT_0;
101+
#else
102+
return sem.try_acquire_until(abs_time);
103+
#endif
104+
}
105+
106+
private:
107+
#ifdef _WIN64
108+
HANDLE sem;
109+
#else
110+
std::counting_semaphore<max> sem;
111+
#endif
112+
};
113+
114+
using BinarySemaphore = Semaphore<1>;
115+
using CountingSemaphore = Semaphore<0x7FFFFFFF /*ORBIS_KERNEL_SEM_VALUE_MAX*/>;
116+
117+
} // namespace Libraries::Kernel

src/core/libraries/kernel/threads/condvar.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ int PthreadCond::Signal() {
191191
PthreadMutex* mp = td->mutex_obj;
192192
has_user_waiters = SleepqRemove(sq, td);
193193

194-
std::binary_semaphore* waddr = nullptr;
194+
BinarySemaphore* waddr = nullptr;
195195
if (mp->m_owner == curthread) {
196196
if (curthread->nwaiter_defer >= Pthread::MaxDeferWaiters) {
197197
curthread->WakeAll();
@@ -211,7 +211,7 @@ int PthreadCond::Signal() {
211211

212212
struct BroadcastArg {
213213
Pthread* curthread;
214-
std::binary_semaphore* waddrs[Pthread::MaxDeferWaiters];
214+
BinarySemaphore* waddrs[Pthread::MaxDeferWaiters];
215215
int count;
216216
};
217217

src/core/libraries/kernel/threads/event_flag.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ class EventFlagInternal {
118118
}
119119

120120
m_bits |= bits;
121-
122121
m_cond_var.notify_all();
123122
}
124123

0 commit comments

Comments
 (0)