SVC: Correct CreateThread, StartThread, ExitThread, SleepThread.

This commit is contained in:
Fernando Sahmkow 2020-02-25 12:40:33 -04:00
parent 18dcb09342
commit 49ba563995
3 changed files with 31 additions and 37 deletions

View File

@ -1464,13 +1464,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
ASSERT(thread->GetStatus() == ThreadStatus::Dormant); ASSERT(thread->GetStatus() == ThreadStatus::Dormant);
thread->ResumeFromWait(); return thread->Start();
if (thread->GetStatus() == ThreadStatus::Ready) {
system.PrepareReschedule(thread->GetProcessorID());
}
return RESULT_SUCCESS;
} }
/// Called when a thread exits /// Called when a thread exits
@ -1478,9 +1472,8 @@ static void ExitThread(Core::System& system) {
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
current_thread->Stop();
system.GlobalScheduler().RemoveThread(SharedFrom(current_thread)); system.GlobalScheduler().RemoveThread(SharedFrom(current_thread));
system.PrepareReschedule(); current_thread->Stop();
} }
/// Sleep the current thread /// Sleep the current thread
@ -1500,13 +1493,13 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
if (nanoseconds <= 0) { if (nanoseconds <= 0) {
switch (static_cast<SleepType>(nanoseconds)) { switch (static_cast<SleepType>(nanoseconds)) {
case SleepType::YieldWithoutLoadBalancing: case SleepType::YieldWithoutLoadBalancing:
is_redundant = current_thread->YieldSimple(); current_thread->YieldSimple();
break; break;
case SleepType::YieldWithLoadBalancing: case SleepType::YieldWithLoadBalancing:
is_redundant = current_thread->YieldAndBalanceLoad(); current_thread->YieldAndBalanceLoad();
break; break;
case SleepType::YieldAndWaitForLoadBalancing: case SleepType::YieldAndWaitForLoadBalancing:
is_redundant = current_thread->YieldAndWaitForLoadBalancing(); current_thread->YieldAndWaitForLoadBalancing();
break; break;
default: default:
UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
@ -1514,7 +1507,6 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
} else { } else {
current_thread->Sleep(nanoseconds); current_thread->Sleep(nanoseconds);
} }
system.PrepareReschedule(current_thread->GetProcessorID());
} }
/// Wait process wide key atomic /// Wait process wide key atomic

View File

@ -56,12 +56,6 @@ void Thread::Stop() {
SetStatus(ThreadStatus::Dead); SetStatus(ThreadStatus::Dead);
Signal(); Signal();
// Clean up any dangling references in objects that this thread was waiting for
for (auto& wait_object : wait_objects) {
wait_object->RemoveWaitingThread(SharedFrom(this));
}
wait_objects.clear();
owner_process->UnregisterThread(this); owner_process->UnregisterThread(this);
// Mark the TLS slot in the thread's page as free. // Mark the TLS slot in the thread's page as free.
@ -138,6 +132,12 @@ void Thread::OnWakeUp() {
SetStatus(ThreadStatus::Ready); SetStatus(ThreadStatus::Ready);
} }
ResultCode Thread::Start() {
SchedulerLock lock(kernel);
SetStatus(ThreadStatus::Ready);
return RESULT_SUCCESS;
}
void Thread::CancelWait() { void Thread::CancelWait() {
if (GetSchedulingStatus() != ThreadSchedStatus::Paused) { if (GetSchedulingStatus() != ThreadSchedStatus::Paused) {
is_sync_cancelled = true; is_sync_cancelled = true;
@ -188,7 +188,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
void* thread_start_parameter) { void* thread_start_parameter) {
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
// Check if priority is in ranged. Lowest priority -> highest priority id. // Check if priority is in ranged. Lowest priority -> highest priority id.
if (priority > THREADPRIO_LOWEST && (type_flags & THREADTYPE_IDLE == 0)) { if (priority > THREADPRIO_LOWEST && ((type_flags & THREADTYPE_IDLE) == 0)) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority); LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
return ERR_INVALID_THREAD_PRIORITY; return ERR_INVALID_THREAD_PRIORITY;
} }
@ -416,7 +416,7 @@ void Thread::SetActivity(ThreadActivity value) {
} }
} }
void Thread::Sleep(s64 nanoseconds) { ResultCode Thread::Sleep(s64 nanoseconds) {
Handle event_handle{}; Handle event_handle{};
{ {
SchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); SchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
@ -427,33 +427,31 @@ void Thread::Sleep(s64 nanoseconds) {
auto& time_manager = kernel.TimeManager(); auto& time_manager = kernel.TimeManager();
time_manager.UnscheduleTimeEvent(event_handle); time_manager.UnscheduleTimeEvent(event_handle);
} }
return RESULT_SUCCESS;
} }
bool Thread::YieldSimple() { ResultCode Thread::YieldSimple() {
bool result{};
{ {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
result = kernel.GlobalScheduler().YieldThread(this); kernel.GlobalScheduler().YieldThread(this);
} }
return result; return RESULT_SUCCESS;
} }
bool Thread::YieldAndBalanceLoad() { ResultCode Thread::YieldAndBalanceLoad() {
bool result{};
{ {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
result = kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this); kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this);
} }
return result; return RESULT_SUCCESS;
} }
bool Thread::YieldAndWaitForLoadBalancing() { ResultCode Thread::YieldAndWaitForLoadBalancing() {
bool result{};
{ {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
result = kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this); kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this);
} }
return result; return RESULT_SUCCESS;
} }
void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) {

View File

@ -236,6 +236,8 @@ public:
void OnWakeUp(); void OnWakeUp();
ResultCode Start();
/// Cancels a waiting operation that this thread may or may not be within. /// Cancels a waiting operation that this thread may or may not be within.
/// ///
/// When the thread is within a waiting state, this will set the thread's /// When the thread is within a waiting state, this will set the thread's
@ -470,16 +472,16 @@ public:
void SetActivity(ThreadActivity value); void SetActivity(ThreadActivity value);
/// Sleeps this thread for the given amount of nanoseconds. /// Sleeps this thread for the given amount of nanoseconds.
void Sleep(s64 nanoseconds); ResultCode Sleep(s64 nanoseconds);
/// Yields this thread without rebalancing loads. /// Yields this thread without rebalancing loads.
bool YieldSimple(); ResultCode YieldSimple();
/// Yields this thread and does a load rebalancing. /// Yields this thread and does a load rebalancing.
bool YieldAndBalanceLoad(); ResultCode YieldAndBalanceLoad();
/// Yields this thread and if the core is left idle, loads are rebalanced /// Yields this thread and if the core is left idle, loads are rebalanced
bool YieldAndWaitForLoadBalancing(); ResultCode YieldAndWaitForLoadBalancing();
void IncrementYieldCount() { void IncrementYieldCount() {
yield_count++; yield_count++;
@ -603,6 +605,8 @@ private:
bool is_running = false; bool is_running = false;
bool is_sync_cancelled = false; bool is_sync_cancelled = false;
bool will_be_terminated{};
std::string name; std::string name;
}; };