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>
bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) {
#ifdef _WIN64
const auto start_time = std::chrono::high_resolution_clock::now();
auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
do {
const auto start_time = std::chrono::high_resolution_clock::now();
u64 timeout_ms = static_cast<u64>(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<std::chrono::nanoseconds>(rel_time).count();
const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns);
const auto rel_time_ns = std::chrono::ceil<std::chrono::nanoseconds>(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 <class Clock, class Duration>
bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
#ifdef _WIN64
const auto start_time = Clock::now();
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 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
const auto current = Clock::now();
if (current >= abs_time) {
return try_acquire();
}
return try_acquire_for(abs_time - current);
}
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().
*/
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++) {

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -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();

View File

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