mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-05 11:58:00 +00:00
Implement WaitSynchronization
This commit is contained in:
parent
7fde5fbe40
commit
e57203a7d4
4 changed files with 81 additions and 5 deletions
|
@ -100,7 +100,7 @@ class ResultError : public ResultBase<ResultError<module, description>> {
|
||||||
DEFINE_RESULT(Kernel, InvalidCapabilityDescriptor, 14);
|
DEFINE_RESULT(Kernel, InvalidCapabilityDescriptor, 14);
|
||||||
|
|
||||||
DEFINE_RESULT(Kernel, NotImplemented, 33);
|
DEFINE_RESULT(Kernel, NotImplemented, 33);
|
||||||
DEFINE_RESULT(Kernel, ThreadTerminated, 59);
|
DEFINE_RESULT(Kernel, ThreadTerminating, 59);
|
||||||
|
|
||||||
DEFINE_RESULT(Kernel, OutOfDebugEvents, 70);
|
DEFINE_RESULT(Kernel, OutOfDebugEvents, 70);
|
||||||
|
|
||||||
|
|
|
@ -31,13 +31,13 @@ class IAlarmable : public AlarmableSetBaseHook {
|
||||||
template<typename Clock, typename Duration>
|
template<typename Clock, typename Duration>
|
||||||
void SetAlarmTime(const std::chrono::time_point<Clock, Duration> &alarmTime)
|
void SetAlarmTime(const std::chrono::time_point<Clock, Duration> &alarmTime)
|
||||||
{
|
{
|
||||||
SetAlarmTime(alarmTime);
|
SetAlarmTimeImpl(alarmTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Rep, typename Period>
|
template<typename Rep, typename Period>
|
||||||
void SetAlarmIn(const std::chrono::duration<Rep, Period> &alarmTimeOffset)
|
void SetAlarmIn(const std::chrono::duration<Rep, Period> &alarmTimeOffset)
|
||||||
{
|
{
|
||||||
SetAlarmTime(KSystemClock::now() + alarmTimeOffset);
|
SetAlarmTimeImpl(KSystemClock::now() + alarmTimeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearAlarm();
|
void ClearAlarm();
|
||||||
|
|
|
@ -210,6 +210,12 @@ class KThread final :
|
||||||
/// Takes effect when critical section is left
|
/// Takes effect when critical section is left
|
||||||
void HandleSyncObjectSignaled(KSynchronizationObject *syncObj);
|
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 size_t GetNumberOfKMutexWaiters() const { return numKernelMutexWaiters; }
|
||||||
constexpr uiptr GetWantedMutex() const { return wantedMutex; }
|
constexpr uiptr GetWantedMutex() const { return wantedMutex; }
|
||||||
void SetWantedMutex(uiptr mtx) { wantedMutex = mtx; }
|
void SetWantedMutex(uiptr mtx) { wantedMutex = mtx; }
|
||||||
|
@ -224,6 +230,8 @@ class KThread final :
|
||||||
id(id), basePriority(priority), priority(priority),
|
id(id), basePriority(priority), priority(priority),
|
||||||
currentCoreId(0), affinityMask(15) {};
|
currentCoreId(0), affinityMask(15) {};
|
||||||
private:
|
private:
|
||||||
|
Result WaitSynchronizationImpl(int &outId, KSynchronizationObject **syncObjs, int numSyncObjs, const KSystemClock::time_point &timeoutTime);
|
||||||
|
|
||||||
void AddToMutexWaitList(KThread &thread);
|
void AddToMutexWaitList(KThread &thread);
|
||||||
MutexWaitList::iterator RemoveFromMutexWaitList(MutexWaitList::const_iterator it);
|
MutexWaitList::iterator RemoveFromMutexWaitList(MutexWaitList::const_iterator it);
|
||||||
void RemoveFromMutexWaitList(const KThread &t);
|
void RemoveFromMutexWaitList(const KThread &t);
|
||||||
|
@ -242,7 +250,8 @@ private:
|
||||||
uint basePriority = 64, priority = 64;
|
uint basePriority = 64, priority = 64;
|
||||||
int currentCoreId = -1;
|
int currentCoreId = -1;
|
||||||
ulong affinityMask = 0;
|
ulong affinityMask = 0;
|
||||||
|
bool cancelled = false;
|
||||||
|
bool isWaitingSync = false;
|
||||||
uiptr wantedMutex = 0;
|
uiptr wantedMutex = 0;
|
||||||
KThread *wantedMutexOwner = nullptr;
|
KThread *wantedMutexOwner = nullptr;
|
||||||
MutexWaitList mutexWaitList{};
|
MutexWaitList mutexWaitList{};
|
||||||
|
|
|
@ -32,7 +32,8 @@ void KThread::AdjustScheduling(ushort oldMaskFull)
|
||||||
|
|
||||||
void KThread::Reschedule(KThread::SchedulingStatus newStatus)
|
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));
|
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)
|
void KThread::AddToMutexWaitList(KThread &thread)
|
||||||
{
|
{
|
||||||
// TODO: check&increment numKernelMutexWaiters
|
// TODO: check&increment numKernelMutexWaiters
|
||||||
|
|
Loading…
Reference in a new issue