summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-25 12:40:33 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:11 -0400
commit49ba56399563a87f29b4d89eb04b1178a571eb61 (patch)
tree3da8def77e63141936483c64f7e13bfe89e614fa
parentHostTiming: Pause the hardware clock on pause. (diff)
downloadyuzu-49ba56399563a87f29b4d89eb04b1178a571eb61.tar.gz
yuzu-49ba56399563a87f29b4d89eb04b1178a571eb61.tar.xz
yuzu-49ba56399563a87f29b4d89eb04b1178a571eb61.zip
SVC: Correct CreateThread, StartThread, ExitThread, SleepThread.
-rw-r--r--src/core/hle/kernel/svc.cpp18
-rw-r--r--src/core/hle/kernel/thread.cpp38
-rw-r--r--src/core/hle/kernel/thread.h12
3 files changed, 31 insertions, 37 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index d7f0dcabd..dfb032b4b 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1464,13 +1464,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
1464 1464
1465 ASSERT(thread->GetStatus() == ThreadStatus::Dormant); 1465 ASSERT(thread->GetStatus() == ThreadStatus::Dormant);
1466 1466
1467 thread->ResumeFromWait(); 1467 return thread->Start();
1468
1469 if (thread->GetStatus() == ThreadStatus::Ready) {
1470 system.PrepareReschedule(thread->GetProcessorID());
1471 }
1472
1473 return RESULT_SUCCESS;
1474} 1468}
1475 1469
1476/// Called when a thread exits 1470/// Called when a thread exits
@@ -1478,9 +1472,8 @@ static void ExitThread(Core::System& system) {
1478 LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); 1472 LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
1479 1473
1480 auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); 1474 auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
1481 current_thread->Stop();
1482 system.GlobalScheduler().RemoveThread(SharedFrom(current_thread)); 1475 system.GlobalScheduler().RemoveThread(SharedFrom(current_thread));
1483 system.PrepareReschedule(); 1476 current_thread->Stop();
1484} 1477}
1485 1478
1486/// Sleep the current thread 1479/// Sleep the current thread
@@ -1500,13 +1493,13 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
1500 if (nanoseconds <= 0) { 1493 if (nanoseconds <= 0) {
1501 switch (static_cast<SleepType>(nanoseconds)) { 1494 switch (static_cast<SleepType>(nanoseconds)) {
1502 case SleepType::YieldWithoutLoadBalancing: 1495 case SleepType::YieldWithoutLoadBalancing:
1503 is_redundant = current_thread->YieldSimple(); 1496 current_thread->YieldSimple();
1504 break; 1497 break;
1505 case SleepType::YieldWithLoadBalancing: 1498 case SleepType::YieldWithLoadBalancing:
1506 is_redundant = current_thread->YieldAndBalanceLoad(); 1499 current_thread->YieldAndBalanceLoad();
1507 break; 1500 break;
1508 case SleepType::YieldAndWaitForLoadBalancing: 1501 case SleepType::YieldAndWaitForLoadBalancing:
1509 is_redundant = current_thread->YieldAndWaitForLoadBalancing(); 1502 current_thread->YieldAndWaitForLoadBalancing();
1510 break; 1503 break;
1511 default: 1504 default:
1512 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); 1505 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
@@ -1514,7 +1507,6 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
1514 } else { 1507 } else {
1515 current_thread->Sleep(nanoseconds); 1508 current_thread->Sleep(nanoseconds);
1516 } 1509 }
1517 system.PrepareReschedule(current_thread->GetProcessorID());
1518} 1510}
1519 1511
1520/// Wait process wide key atomic 1512/// Wait process wide key atomic
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 8cb3593db..d9e610272 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -56,12 +56,6 @@ void Thread::Stop() {
56 SetStatus(ThreadStatus::Dead); 56 SetStatus(ThreadStatus::Dead);
57 Signal(); 57 Signal();
58 58
59 // Clean up any dangling references in objects that this thread was waiting for
60 for (auto& wait_object : wait_objects) {
61 wait_object->RemoveWaitingThread(SharedFrom(this));
62 }
63 wait_objects.clear();
64
65 owner_process->UnregisterThread(this); 59 owner_process->UnregisterThread(this);
66 60
67 // Mark the TLS slot in the thread's page as free. 61 // Mark the TLS slot in the thread's page as free.
@@ -138,6 +132,12 @@ void Thread::OnWakeUp() {
138 SetStatus(ThreadStatus::Ready); 132 SetStatus(ThreadStatus::Ready);
139} 133}
140 134
135ResultCode Thread::Start() {
136 SchedulerLock lock(kernel);
137 SetStatus(ThreadStatus::Ready);
138 return RESULT_SUCCESS;
139}
140
141void Thread::CancelWait() { 141void Thread::CancelWait() {
142 if (GetSchedulingStatus() != ThreadSchedStatus::Paused) { 142 if (GetSchedulingStatus() != ThreadSchedStatus::Paused) {
143 is_sync_cancelled = true; 143 is_sync_cancelled = true;
@@ -188,7 +188,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
188 void* thread_start_parameter) { 188 void* thread_start_parameter) {
189 auto& kernel = system.Kernel(); 189 auto& kernel = system.Kernel();
190 // Check if priority is in ranged. Lowest priority -> highest priority id. 190 // Check if priority is in ranged. Lowest priority -> highest priority id.
191 if (priority > THREADPRIO_LOWEST && (type_flags & THREADTYPE_IDLE == 0)) { 191 if (priority > THREADPRIO_LOWEST && ((type_flags & THREADTYPE_IDLE) == 0)) {
192 LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority); 192 LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
193 return ERR_INVALID_THREAD_PRIORITY; 193 return ERR_INVALID_THREAD_PRIORITY;
194 } 194 }
@@ -416,7 +416,7 @@ void Thread::SetActivity(ThreadActivity value) {
416 } 416 }
417} 417}
418 418
419void Thread::Sleep(s64 nanoseconds) { 419ResultCode Thread::Sleep(s64 nanoseconds) {
420 Handle event_handle{}; 420 Handle event_handle{};
421 { 421 {
422 SchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); 422 SchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
@@ -427,33 +427,31 @@ void Thread::Sleep(s64 nanoseconds) {
427 auto& time_manager = kernel.TimeManager(); 427 auto& time_manager = kernel.TimeManager();
428 time_manager.UnscheduleTimeEvent(event_handle); 428 time_manager.UnscheduleTimeEvent(event_handle);
429 } 429 }
430 return RESULT_SUCCESS;
430} 431}
431 432
432bool Thread::YieldSimple() { 433ResultCode Thread::YieldSimple() {
433 bool result{};
434 { 434 {
435 SchedulerLock lock(kernel); 435 SchedulerLock lock(kernel);
436 result = kernel.GlobalScheduler().YieldThread(this); 436 kernel.GlobalScheduler().YieldThread(this);
437 } 437 }
438 return result; 438 return RESULT_SUCCESS;
439} 439}
440 440
441bool Thread::YieldAndBalanceLoad() { 441ResultCode Thread::YieldAndBalanceLoad() {
442 bool result{};
443 { 442 {
444 SchedulerLock lock(kernel); 443 SchedulerLock lock(kernel);
445 result = kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this); 444 kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this);
446 } 445 }
447 return result; 446 return RESULT_SUCCESS;
448} 447}
449 448
450bool Thread::YieldAndWaitForLoadBalancing() { 449ResultCode Thread::YieldAndWaitForLoadBalancing() {
451 bool result{};
452 { 450 {
453 SchedulerLock lock(kernel); 451 SchedulerLock lock(kernel);
454 result = kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this); 452 kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this);
455 } 453 }
456 return result; 454 return RESULT_SUCCESS;
457} 455}
458 456
459void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { 457void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 33d340b47..78a4357b0 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -236,6 +236,8 @@ public:
236 236
237 void OnWakeUp(); 237 void OnWakeUp();
238 238
239 ResultCode Start();
240
239 /// Cancels a waiting operation that this thread may or may not be within. 241 /// Cancels a waiting operation that this thread may or may not be within.
240 /// 242 ///
241 /// When the thread is within a waiting state, this will set the thread's 243 /// When the thread is within a waiting state, this will set the thread's
@@ -470,16 +472,16 @@ public:
470 void SetActivity(ThreadActivity value); 472 void SetActivity(ThreadActivity value);
471 473
472 /// Sleeps this thread for the given amount of nanoseconds. 474 /// Sleeps this thread for the given amount of nanoseconds.
473 void Sleep(s64 nanoseconds); 475 ResultCode Sleep(s64 nanoseconds);
474 476
475 /// Yields this thread without rebalancing loads. 477 /// Yields this thread without rebalancing loads.
476 bool YieldSimple(); 478 ResultCode YieldSimple();
477 479
478 /// Yields this thread and does a load rebalancing. 480 /// Yields this thread and does a load rebalancing.
479 bool YieldAndBalanceLoad(); 481 ResultCode YieldAndBalanceLoad();
480 482
481 /// Yields this thread and if the core is left idle, loads are rebalanced 483 /// Yields this thread and if the core is left idle, loads are rebalanced
482 bool YieldAndWaitForLoadBalancing(); 484 ResultCode YieldAndWaitForLoadBalancing();
483 485
484 void IncrementYieldCount() { 486 void IncrementYieldCount() {
485 yield_count++; 487 yield_count++;
@@ -603,6 +605,8 @@ private:
603 bool is_running = false; 605 bool is_running = false;
604 bool is_sync_cancelled = false; 606 bool is_sync_cancelled = false;
605 607
608 bool will_be_terminated{};
609
606 std::string name; 610 std::string name;
607}; 611};
608 612