mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
SVC: Correct SetThreadActivity.
This commit is contained in:
parent
a66c61ca2d
commit
83c7ba1ef7
4 changed files with 59 additions and 38 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -143,7 +134,7 @@ void Thread::CancelWait() {
|
||||||
is_sync_cancelled = true;
|
is_sync_cancelled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO(Blinkhawk): Implement cancel of server session
|
// TODO(Blinkhawk): Implement cancel of server session
|
||||||
is_sync_cancelled = false;
|
is_sync_cancelled = false;
|
||||||
SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED);
|
SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED);
|
||||||
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) {
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue