The way to Unity, pt.2 (#1671)

This commit is contained in:
Daniel R.
2024-12-06 22:04:36 +01:00
committed by GitHub
parent 357b7829c3
commit 7ffa581d4b
15 changed files with 311 additions and 28 deletions

View File

@@ -191,7 +191,7 @@ int PthreadCond::Signal() {
PthreadMutex* mp = td->mutex_obj;
has_user_waiters = SleepqRemove(sq, td);
std::binary_semaphore* waddr = nullptr;
BinarySemaphore* waddr = nullptr;
if (mp->m_owner == curthread) {
if (curthread->nwaiter_defer >= Pthread::MaxDeferWaiters) {
curthread->WakeAll();
@@ -211,7 +211,7 @@ int PthreadCond::Signal() {
struct BroadcastArg {
Pthread* curthread;
std::binary_semaphore* waddrs[Pthread::MaxDeferWaiters];
BinarySemaphore* waddrs[Pthread::MaxDeferWaiters];
int count;
};

View File

@@ -118,7 +118,6 @@ public:
}
m_bits |= bits;
m_cond_var.notify_all();
}

View File

@@ -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) {
LOG_INFO(Kernel_Pthread, "name = {}", name);
Common::SetThreadName(reinterpret_cast<void*>(thread->native_thr.GetHandle()), name);
thread->name = name;
return ORBIS_OK;
}

View File

@@ -11,6 +11,8 @@
#include <shared_mutex>
#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/thread.h"
#include "core/tls.h"
@@ -44,7 +46,7 @@ enum class PthreadMutexProt : u32 {
};
struct PthreadMutex {
std::timed_mutex m_lock;
TimedMutex m_lock;
PthreadMutexFlags m_flags;
Pthread* m_owner;
int m_count;
@@ -288,14 +290,14 @@ struct Pthread {
int report_events;
int event_mask;
std::string name;
std::binary_semaphore wake_sema{0};
BinarySemaphore wake_sema{0};
SleepQueue* sleepqueue;
void* wchan;
PthreadMutex* mutex_obj;
bool will_sleep;
bool has_user_waiters;
int nwaiter_defer;
std::binary_semaphore* defer_waiters[MaxDeferWaiters];
BinarySemaphore* defer_waiters[MaxDeferWaiters];
bool InCritical() const noexcept {
return locklevel > 0 || critical_count > 0;

View File

@@ -6,6 +6,8 @@
#include <mutex>
#include <semaphore>
#include "core/libraries/kernel/sync/semaphore.h"
#include "common/logging/log.h"
#include "core/libraries/kernel/kernel.h"
#include "core/libraries/kernel/orbis_error.h"
@@ -21,7 +23,7 @@ constexpr int ORBIS_KERNEL_SEM_VALUE_MAX = 0x7FFFFFFF;
struct PthreadSem {
explicit PthreadSem(s32 value_) : semaphore{value_}, value{value_} {}
std::counting_semaphore<ORBIS_KERNEL_SEM_VALUE_MAX> semaphore;
CountingSemaphore semaphore;
std::atomic<s32> value;
};
@@ -75,7 +77,7 @@ public:
it = wait_list.erase(it);
token_count -= waiter->need_count;
waiter->was_signaled = true;
waiter->cv.notify_one();
waiter->sem.release();
}
return true;
@@ -88,7 +90,7 @@ public:
}
for (auto* waiter : wait_list) {
waiter->was_cancled = true;
waiter->cv.notify_one();
waiter->sem.release();
}
wait_list.clear();
token_count = set_count < 0 ? init_count : set_count;
@@ -99,21 +101,21 @@ public:
std::scoped_lock lk{mutex};
for (auto* waiter : wait_list) {
waiter->was_deleted = true;
waiter->cv.notify_one();
waiter->sem.release();
}
wait_list.clear();
}
public:
struct WaitingThread {
std::condition_variable cv;
BinarySemaphore sem;
u32 priority;
s32 need_count;
bool was_signaled{};
bool was_deleted{};
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.
if (!is_fifo) {
priority = g_curthread->attr.prio;
@@ -134,24 +136,26 @@ public:
}
int Wait(std::unique_lock<std::mutex>& lk, u32* timeout) {
lk.unlock();
if (!timeout) {
// Wait indefinitely until we are woken up.
cv.wait(lk);
sem.acquire();
lk.lock();
return GetResult(false);
}
// Wait until timeout runs out, recording how much remaining time there was.
const auto start = std::chrono::high_resolution_clock::now();
const auto signaled = cv.wait_for(lk, std::chrono::microseconds(*timeout),
[this] { return was_signaled; });
sem.try_acquire_for(std::chrono::microseconds(*timeout));
const auto end = std::chrono::high_resolution_clock::now();
const auto time =
std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if (signaled) {
lk.lock();
if (was_signaled) {
*timeout -= time;
} else {
*timeout = 0;
}
return GetResult(!signaled);
return GetResult(!was_signaled);
}
};