kernel: Improvements to condvars. (#3592)

This commit is contained in:
squidbus
2025-09-13 08:41:26 -07:00
committed by GitHub
parent 70d33be7b7
commit 321fa34892
6 changed files with 28 additions and 50 deletions

View File

@@ -87,10 +87,9 @@ public:
template <class Rep, class Period> template <class Rep, class Period>
bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) { bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) {
#ifdef _WIN64 #ifdef _WIN64
const auto start_time = std::chrono::high_resolution_clock::now();
auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time); auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
do { do {
const auto start_time = std::chrono::high_resolution_clock::now();
u64 timeout_ms = static_cast<u64>(rel_time_ms.count()); u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
u64 res = WaitForSingleObjectEx(sem, timeout_ms, true); u64 res = WaitForSingleObjectEx(sem, timeout_ms, true);
if (res == WAIT_OBJECT_0) { if (res == WAIT_OBJECT_0) {
@@ -105,8 +104,8 @@ public:
return false; return false;
#elif defined(__APPLE__) #elif defined(__APPLE__)
const auto rel_time_ns = std::chrono::ceil<std::chrono::nanoseconds>(rel_time).count(); const auto rel_time_ns = std::chrono::ceil<std::chrono::nanoseconds>(rel_time);
const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns); const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns.count());
return dispatch_semaphore_wait(sem, timeout) == 0; return dispatch_semaphore_wait(sem, timeout) == 0;
#else #else
return sem.try_acquire_for(rel_time); return sem.try_acquire_for(rel_time);
@@ -115,37 +114,11 @@ public:
template <class Clock, class Duration> template <class Clock, class Duration>
bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) { bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
#ifdef _WIN64 const auto current = Clock::now();
const auto start_time = Clock::now(); if (current >= abs_time) {
return try_acquire();
auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - start_time);
do {
u64 timeout_ms = static_cast<u64>(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<std::chrono::milliseconds>(elapsed_time);
} else {
return false;
} }
} while (rel_time.count() > 0); return try_acquire_for(abs_time - current);
return false;
#elif defined(__APPLE__)
auto abs_s = std::chrono::time_point_cast<std::chrono::seconds>(abs_time);
auto abs_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(abs_time) -
std::chrono::time_point_cast<std::chrono::nanoseconds>(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
} }
private: private:

View File

@@ -108,7 +108,7 @@ int PthreadCond::Wait(PthreadMutexT* mutex, const OrbisKernelTimespec* abstime,
* us to check it without locking in pthread_cond_signal(). * us to check it without locking in pthread_cond_signal().
*/ */
has_user_waiters = 1; has_user_waiters = 1;
curthread->will_sleep = 1; curthread->will_sleep = true;
int recurse; int recurse;
mp->CvUnlock(&recurse); mp->CvUnlock(&recurse);
@@ -118,7 +118,7 @@ int PthreadCond::Wait(PthreadMutexT* mutex, const OrbisKernelTimespec* abstime,
int error = 0; int error = 0;
for (;;) { for (;;) {
void(curthread->wake_sema.try_acquire()); curthread->ClearWake();
SleepqUnlock(this); SleepqUnlock(this);
//_thr_cancel_enter2(curthread, 0); //_thr_cancel_enter2(curthread, 0);
@@ -198,7 +198,7 @@ int PthreadCond::Signal(Pthread* thread) {
curthread->WakeAll(); curthread->WakeAll();
} }
curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_sema; curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_sema;
mp->m_flags |= PthreadMutexFlags::Defered; mp->m_flags |= PthreadMutexFlags::Deferred;
} else { } else {
waddr = &td->wake_sema; waddr = &td->wake_sema;
} }
@@ -231,7 +231,7 @@ int PthreadCond::Broadcast() {
curthread->WakeAll(); curthread->WakeAll();
} }
curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_sema; curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_sema;
mp->m_flags |= PthreadMutexFlags::Defered; mp->m_flags |= PthreadMutexFlags::Deferred;
} else { } else {
if (ba->count >= Pthread::MaxDeferWaiters) { if (ba->count >= Pthread::MaxDeferWaiters) {
for (int i = 0; i < ba->count; i++) { for (int i = 0; i < ba->count; i++) {

View File

@@ -282,13 +282,13 @@ int PthreadMutex::Unlock() {
if (Type() == PthreadMutexType::Recursive && m_count > 0) [[unlikely]] { if (Type() == PthreadMutexType::Recursive && m_count > 0) [[unlikely]] {
m_count--; m_count--;
} else { } else {
int defered = True(m_flags & PthreadMutexFlags::Defered); const bool deferred = True(m_flags & PthreadMutexFlags::Deferred);
m_flags &= ~PthreadMutexFlags::Defered; m_flags &= ~PthreadMutexFlags::Deferred;
m_owner = nullptr; m_owner = nullptr;
m_lock.unlock(); m_lock.unlock();
if (curthread->will_sleep == 0 && defered) { if (curthread->will_sleep == 0 && deferred) {
curthread->WakeAll(); curthread->WakeAll();
} }
} }

View File

@@ -27,7 +27,7 @@ struct Pthread;
enum class PthreadMutexFlags : u32 { enum class PthreadMutexFlags : u32 {
TypeMask = 0xff, TypeMask = 0xff,
Defered = 0x200, Deferred = 0x200,
}; };
DECLARE_ENUM_FLAG_OPERATORS(PthreadMutexFlags) DECLARE_ENUM_FLAG_OPERATORS(PthreadMutexFlags)
@@ -319,8 +319,13 @@ struct Pthread {
nwaiter_defer = 0; 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) { bool Sleep(const OrbisKernelTimespec* abstime, u64 usec) {
will_sleep = 0; will_sleep = false;
if (nwaiter_defer > 0) { if (nwaiter_defer > 0) {
WakeAll(); WakeAll();
} }

View File

@@ -53,7 +53,7 @@ void SleepqAdd(void* wchan, Pthread* td) {
sq->sq_wchan = wchan; sq->sq_wchan = wchan;
/* sq->sq_type = type; */ /* sq->sq_type = type; */
} }
td->sleepqueue = NULL; td->sleepqueue = nullptr;
td->wchan = wchan; td->wchan = wchan;
sq->sq_blocked.push_front(td); sq->sq_blocked.push_front(td);
} }
@@ -88,10 +88,10 @@ void SleepqDrop(SleepQueue* sq, void (*callback)(Pthread*, void*), void* arg) {
td->wchan = nullptr; td->wchan = nullptr;
auto sq2 = sq->sq_freeq.begin(); auto sq2 = sq->sq_freeq.begin();
for (Pthread* td : sq->sq_blocked) { for (Pthread* td2 : sq->sq_blocked) {
callback(td, arg); callback(td2, arg);
td->sleepqueue = std::addressof(*sq2); td2->sleepqueue = std::addressof(*sq2);
td->wchan = nullptr; td2->wchan = nullptr;
++sq2; ++sq2;
} }
sq->sq_blocked.clear(); sq->sq_blocked.clear();

View File

@@ -16,7 +16,7 @@
#include <windows.h> #include <windows.h>
#include "common/ntapi.h" #include "common/ntapi.h"
#else #else
#if __APPLE__ #ifdef __APPLE__
#include <date/tz.h> #include <date/tz.h>
#endif #endif
#include <ctime> #include <ctime>