1
0
Fork 0
forked from suyu/suyu

SVC: Correct SetThreadActivity.

This commit is contained in:
Fernando Sahmkow 2020-03-07 12:44:35 -04:00
parent a66c61ca2d
commit 83c7ba1ef7
4 changed files with 59 additions and 38 deletions

View file

@ -417,8 +417,7 @@ void GlobalScheduler::AdjustSchedulingOnStatus(Thread* thread, u32 old_flags) {
} }
ASSERT(is_locked); ASSERT(is_locked);
if (static_cast<ThreadSchedStatus>(old_flags & static_cast<u32>(ThreadSchedMasks::LowMask)) == if (old_flags == static_cast<u32>(ThreadSchedStatus::Runnable)) {
ThreadSchedStatus::Runnable) {
// In this case the thread was running, now it's pausing/exitting // In this case the thread was running, now it's pausing/exitting
if (thread->processor_id >= 0) { if (thread->processor_id >= 0) {
Unschedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread); Unschedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread);
@ -430,7 +429,7 @@ void GlobalScheduler::AdjustSchedulingOnStatus(Thread* thread, u32 old_flags) {
Unsuggest(thread->current_priority, core, thread); Unsuggest(thread->current_priority, core, thread);
} }
} }
} else if (thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable) { } else if (thread->scheduling_state == static_cast<u32>(ThreadSchedStatus::Runnable)) {
// The thread is now set to running from being stopped // The thread is now set to running from being stopped
if (thread->processor_id >= 0) { if (thread->processor_id >= 0) {
Schedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread); Schedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread);
@ -448,7 +447,7 @@ void GlobalScheduler::AdjustSchedulingOnStatus(Thread* thread, u32 old_flags) {
} }
void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priority) { void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priority) {
if (thread->GetSchedulingStatus() != ThreadSchedStatus::Runnable) { if (thread->scheduling_state != static_cast<u32>(ThreadSchedStatus::Runnable)) {
return; return;
} }
ASSERT(is_locked); ASSERT(is_locked);
@ -486,7 +485,7 @@ void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priorit
void GlobalScheduler::AdjustSchedulingOnAffinity(Thread* thread, u64 old_affinity_mask, void GlobalScheduler::AdjustSchedulingOnAffinity(Thread* thread, u64 old_affinity_mask,
s32 old_core) { s32 old_core) {
if (thread->GetSchedulingStatus() != ThreadSchedStatus::Runnable || if (thread->scheduling_state != static_cast<u32>(ThreadSchedStatus::Runnable) ||
thread->current_priority >= THREADPRIO_COUNT) { thread->current_priority >= THREADPRIO_COUNT) {
return; return;
} }

View file

@ -1012,7 +1012,6 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
/// Sets the thread activity /// Sets the thread activity
static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity);
UNIMPLEMENTED();
if (activity > static_cast<u32>(ThreadActivity::Paused)) { if (activity > static_cast<u32>(ThreadActivity::Paused)) {
return ERR_INVALID_ENUM_VALUE; return ERR_INVALID_ENUM_VALUE;
} }
@ -1039,9 +1038,7 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act
return ERR_BUSY; return ERR_BUSY;
} }
thread->SetActivity(static_cast<ThreadActivity>(activity)); return thread->SetActivity(static_cast<ThreadActivity>(activity));
return RESULT_SUCCESS;
} }
/// Gets the thread context /// Gets the thread context

View file

@ -113,20 +113,11 @@ void Thread::ResumeFromWait() {
return; return;
} }
if (activity == ThreadActivity::Paused) {
SetStatus(ThreadStatus::Paused);
return;
}
SetStatus(ThreadStatus::Ready); SetStatus(ThreadStatus::Ready);
} }
void Thread::OnWakeUp() { void Thread::OnWakeUp() {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
if (activity == ThreadActivity::Paused) {
SetStatus(ThreadStatus::Paused);
return;
}
SetStatus(ThreadStatus::Ready); SetStatus(ThreadStatus::Ready);
} }
@ -407,19 +398,31 @@ bool Thread::InvokeHLECallback(std::shared_ptr<Thread> thread) {
return hle_callback(std::move(thread)); return hle_callback(std::move(thread));
} }
void Thread::SetActivity(ThreadActivity value) { ResultCode Thread::SetActivity(ThreadActivity value) {
activity = value; SchedulerLock lock(kernel);
auto sched_status = GetSchedulingStatus();
if (sched_status != ThreadSchedStatus::Runnable && sched_status != ThreadSchedStatus::Paused) {
return ERR_INVALID_STATE;
}
if (IsPendingTermination()) {
return RESULT_SUCCESS;
}
if (value == ThreadActivity::Paused) { if (value == ThreadActivity::Paused) {
// Set status if not waiting if (pausing_state & static_cast<u32>(ThreadSchedFlags::ThreadPauseFlag) != 0) {
if (status == ThreadStatus::Ready || status == ThreadStatus::Running) { return ERR_INVALID_STATE;
SetStatus(ThreadStatus::Paused);
kernel.PrepareReschedule(processor_id);
} }
} else if (status == ThreadStatus::Paused) { AddSchedulingFlag(ThreadSchedFlags::ThreadPauseFlag);
// Ready to reschedule } else {
ResumeFromWait(); if (pausing_state & static_cast<u32>(ThreadSchedFlags::ThreadPauseFlag) == 0) {
return ERR_INVALID_STATE;
} }
RemoveSchedulingFlag(ThreadSchedFlags::ThreadPauseFlag);
}
return RESULT_SUCCESS;
} }
ResultCode Thread::Sleep(s64 nanoseconds) { ResultCode Thread::Sleep(s64 nanoseconds) {
@ -460,11 +463,27 @@ ResultCode Thread::YieldAndWaitForLoadBalancing() {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
void Thread::AddSchedulingFlag(ThreadSchedFlags flag) {
const u32 old_state = scheduling_state;
pausing_state |= static_cast<u32>(flag);
const u32 base_scheduling = static_cast<u32>(GetSchedulingStatus());
scheduling_state = base_scheduling | pausing_state;
kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_state);
}
void Thread::RemoveSchedulingFlag(ThreadSchedFlags flag) {
const u32 old_state = scheduling_state;
pausing_state &= ~static_cast<u32>(flag);
const u32 base_scheduling = static_cast<u32>(GetSchedulingStatus());
scheduling_state = base_scheduling | pausing_state;
kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_state);
}
void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) {
const u32 old_flags = scheduling_state; const u32 old_state = scheduling_state;
scheduling_state = (scheduling_state & static_cast<u32>(ThreadSchedMasks::HighMask)) | scheduling_state = (scheduling_state & static_cast<u32>(ThreadSchedMasks::HighMask)) |
static_cast<u32>(new_status); static_cast<u32>(new_status);
kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_flags); kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_state);
} }
void Thread::SetCurrentPriority(u32 new_priority) { void Thread::SetCurrentPriority(u32 new_priority) {

View file

@ -497,11 +497,7 @@ public:
return affinity_mask; return affinity_mask;
} }
ThreadActivity GetActivity() const { ResultCode SetActivity(ThreadActivity value);
return activity;
}
void SetActivity(ThreadActivity value);
/// Sleeps this thread for the given amount of nanoseconds. /// Sleeps this thread for the given amount of nanoseconds.
ResultCode Sleep(s64 nanoseconds); ResultCode Sleep(s64 nanoseconds);
@ -564,11 +560,22 @@ public:
is_waiting_on_sync = is_waiting; is_waiting_on_sync = is_waiting;
} }
bool IsPendingTermination() const {
return will_be_terminated || GetSchedulingStatus() == ThreadSchedStatus::Exited;
}
bool IsPaused() const {
return pausing_state != 0;
}
private: private:
friend class GlobalScheduler; friend class GlobalScheduler;
friend class Scheduler; friend class Scheduler;
void SetSchedulingStatus(ThreadSchedStatus new_status); void SetSchedulingStatus(ThreadSchedStatus new_status);
void AddSchedulingFlag(ThreadSchedFlags flag);
void RemoveSchedulingFlag(ThreadSchedFlags flag);
void SetCurrentPriority(u32 new_priority); void SetCurrentPriority(u32 new_priority);
void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
@ -650,18 +657,17 @@ private:
u32 ideal_core{0xFFFFFFFF}; u32 ideal_core{0xFFFFFFFF};
u64 affinity_mask{0x1}; u64 affinity_mask{0x1};
ThreadActivity activity = ThreadActivity::Normal;
s32 ideal_core_override = -1; s32 ideal_core_override = -1;
u64 affinity_mask_override = 0x1; u64 affinity_mask_override = 0x1;
u32 affinity_override_count = 0; u32 affinity_override_count = 0;
u32 scheduling_state = 0; u32 scheduling_state = 0;
u32 pausing_state = 0;
bool is_running = false; bool is_running = false;
bool is_waiting_on_sync = false; bool is_waiting_on_sync = false;
bool is_sync_cancelled = false; bool is_sync_cancelled = false;
bool will_be_terminated{}; bool will_be_terminated = false;
std::string name; std::string name;
}; };