summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-03-08 12:51:24 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:40 -0400
commit6515c6e8c699584528486341579cf3a8dde3eea4 (patch)
tree1663248cbd02cc0db108ed18feef5a994e44d63d /src/core/hle/kernel
parentScheduler: Correct yields. (diff)
downloadyuzu-6515c6e8c699584528486341579cf3a8dde3eea4.tar.gz
yuzu-6515c6e8c699584528486341579cf3a8dde3eea4.tar.xz
yuzu-6515c6e8c699584528486341579cf3a8dde3eea4.zip
Kernel: Fixes, corrections and asserts to scheduler and different svcs.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp27
-rw-r--r--src/core/hle/kernel/kernel.cpp1
-rw-r--r--src/core/hle/kernel/scheduler.cpp3
-rw-r--r--src/core/hle/kernel/scheduler.h5
-rw-r--r--src/core/hle/kernel/svc.cpp27
-rw-r--r--src/core/hle/kernel/synchronization.cpp10
-rw-r--r--src/core/hle/kernel/time_manager.cpp2
-rw-r--r--src/core/hle/kernel/time_manager.h1
8 files changed, 38 insertions, 38 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 07acabc1d..e8f22b598 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -34,19 +34,9 @@ void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& wai
34 34
35 // Signal the waiting threads. 35 // Signal the waiting threads.
36 for (std::size_t i = 0; i < last; i++) { 36 for (std::size_t i = 0; i < last; i++) {
37 if (waiting_threads[i]->GetStatus() != ThreadStatus::WaitArb) {
38 last++;
39 last = std::min(waiting_threads.size(), last);
40 continue;
41 }
42
43 time_manager.CancelTimeEvent(waiting_threads[i].get());
44
45 ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb);
46 waiting_threads[i]->SetSynchronizationResults(nullptr, RESULT_SUCCESS); 37 waiting_threads[i]->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
47 RemoveThread(waiting_threads[i]); 38 RemoveThread(waiting_threads[i]);
48 waiting_threads[i]->WaitForArbitration(false); 39 waiting_threads[i]->WaitForArbitration(false);
49 waiting_threads[i]->SetArbiterWaitAddress(0);
50 waiting_threads[i]->ResumeFromWait(); 40 waiting_threads[i]->ResumeFromWait();
51 } 41 }
52} 42}
@@ -172,20 +162,25 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
172 { 162 {
173 SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout); 163 SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
174 164
165 if (current_thread->IsPendingTermination()) {
166 lock.CancelSleep();
167 return ERR_THREAD_TERMINATING;
168 }
169
175 // Ensure that we can read the address. 170 // Ensure that we can read the address.
176 if (!memory.IsValidVirtualAddress(address)) { 171 if (!memory.IsValidVirtualAddress(address)) {
177 lock.CancelSleep(); 172 lock.CancelSleep();
178 return ERR_INVALID_ADDRESS_STATE; 173 return ERR_INVALID_ADDRESS_STATE;
179 } 174 }
180 175
181 /// TODO(Blinkhawk): Check termination pending.
182
183 s32 current_value = static_cast<s32>(memory.Read32(address)); 176 s32 current_value = static_cast<s32>(memory.Read32(address));
184 if (current_value >= value) { 177 if (current_value >= value) {
185 lock.CancelSleep(); 178 lock.CancelSleep();
186 return ERR_INVALID_STATE; 179 return ERR_INVALID_STATE;
187 } 180 }
188 181
182 current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
183
189 s32 decrement_value; 184 s32 decrement_value;
190 185
191 const std::size_t current_core = system.CurrentCoreIndex(); 186 const std::size_t current_core = system.CurrentCoreIndex();
@@ -207,7 +202,6 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
207 return RESULT_TIMEOUT; 202 return RESULT_TIMEOUT;
208 } 203 }
209 204
210 current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
211 current_thread->SetArbiterWaitAddress(address); 205 current_thread->SetArbiterWaitAddress(address);
212 InsertThread(SharedFrom(current_thread)); 206 InsertThread(SharedFrom(current_thread));
213 current_thread->SetStatus(ThreadStatus::WaitArb); 207 current_thread->SetStatus(ThreadStatus::WaitArb);
@@ -239,14 +233,17 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
239 { 233 {
240 SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout); 234 SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
241 235
236 if (current_thread->IsPendingTermination()) {
237 lock.CancelSleep();
238 return ERR_THREAD_TERMINATING;
239 }
240
242 // Ensure that we can read the address. 241 // Ensure that we can read the address.
243 if (!memory.IsValidVirtualAddress(address)) { 242 if (!memory.IsValidVirtualAddress(address)) {
244 lock.CancelSleep(); 243 lock.CancelSleep();
245 return ERR_INVALID_ADDRESS_STATE; 244 return ERR_INVALID_ADDRESS_STATE;
246 } 245 }
247 246
248 /// TODO(Blinkhawk): Check termination pending.
249
250 s32 current_value = static_cast<s32>(memory.Read32(address)); 247 s32 current_value = static_cast<s32>(memory.Read32(address));
251 if (current_value != value) { 248 if (current_value != value) {
252 lock.CancelSleep(); 249 lock.CancelSleep();
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index ba051a7d8..721ab1e70 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -49,6 +49,7 @@ namespace Kernel {
49 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time 49 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
50 */ 50 */
51static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) { 51static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) {
52 UNREACHABLE();
52 const auto proper_handle = static_cast<Handle>(thread_handle); 53 const auto proper_handle = static_cast<Handle>(thread_handle);
53 const auto& system = Core::System::GetInstance(); 54 const auto& system = Core::System::GetInstance();
54 55
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index ab17204bb..5322f0aae 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -133,6 +133,7 @@ u32 GlobalScheduler::SelectThreads() {
133 u32 cores_needing_context_switch{}; 133 u32 cores_needing_context_switch{};
134 for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 134 for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
135 Scheduler& sched = kernel.Scheduler(core); 135 Scheduler& sched = kernel.Scheduler(core);
136 ASSERT(top_threads[core] == nullptr || top_threads[core]->GetProcessorID() == core);
136 if (update_thread(top_threads[core], sched)) { 137 if (update_thread(top_threads[core], sched)) {
137 cores_needing_context_switch |= (1ul << core); 138 cores_needing_context_switch |= (1ul << core);
138 } 139 }
@@ -244,7 +245,7 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread
244 winner = yielding_thread; 245 winner = yielding_thread;
245 } 246 }
246 } else { 247 } else {
247 winner = scheduled_queue[i].front(); 248 winner = scheduled_queue[core_id].front();
248 } 249 }
249 250
250 if (kernel.GetCurrentHostThreadID() != core_id) { 251 if (kernel.GetCurrentHostThreadID() != core_id) {
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index 728cca802..5e062bf59 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -16,7 +16,7 @@
16#include "core/hle/kernel/thread.h" 16#include "core/hle/kernel/thread.h"
17 17
18namespace Common { 18namespace Common {
19 class Fiber; 19class Fiber;
20} 20}
21 21
22namespace Core { 22namespace Core {
@@ -133,7 +133,8 @@ private:
133 /// and reschedules current core if needed. 133 /// and reschedules current core if needed.
134 void Unlock(); 134 void Unlock();
135 135
136 void EnableInterruptAndSchedule(u32 cores_pending_reschedule, Core::EmuThreadHandle global_thread); 136 void EnableInterruptAndSchedule(u32 cores_pending_reschedule,
137 Core::EmuThreadHandle global_thread);
137 138
138 /** 139 /**
139 * Add a thread to the suggested queue of a cpu core. Suggested threads may be 140 * Add a thread to the suggested queue of a cpu core. Suggested threads may be
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 371beed0d..aad2ac549 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1562,6 +1562,11 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
1562 1562
1563 current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); 1563 current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
1564 1564
1565 if (thread->IsPendingTermination()) {
1566 lock.CancelSleep();
1567 return ERR_THREAD_TERMINATING;
1568 }
1569
1565 const auto release_result = current_process->GetMutex().Release(mutex_addr); 1570 const auto release_result = current_process->GetMutex().Release(mutex_addr);
1566 if (release_result.IsError()) { 1571 if (release_result.IsError()) {
1567 lock.CancelSleep(); 1572 lock.CancelSleep();
@@ -1588,6 +1593,11 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
1588 { 1593 {
1589 SchedulerLock lock(kernel); 1594 SchedulerLock lock(kernel);
1590 1595
1596 auto* owner = current_thread->GetLockOwner();
1597 if (owner != nullptr) {
1598 owner->RemoveMutexWaiter(SharedFrom(current_thread));
1599 }
1600
1591 current_process->RemoveConditionVariableThread(SharedFrom(current_thread)); 1601 current_process->RemoveConditionVariableThread(SharedFrom(current_thread));
1592 } 1602 }
1593 // Note: Deliberately don't attempt to inherit the lock owner's priority. 1603 // Note: Deliberately don't attempt to inherit the lock owner's priority.
@@ -1618,19 +1628,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1618 for (std::size_t index = 0; index < last; ++index) { 1628 for (std::size_t index = 0; index < last; ++index) {
1619 auto& thread = waiting_threads[index]; 1629 auto& thread = waiting_threads[index];
1620 1630
1621 if (thread->GetStatus() != ThreadStatus::WaitCondVar) {
1622 last++;
1623 last = std::min(waiting_threads.size(), last);
1624 continue;
1625 }
1626
1627 time_manager.CancelTimeEvent(thread.get());
1628
1629 ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); 1631 ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr);
1630 1632
1631 // liberate Cond Var Thread. 1633 // liberate Cond Var Thread.
1632 current_process->RemoveConditionVariableThread(thread); 1634 current_process->RemoveConditionVariableThread(thread);
1633 thread->SetCondVarWaitAddress(0);
1634 1635
1635 const std::size_t current_core = system.CurrentCoreIndex(); 1636 const std::size_t current_core = system.CurrentCoreIndex();
1636 auto& monitor = system.Monitor(); 1637 auto& monitor = system.Monitor();
@@ -1655,9 +1656,6 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1655 monitor.ClearExclusive(); 1656 monitor.ClearExclusive();
1656 if (mutex_val == 0) { 1657 if (mutex_val == 0) {
1657 // We were able to acquire the mutex, resume this thread. 1658 // We were able to acquire the mutex, resume this thread.
1658 ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar);
1659 thread->ResumeFromWait();
1660
1661 auto* const lock_owner = thread->GetLockOwner(); 1659 auto* const lock_owner = thread->GetLockOwner();
1662 if (lock_owner != nullptr) { 1660 if (lock_owner != nullptr) {
1663 lock_owner->RemoveMutexWaiter(thread); 1661 lock_owner->RemoveMutexWaiter(thread);
@@ -1665,13 +1663,16 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1665 1663
1666 thread->SetLockOwner(nullptr); 1664 thread->SetLockOwner(nullptr);
1667 thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); 1665 thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
1666 thread->ResumeFromWait();
1668 } else { 1667 } else {
1669 // The mutex is already owned by some other thread, make this thread wait on it. 1668 // The mutex is already owned by some other thread, make this thread wait on it.
1670 const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); 1669 const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
1671 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1670 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1672 auto owner = handle_table.Get<Thread>(owner_handle); 1671 auto owner = handle_table.Get<Thread>(owner_handle);
1673 ASSERT(owner); 1672 ASSERT(owner);
1674 thread->SetStatus(ThreadStatus::WaitMutex); 1673 if (thread->GetStatus() == ThreadStatus::WaitCondVar) {
1674 thread->SetStatus(ThreadStatus::WaitMutex);
1675 }
1675 1676
1676 owner->AddMutexWaiter(thread); 1677 owner->AddMutexWaiter(thread);
1677 } 1678 }
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp
index 4323fc120..275bf11cc 100644
--- a/src/core/hle/kernel/synchronization.cpp
+++ b/src/core/hle/kernel/synchronization.cpp
@@ -23,9 +23,10 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const {
23 if (obj.IsSignaled()) { 23 if (obj.IsSignaled()) {
24 for (auto thread : obj.GetWaitingThreads()) { 24 for (auto thread : obj.GetWaitingThreads()) {
25 if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { 25 if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) {
26 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
27 ASSERT(thread->IsWaitingSync());
26 thread->SetSynchronizationResults(&obj, RESULT_SUCCESS); 28 thread->SetSynchronizationResults(&obj, RESULT_SUCCESS);
27 thread->ResumeFromWait(); 29 thread->ResumeFromWait();
28 time_manager.CancelTimeEvent(thread.get());
29 } 30 }
30 } 31 }
31 obj.ClearWaitingThreads(); 32 obj.ClearWaitingThreads();
@@ -91,10 +92,11 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
91 ResultCode signaling_result = thread->GetSignalingResult(); 92 ResultCode signaling_result = thread->GetSignalingResult();
92 SynchronizationObject* signaling_object = thread->GetSignalingObject(); 93 SynchronizationObject* signaling_object = thread->GetSignalingObject();
93 thread->SetSynchronizationObjects(nullptr); 94 thread->SetSynchronizationObjects(nullptr);
95 auto shared_thread = SharedFrom(thread);
94 for (auto& obj : sync_objects) { 96 for (auto& obj : sync_objects) {
95 obj->RemoveWaitingThread(SharedFrom(thread)); 97 obj->RemoveWaitingThread(shared_thread);
96 } 98 }
97 if (signaling_result == RESULT_SUCCESS) { 99 if (signaling_object != nullptr) {
98 const auto itr = std::find_if( 100 const auto itr = std::find_if(
99 sync_objects.begin(), sync_objects.end(), 101 sync_objects.begin(), sync_objects.end(),
100 [signaling_object](const std::shared_ptr<SynchronizationObject>& object) { 102 [signaling_object](const std::shared_ptr<SynchronizationObject>& object) {
@@ -103,7 +105,7 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
103 ASSERT(itr != sync_objects.end()); 105 ASSERT(itr != sync_objects.end());
104 signaling_object->Acquire(thread); 106 signaling_object->Acquire(thread);
105 const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); 107 const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr));
106 return {RESULT_SUCCESS, index}; 108 return {signaling_result, index};
107 } 109 }
108 return {signaling_result, -1}; 110 return {signaling_result, -1};
109 } 111 }
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index dab5fc4c6..cc228f5f7 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -22,7 +22,6 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} {
22 if (cancelled_events[proper_handle]) { 22 if (cancelled_events[proper_handle]) {
23 return; 23 return;
24 } 24 }
25 event_fired[proper_handle] = true;
26 std::shared_ptr<Thread> thread = 25 std::shared_ptr<Thread> thread =
27 this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); 26 this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
28 thread->OnWakeUp(); 27 thread->OnWakeUp();
@@ -39,7 +38,6 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64
39 event_handle = InvalidHandle; 38 event_handle = InvalidHandle;
40 } 39 }
41 cancelled_events[event_handle] = false; 40 cancelled_events[event_handle] = false;
42 event_fired[event_handle] = false;
43} 41}
44 42
45void TimeManager::UnscheduleTimeEvent(Handle event_handle) { 43void TimeManager::UnscheduleTimeEvent(Handle event_handle) {
diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h
index 3080ac838..307a18765 100644
--- a/src/core/hle/kernel/time_manager.h
+++ b/src/core/hle/kernel/time_manager.h
@@ -42,7 +42,6 @@ private:
42 Core::System& system; 42 Core::System& system;
43 std::shared_ptr<Core::Timing::EventType> time_manager_event_type; 43 std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
44 std::unordered_map<Handle, bool> cancelled_events; 44 std::unordered_map<Handle, bool> cancelled_events;
45 std::unordered_map<Handle, bool> event_fired;
46}; 45};
47 46
48} // namespace Kernel 47} // namespace Kernel