From 321fa34892779e82bfe8ba69427e11a2930e488f Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sat, 13 Sep 2025 08:41:26 -0700 Subject: [PATCH] kernel: Improvements to condvars. (#3592) --- src/core/libraries/kernel/sync/semaphore.h | 43 ++++--------------- src/core/libraries/kernel/threads/condvar.cpp | 8 ++-- src/core/libraries/kernel/threads/mutex.cpp | 6 +-- src/core/libraries/kernel/threads/pthread.h | 9 +++- src/core/libraries/kernel/threads/sleepq.cpp | 10 ++--- src/core/libraries/kernel/time.cpp | 2 +- 6 files changed, 28 insertions(+), 50 deletions(-) diff --git a/src/core/libraries/kernel/sync/semaphore.h b/src/core/libraries/kernel/sync/semaphore.h index 738df37d8..71926210f 100644 --- a/src/core/libraries/kernel/sync/semaphore.h +++ b/src/core/libraries/kernel/sync/semaphore.h @@ -87,10 +87,9 @@ public: template bool try_acquire_for(const std::chrono::duration& rel_time) { #ifdef _WIN64 - const auto start_time = std::chrono::high_resolution_clock::now(); auto rel_time_ms = std::chrono::ceil(rel_time); - do { + const auto start_time = std::chrono::high_resolution_clock::now(); u64 timeout_ms = static_cast(rel_time_ms.count()); u64 res = WaitForSingleObjectEx(sem, timeout_ms, true); if (res == WAIT_OBJECT_0) { @@ -105,8 +104,8 @@ public: return false; #elif defined(__APPLE__) - const auto rel_time_ns = std::chrono::ceil(rel_time).count(); - const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns); + const auto rel_time_ns = std::chrono::ceil(rel_time); + const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns.count()); return dispatch_semaphore_wait(sem, timeout) == 0; #else return sem.try_acquire_for(rel_time); @@ -115,37 +114,11 @@ public: template bool try_acquire_until(const std::chrono::time_point& abs_time) { -#ifdef _WIN64 - const auto start_time = Clock::now(); - - auto rel_time = std::chrono::ceil(abs_time - start_time); - do { - u64 timeout_ms = static_cast(rel_time.count()); - u64 res = WaitForSingleObjectEx(sem, timeout_ms, true); - if (res == WAIT_OBJECT_0) { - return true; - } else if (res == WAIT_IO_COMPLETION) { - auto elapsed_time = Clock::now() - start_time; - rel_time -= std::chrono::duration_cast(elapsed_time); - } else { - return false; - } - } while (rel_time.count() > 0); - - return false; -#elif defined(__APPLE__) - auto abs_s = std::chrono::time_point_cast(abs_time); - auto abs_ns = std::chrono::time_point_cast(abs_time) - - std::chrono::time_point_cast(abs_s); - const timespec abs_timespec = { - .tv_sec = abs_s.time_since_epoch().count(), - .tv_nsec = abs_ns.count(), - }; - const auto timeout = dispatch_walltime(&abs_timespec, 0); - return dispatch_semaphore_wait(sem, timeout) == 0; -#else - return sem.try_acquire_until(abs_time); -#endif + const auto current = Clock::now(); + if (current >= abs_time) { + return try_acquire(); + } + return try_acquire_for(abs_time - current); } private: diff --git a/src/core/libraries/kernel/threads/condvar.cpp b/src/core/libraries/kernel/threads/condvar.cpp index 89b2c59d4..bd3822f09 100644 --- a/src/core/libraries/kernel/threads/condvar.cpp +++ b/src/core/libraries/kernel/threads/condvar.cpp @@ -108,7 +108,7 @@ int PthreadCond::Wait(PthreadMutexT* mutex, const OrbisKernelTimespec* abstime, * us to check it without locking in pthread_cond_signal(). */ has_user_waiters = 1; - curthread->will_sleep = 1; + curthread->will_sleep = true; int recurse; mp->CvUnlock(&recurse); @@ -118,7 +118,7 @@ int PthreadCond::Wait(PthreadMutexT* mutex, const OrbisKernelTimespec* abstime, int error = 0; for (;;) { - void(curthread->wake_sema.try_acquire()); + curthread->ClearWake(); SleepqUnlock(this); //_thr_cancel_enter2(curthread, 0); @@ -198,7 +198,7 @@ int PthreadCond::Signal(Pthread* thread) { curthread->WakeAll(); } curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_sema; - mp->m_flags |= PthreadMutexFlags::Defered; + mp->m_flags |= PthreadMutexFlags::Deferred; } else { waddr = &td->wake_sema; } @@ -231,7 +231,7 @@ int PthreadCond::Broadcast() { curthread->WakeAll(); } curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_sema; - mp->m_flags |= PthreadMutexFlags::Defered; + mp->m_flags |= PthreadMutexFlags::Deferred; } else { if (ba->count >= Pthread::MaxDeferWaiters) { for (int i = 0; i < ba->count; i++) { diff --git a/src/core/libraries/kernel/threads/mutex.cpp b/src/core/libraries/kernel/threads/mutex.cpp index d619367c9..af5f43cb3 100644 --- a/src/core/libraries/kernel/threads/mutex.cpp +++ b/src/core/libraries/kernel/threads/mutex.cpp @@ -282,13 +282,13 @@ int PthreadMutex::Unlock() { if (Type() == PthreadMutexType::Recursive && m_count > 0) [[unlikely]] { m_count--; } else { - int defered = True(m_flags & PthreadMutexFlags::Defered); - m_flags &= ~PthreadMutexFlags::Defered; + const bool deferred = True(m_flags & PthreadMutexFlags::Deferred); + m_flags &= ~PthreadMutexFlags::Deferred; m_owner = nullptr; m_lock.unlock(); - if (curthread->will_sleep == 0 && defered) { + if (curthread->will_sleep == 0 && deferred) { curthread->WakeAll(); } } diff --git a/src/core/libraries/kernel/threads/pthread.h b/src/core/libraries/kernel/threads/pthread.h index ebcc4aed3..f002598fd 100644 --- a/src/core/libraries/kernel/threads/pthread.h +++ b/src/core/libraries/kernel/threads/pthread.h @@ -27,7 +27,7 @@ struct Pthread; enum class PthreadMutexFlags : u32 { TypeMask = 0xff, - Defered = 0x200, + Deferred = 0x200, }; DECLARE_ENUM_FLAG_OPERATORS(PthreadMutexFlags) @@ -319,8 +319,13 @@ struct Pthread { nwaiter_defer = 0; } + void ClearWake() { + // Try to acquire wake semaphore to reset it. + void(wake_sema.try_acquire()); + } + bool Sleep(const OrbisKernelTimespec* abstime, u64 usec) { - will_sleep = 0; + will_sleep = false; if (nwaiter_defer > 0) { WakeAll(); } diff --git a/src/core/libraries/kernel/threads/sleepq.cpp b/src/core/libraries/kernel/threads/sleepq.cpp index d998141d0..7d21c91d4 100644 --- a/src/core/libraries/kernel/threads/sleepq.cpp +++ b/src/core/libraries/kernel/threads/sleepq.cpp @@ -53,7 +53,7 @@ void SleepqAdd(void* wchan, Pthread* td) { sq->sq_wchan = wchan; /* sq->sq_type = type; */ } - td->sleepqueue = NULL; + td->sleepqueue = nullptr; td->wchan = wchan; sq->sq_blocked.push_front(td); } @@ -88,10 +88,10 @@ void SleepqDrop(SleepQueue* sq, void (*callback)(Pthread*, void*), void* arg) { td->wchan = nullptr; auto sq2 = sq->sq_freeq.begin(); - for (Pthread* td : sq->sq_blocked) { - callback(td, arg); - td->sleepqueue = std::addressof(*sq2); - td->wchan = nullptr; + for (Pthread* td2 : sq->sq_blocked) { + callback(td2, arg); + td2->sleepqueue = std::addressof(*sq2); + td2->wchan = nullptr; ++sq2; } sq->sq_blocked.clear(); diff --git a/src/core/libraries/kernel/time.cpp b/src/core/libraries/kernel/time.cpp index 8e070e683..ffdcc8bc2 100644 --- a/src/core/libraries/kernel/time.cpp +++ b/src/core/libraries/kernel/time.cpp @@ -16,7 +16,7 @@ #include #include "common/ntapi.h" #else -#if __APPLE__ +#ifdef __APPLE__ #include #endif #include