mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-30 18:34:38 +01:00
Implement WaitSynchronization
This commit is contained in:
parent
7fde5fbe40
commit
e57203a7d4
@ -100,7 +100,7 @@ class ResultError : public ResultBase<ResultError<module, description>> {
|
||||
DEFINE_RESULT(Kernel, InvalidCapabilityDescriptor, 14);
|
||||
|
||||
DEFINE_RESULT(Kernel, NotImplemented, 33);
|
||||
DEFINE_RESULT(Kernel, ThreadTerminated, 59);
|
||||
DEFINE_RESULT(Kernel, ThreadTerminating, 59);
|
||||
|
||||
DEFINE_RESULT(Kernel, OutOfDebugEvents, 70);
|
||||
|
||||
|
@ -31,13 +31,13 @@ class IAlarmable : public AlarmableSetBaseHook {
|
||||
template<typename Clock, typename Duration>
|
||||
void SetAlarmTime(const std::chrono::time_point<Clock, Duration> &alarmTime)
|
||||
{
|
||||
SetAlarmTime(alarmTime);
|
||||
SetAlarmTimeImpl(alarmTime);
|
||||
}
|
||||
|
||||
template<typename Rep, typename Period>
|
||||
void SetAlarmIn(const std::chrono::duration<Rep, Period> &alarmTimeOffset)
|
||||
{
|
||||
SetAlarmTime(KSystemClock::now() + alarmTimeOffset);
|
||||
SetAlarmTimeImpl(KSystemClock::now() + alarmTimeOffset);
|
||||
}
|
||||
|
||||
void ClearAlarm();
|
||||
|
@ -210,6 +210,12 @@ class KThread final :
|
||||
/// Takes effect when critical section is left
|
||||
void HandleSyncObjectSignaled(KSynchronizationObject *syncObj);
|
||||
|
||||
template<typename Clock, typename Duration>
|
||||
Result WaitSynchronization(int &outId, KSynchronizationObject **syncObjs, int numSyncObjs, const std::chrono::time_point<Clock, Duration> &timeoutTime)
|
||||
{
|
||||
return WaitSynchronizationImpl(outId, syncObjs, numSyncObjs, timeoutTime);
|
||||
}
|
||||
|
||||
constexpr size_t GetNumberOfKMutexWaiters() const { return numKernelMutexWaiters; }
|
||||
constexpr uiptr GetWantedMutex() const { return wantedMutex; }
|
||||
void SetWantedMutex(uiptr mtx) { wantedMutex = mtx; }
|
||||
@ -224,6 +230,8 @@ class KThread final :
|
||||
id(id), basePriority(priority), priority(priority),
|
||||
currentCoreId(0), affinityMask(15) {};
|
||||
private:
|
||||
Result WaitSynchronizationImpl(int &outId, KSynchronizationObject **syncObjs, int numSyncObjs, const KSystemClock::time_point &timeoutTime);
|
||||
|
||||
void AddToMutexWaitList(KThread &thread);
|
||||
MutexWaitList::iterator RemoveFromMutexWaitList(MutexWaitList::const_iterator it);
|
||||
void RemoveFromMutexWaitList(const KThread &t);
|
||||
@ -242,7 +250,8 @@ private:
|
||||
uint basePriority = 64, priority = 64;
|
||||
int currentCoreId = -1;
|
||||
ulong affinityMask = 0;
|
||||
|
||||
bool cancelled = false;
|
||||
bool isWaitingSync = false;
|
||||
uiptr wantedMutex = 0;
|
||||
KThread *wantedMutexOwner = nullptr;
|
||||
MutexWaitList mutexWaitList{};
|
||||
|
@ -32,7 +32,8 @@ void KThread::AdjustScheduling(ushort oldMaskFull)
|
||||
|
||||
void KThread::Reschedule(KThread::SchedulingStatus newStatus)
|
||||
{
|
||||
std::lock_guard criticalSection{KScheduler::GetCriticalSection()};
|
||||
//std::lock_guard criticalSection{KScheduler::GetCriticalSection()};
|
||||
// TODO check the above ^
|
||||
AdjustScheduling(SetSchedulingStatusField(newStatus));
|
||||
}
|
||||
|
||||
@ -129,6 +130,72 @@ void KThread::HandleSyncObjectSignaled(KSynchronizationObject *syncObj)
|
||||
}
|
||||
}
|
||||
|
||||
Result KThread::WaitSynchronizationImpl(int &outId, KSynchronizationObject **syncObjs, int numSyncObjs, const KSystemClock::time_point &timeoutTime)
|
||||
{
|
||||
KLinkedList<KThread *>::const_iterator nodes[numSyncObjs];
|
||||
|
||||
outId = -1;
|
||||
{
|
||||
std::lock_guard criticalSection{KScheduler::GetCriticalSection()};
|
||||
|
||||
// Try to find an already signaled object.
|
||||
if (numSyncObjs >= 1) {
|
||||
KSynchronizationObject **readyFound = std::find_if(
|
||||
syncObjs,
|
||||
syncObjs + numSyncObjs,
|
||||
[](KSynchronizationObject *obj) {
|
||||
return obj->IsSignaled();
|
||||
}
|
||||
);
|
||||
|
||||
outId = readyFound - syncObjs >= numSyncObjs ? -1 : readyFound - syncObjs;
|
||||
}
|
||||
|
||||
if (timeoutTime == KSystemClock::time_point{} && outId == -1) {
|
||||
return ResultKernelTimedOut{};
|
||||
}
|
||||
if (IsDying()) {
|
||||
return ResultKernelThreadTerminating{};
|
||||
}
|
||||
if (cancelled) {
|
||||
return ResultKernelCancelled{};
|
||||
}
|
||||
|
||||
for (int i = 0; i < numSyncObjs; i++) {
|
||||
nodes[i] = syncObjs[i]->AddWaiter(*this);
|
||||
}
|
||||
|
||||
isWaitingSync = true;
|
||||
signaledSyncObject = nullptr;
|
||||
syncResult = ResultKernelTimedOut{};
|
||||
|
||||
Reschedule(SchedulingStatus::Paused);
|
||||
if (timeoutTime > KSystemClock::time_point{}) {
|
||||
SetAlarmTime(timeoutTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Now waiting...
|
||||
|
||||
{
|
||||
std::lock_guard criticalSection{KScheduler::GetCriticalSection()};
|
||||
|
||||
isWaitingSync = false;
|
||||
if (timeoutTime > KSystemClock::time_point{}) {
|
||||
ClearAlarm();
|
||||
}
|
||||
|
||||
for (int i = 0; i < numSyncObjs; i++) {
|
||||
syncObjs[i]->RemoveWaiter(nodes[i]);
|
||||
if (syncObjs[i] == signaledSyncObject) {
|
||||
outId = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return syncResult;
|
||||
}
|
||||
|
||||
void KThread::AddToMutexWaitList(KThread &thread)
|
||||
{
|
||||
// TODO: check&increment numKernelMutexWaiters
|
||||
|
Loading…
Reference in New Issue
Block a user