mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-20 23:50:46 +01:00
[orbis-kernel] Implement umtx_sem_wait +...
umtx_sem_wake Use duration_cast
This commit is contained in:
parent
b5f8657732
commit
1ea8e148fa
|
|
@ -88,10 +88,8 @@ ErrorCode umtx_rw_unlock(Thread *thread, ptr<void> obj, std::int64_t val,
|
|||
ErrorCode umtx_wake_private(Thread *thread, ptr<void> uaddr, sint n_wake);
|
||||
ErrorCode umtx_wait_umutex(Thread *thread, ptr<umutex> m, std::uint64_t ut);
|
||||
ErrorCode umtx_wake_umutex(Thread *thread, ptr<umutex> m);
|
||||
ErrorCode umtx_sem_wait(Thread *thread, ptr<void> obj, std::int64_t val,
|
||||
ptr<void> uaddr1, ptr<void> uaddr2);
|
||||
ErrorCode umtx_sem_wake(Thread *thread, ptr<void> obj, std::int64_t val,
|
||||
ptr<void> uaddr1, ptr<void> uaddr2);
|
||||
ErrorCode umtx_sem_wait(Thread *thread, ptr<usem> sem, std::uint64_t ut);
|
||||
ErrorCode umtx_sem_wake(Thread *thread, ptr<usem> sem);
|
||||
ErrorCode umtx_nwake_private(Thread *thread, ptr<void *> uaddrs,
|
||||
std::int64_t count);
|
||||
ErrorCode umtx_wake2_umutex(Thread *thread, ptr<void> obj, std::int64_t val,
|
||||
|
|
|
|||
|
|
@ -66,7 +66,9 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
while (true) {
|
||||
if (auto r = op(usec - udiff); r != ErrorCode::TIMEDOUT)
|
||||
return r;
|
||||
udiff = (std::chrono::steady_clock::now() - start).count() / 1000;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count();
|
||||
if (udiff >= usec)
|
||||
return ErrorCode::TIMEDOUT;
|
||||
}
|
||||
|
|
@ -142,9 +144,13 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
case 18:
|
||||
return umtx_wake_umutex(thread, (ptr<umutex>)obj);
|
||||
case 19:
|
||||
return umtx_sem_wait(thread, obj, val, uaddr1, uaddr2);
|
||||
return with_timeout(
|
||||
[&](std::uint64_t ut) {
|
||||
return umtx_sem_wait(thread, (ptr<usem>)obj, ut);
|
||||
},
|
||||
false);
|
||||
case 20:
|
||||
return umtx_sem_wake(thread, obj, val, uaddr1, uaddr2);
|
||||
return umtx_sem_wake(thread, (ptr<usem>)obj);
|
||||
case 21:
|
||||
return umtx_nwake_private(thread, (ptr<void *>)obj, val);
|
||||
case 22:
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
|||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = (std::chrono::steady_clock::now() - start).count() / 1000;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count();
|
||||
if (udiff >= ut) {
|
||||
result = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
|
|
@ -315,7 +317,9 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
|
|||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = (std::chrono::steady_clock::now() - start).count() / 1000;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count();
|
||||
if (udiff >= ut) {
|
||||
result = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
|
|
@ -415,18 +419,59 @@ orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr<umutex> m) {
|
|||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<void> obj,
|
||||
std::int64_t val, ptr<void> uaddr1,
|
||||
ptr<void> uaddr2) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, obj, val, uaddr1, uaddr2);
|
||||
return ErrorCode::NOSYS;
|
||||
orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sem, ut);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, sem);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
|
||||
std::uint32_t has_waiters = sem->has_waiters;
|
||||
if (!has_waiters)
|
||||
sem->has_waiters.compare_exchange_strong(has_waiters, 1);
|
||||
|
||||
ErrorCode result = {};
|
||||
if (!sem->count) {
|
||||
if (ut + 1 == 0) {
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
node->second.cv.wait(chain.mtx, ut - udiff);
|
||||
if (node->second.thr != thread)
|
||||
break;
|
||||
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count();
|
||||
if (udiff >= ut) {
|
||||
result = ErrorCode::TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node->second.thr != thread) {
|
||||
result = {};
|
||||
} else {
|
||||
chain.erase(node);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_sem_wake(Thread *thread, ptr<void> obj,
|
||||
std::int64_t val, ptr<void> uaddr1,
|
||||
ptr<void> uaddr2) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, obj, val, uaddr1, uaddr2);
|
||||
return ErrorCode::NOSYS;
|
||||
orbis::ErrorCode orbis::umtx_sem_wake(Thread *thread, ptr<usem> sem) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sem);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, sem);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
if (auto up = chain.notify_one(key); up >= count)
|
||||
thread->retval[0] = sem->has_waiters;
|
||||
else
|
||||
thread->retval[0] = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_nwake_private(Thread *thread, ptr<void *> uaddrs,
|
||||
|
|
|
|||
Loading…
Reference in a new issue