SVC: Correct CreateThread, StartThread, ExitThread, SleepThread.
This commit is contained in:
parent
18dcb09342
commit
49ba563995
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user