diff options
36 files changed, 326 insertions, 231 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index b369f199f..4462ff3fb 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -39,8 +39,10 @@ public: | |||
| 39 | Impl(Impl const&) = delete; | 39 | Impl(Impl const&) = delete; |
| 40 | const Impl& operator=(Impl const&) = delete; | 40 | const Impl& operator=(Impl const&) = delete; |
| 41 | 41 | ||
| 42 | void PushEntry(Entry e) { | 42 | void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, |
| 43 | message_queue.Push(std::move(e)); | 43 | const char* function, std::string message) { |
| 44 | message_queue.Push( | ||
| 45 | CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); | ||
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | void AddBackend(std::unique_ptr<Backend> backend) { | 48 | void AddBackend(std::unique_ptr<Backend> backend) { |
| @@ -108,11 +110,30 @@ private: | |||
| 108 | backend_thread.join(); | 110 | backend_thread.join(); |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 113 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | ||
| 114 | const char* function, std::string message) const { | ||
| 115 | using std::chrono::duration_cast; | ||
| 116 | using std::chrono::steady_clock; | ||
| 117 | |||
| 118 | Entry entry; | ||
| 119 | entry.timestamp = | ||
| 120 | duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||
| 121 | entry.log_class = log_class; | ||
| 122 | entry.log_level = log_level; | ||
| 123 | entry.filename = Common::TrimSourcePath(filename); | ||
| 124 | entry.line_num = line_nr; | ||
| 125 | entry.function = function; | ||
| 126 | entry.message = std::move(message); | ||
| 127 | |||
| 128 | return entry; | ||
| 129 | } | ||
| 130 | |||
| 111 | std::mutex writing_mutex; | 131 | std::mutex writing_mutex; |
| 112 | std::thread backend_thread; | 132 | std::thread backend_thread; |
| 113 | std::vector<std::unique_ptr<Backend>> backends; | 133 | std::vector<std::unique_ptr<Backend>> backends; |
| 114 | Common::MPSCQueue<Log::Entry> message_queue; | 134 | Common::MPSCQueue<Log::Entry> message_queue; |
| 115 | Filter filter; | 135 | Filter filter; |
| 136 | std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; | ||
| 116 | }; | 137 | }; |
| 117 | 138 | ||
| 118 | void ConsoleBackend::Write(const Entry& entry) { | 139 | void ConsoleBackend::Write(const Entry& entry) { |
| @@ -271,25 +292,6 @@ const char* GetLevelName(Level log_level) { | |||
| 271 | #undef LVL | 292 | #undef LVL |
| 272 | } | 293 | } |
| 273 | 294 | ||
| 274 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | ||
| 275 | const char* function, std::string message) { | ||
| 276 | using std::chrono::duration_cast; | ||
| 277 | using std::chrono::steady_clock; | ||
| 278 | |||
| 279 | static steady_clock::time_point time_origin = steady_clock::now(); | ||
| 280 | |||
| 281 | Entry entry; | ||
| 282 | entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||
| 283 | entry.log_class = log_class; | ||
| 284 | entry.log_level = log_level; | ||
| 285 | entry.filename = Common::TrimSourcePath(filename); | ||
| 286 | entry.line_num = line_nr; | ||
| 287 | entry.function = function; | ||
| 288 | entry.message = std::move(message); | ||
| 289 | |||
| 290 | return entry; | ||
| 291 | } | ||
| 292 | |||
| 293 | void SetGlobalFilter(const Filter& filter) { | 295 | void SetGlobalFilter(const Filter& filter) { |
| 294 | Impl::Instance().SetGlobalFilter(filter); | 296 | Impl::Instance().SetGlobalFilter(filter); |
| 295 | } | 297 | } |
| @@ -314,9 +316,7 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | |||
| 314 | if (!filter.CheckMessage(log_class, log_level)) | 316 | if (!filter.CheckMessage(log_class, log_level)) |
| 315 | return; | 317 | return; |
| 316 | 318 | ||
| 317 | Entry entry = | 319 | instance.PushEntry(log_class, log_level, filename, line_num, function, |
| 318 | CreateEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); | 320 | fmt::vformat(format, args)); |
| 319 | |||
| 320 | instance.PushEntry(std::move(entry)); | ||
| 321 | } | 321 | } |
| 322 | } // namespace Log | 322 | } // namespace Log |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index a31ee6968..fca0267a1 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -135,10 +135,6 @@ const char* GetLogClassName(Class log_class); | |||
| 135 | */ | 135 | */ |
| 136 | const char* GetLevelName(Level log_level); | 136 | const char* GetLevelName(Level log_level); |
| 137 | 137 | ||
| 138 | /// Creates a log entry by formatting the given source location, and message. | ||
| 139 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | ||
| 140 | const char* function, std::string message); | ||
| 141 | |||
| 142 | /** | 138 | /** |
| 143 | * The global filter will prevent any messages from even being processed if they are filtered. Each | 139 | * The global filter will prevent any messages from even being processed if they are filtered. Each |
| 144 | * backend can have a filter, but if the level is lower than the global filter, the backend will | 140 | * backend can have a filter, but if the level is lower than the global filter, the backend will |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 988356c65..8ccb2d5f0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -217,6 +217,7 @@ add_library(core STATIC | |||
| 217 | hle/service/audio/audren_u.h | 217 | hle/service/audio/audren_u.h |
| 218 | hle/service/audio/codecctl.cpp | 218 | hle/service/audio/codecctl.cpp |
| 219 | hle/service/audio/codecctl.h | 219 | hle/service/audio/codecctl.h |
| 220 | hle/service/audio/errors.h | ||
| 220 | hle/service/audio/hwopus.cpp | 221 | hle/service/audio/hwopus.cpp |
| 221 | hle/service/audio/hwopus.h | 222 | hle/service/audio/hwopus.h |
| 222 | hle/service/bcat/bcat.cpp | 223 | hle/service/bcat/bcat.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 3f4e9c3a8..d741ef90d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -78,6 +78,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 78 | return vfs->OpenFile(path, FileSys::Mode::Read); | 78 | return vfs->OpenFile(path, FileSys::Mode::Read); |
| 79 | } | 79 | } |
| 80 | struct System::Impl { | 80 | struct System::Impl { |
| 81 | explicit Impl(System& system) : kernel{system} {} | ||
| 81 | 82 | ||
| 82 | Cpu& CurrentCpuCore() { | 83 | Cpu& CurrentCpuCore() { |
| 83 | return cpu_core_manager.GetCurrentCore(); | 84 | return cpu_core_manager.GetCurrentCore(); |
| @@ -95,7 +96,7 @@ struct System::Impl { | |||
| 95 | LOG_DEBUG(HW_Memory, "initialized OK"); | 96 | LOG_DEBUG(HW_Memory, "initialized OK"); |
| 96 | 97 | ||
| 97 | core_timing.Initialize(); | 98 | core_timing.Initialize(); |
| 98 | kernel.Initialize(core_timing); | 99 | kernel.Initialize(); |
| 99 | 100 | ||
| 100 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( | 101 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( |
| 101 | std::chrono::system_clock::now().time_since_epoch()); | 102 | std::chrono::system_clock::now().time_since_epoch()); |
| @@ -265,7 +266,7 @@ struct System::Impl { | |||
| 265 | Core::FrameLimiter frame_limiter; | 266 | Core::FrameLimiter frame_limiter; |
| 266 | }; | 267 | }; |
| 267 | 268 | ||
| 268 | System::System() : impl{std::make_unique<Impl>()} {} | 269 | System::System() : impl{std::make_unique<Impl>(*this)} {} |
| 269 | System::~System() = default; | 270 | System::~System() = default; |
| 270 | 271 | ||
| 271 | Cpu& System::CurrentCpuCore() { | 272 | Cpu& System::CurrentCpuCore() { |
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index a250d088d..9780a7849 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/core_cpu.h" | 11 | #include "core/core_cpu.h" |
| 12 | #include "core/hle/kernel/address_arbiter.h" | ||
| 12 | #include "core/hle/kernel/errors.h" | 13 | #include "core/hle/kernel/errors.h" |
| 13 | #include "core/hle/kernel/object.h" | 14 | #include "core/hle/kernel/object.h" |
| 14 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/process.h" |
| @@ -17,58 +18,16 @@ | |||
| 17 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| 18 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| 19 | 20 | ||
| 20 | namespace Kernel::AddressArbiter { | 21 | namespace Kernel { |
| 21 | 22 | namespace { | |
| 22 | // Performs actual address waiting logic. | ||
| 23 | static ResultCode WaitForAddress(VAddr address, s64 timeout) { | ||
| 24 | SharedPtr<Thread> current_thread = GetCurrentThread(); | ||
| 25 | current_thread->SetArbiterWaitAddress(address); | ||
| 26 | current_thread->SetStatus(ThreadStatus::WaitArb); | ||
| 27 | current_thread->InvalidateWakeupCallback(); | ||
| 28 | |||
| 29 | current_thread->WakeAfterDelay(timeout); | ||
| 30 | |||
| 31 | Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); | ||
| 32 | return RESULT_TIMEOUT; | ||
| 33 | } | ||
| 34 | |||
| 35 | // Gets the threads waiting on an address. | ||
| 36 | static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) { | ||
| 37 | const auto RetrieveWaitingThreads = [](std::size_t core_index, | ||
| 38 | std::vector<SharedPtr<Thread>>& waiting_threads, | ||
| 39 | VAddr arb_addr) { | ||
| 40 | const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); | ||
| 41 | const auto& thread_list = scheduler.GetThreadList(); | ||
| 42 | |||
| 43 | for (const auto& thread : thread_list) { | ||
| 44 | if (thread->GetArbiterWaitAddress() == arb_addr) | ||
| 45 | waiting_threads.push_back(thread); | ||
| 46 | } | ||
| 47 | }; | ||
| 48 | |||
| 49 | // Retrieve all threads that are waiting for this address. | ||
| 50 | std::vector<SharedPtr<Thread>> threads; | ||
| 51 | RetrieveWaitingThreads(0, threads, address); | ||
| 52 | RetrieveWaitingThreads(1, threads, address); | ||
| 53 | RetrieveWaitingThreads(2, threads, address); | ||
| 54 | RetrieveWaitingThreads(3, threads, address); | ||
| 55 | |||
| 56 | // Sort them by priority, such that the highest priority ones come first. | ||
| 57 | std::sort(threads.begin(), threads.end(), | ||
| 58 | [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) { | ||
| 59 | return lhs->GetPriority() < rhs->GetPriority(); | ||
| 60 | }); | ||
| 61 | |||
| 62 | return threads; | ||
| 63 | } | ||
| 64 | |||
| 65 | // Wake up num_to_wake (or all) threads in a vector. | 23 | // Wake up num_to_wake (or all) threads in a vector. |
| 66 | static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) { | 24 | void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) { |
| 67 | // Only process up to 'target' threads, unless 'target' is <= 0, in which case process | 25 | // Only process up to 'target' threads, unless 'target' is <= 0, in which case process |
| 68 | // them all. | 26 | // them all. |
| 69 | std::size_t last = waiting_threads.size(); | 27 | std::size_t last = waiting_threads.size(); |
| 70 | if (num_to_wake > 0) | 28 | if (num_to_wake > 0) { |
| 71 | last = num_to_wake; | 29 | last = num_to_wake; |
| 30 | } | ||
| 72 | 31 | ||
| 73 | // Signal the waiting threads. | 32 | // Signal the waiting threads. |
| 74 | for (std::size_t i = 0; i < last; i++) { | 33 | for (std::size_t i = 0; i < last; i++) { |
| @@ -78,42 +37,41 @@ static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num | |||
| 78 | waiting_threads[i]->ResumeFromWait(); | 37 | waiting_threads[i]->ResumeFromWait(); |
| 79 | } | 38 | } |
| 80 | } | 39 | } |
| 40 | } // Anonymous namespace | ||
| 81 | 41 | ||
| 82 | // Signals an address being waited on. | 42 | AddressArbiter::AddressArbiter(Core::System& system) : system{system} {} |
| 83 | ResultCode SignalToAddress(VAddr address, s32 num_to_wake) { | 43 | AddressArbiter::~AddressArbiter() = default; |
| 84 | std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address); | ||
| 85 | 44 | ||
| 45 | ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) { | ||
| 46 | const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address); | ||
| 86 | WakeThreads(waiting_threads, num_to_wake); | 47 | WakeThreads(waiting_threads, num_to_wake); |
| 87 | return RESULT_SUCCESS; | 48 | return RESULT_SUCCESS; |
| 88 | } | 49 | } |
| 89 | 50 | ||
| 90 | // Signals an address being waited on and increments its value if equal to the value argument. | 51 | ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, |
| 91 | ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { | 52 | s32 num_to_wake) { |
| 92 | // Ensure that we can write to the address. | 53 | // Ensure that we can write to the address. |
| 93 | if (!Memory::IsValidVirtualAddress(address)) { | 54 | if (!Memory::IsValidVirtualAddress(address)) { |
| 94 | return ERR_INVALID_ADDRESS_STATE; | 55 | return ERR_INVALID_ADDRESS_STATE; |
| 95 | } | 56 | } |
| 96 | 57 | ||
| 97 | if (static_cast<s32>(Memory::Read32(address)) == value) { | 58 | if (static_cast<s32>(Memory::Read32(address)) != value) { |
| 98 | Memory::Write32(address, static_cast<u32>(value + 1)); | ||
| 99 | } else { | ||
| 100 | return ERR_INVALID_STATE; | 59 | return ERR_INVALID_STATE; |
| 101 | } | 60 | } |
| 102 | 61 | ||
| 62 | Memory::Write32(address, static_cast<u32>(value + 1)); | ||
| 103 | return SignalToAddress(address, num_to_wake); | 63 | return SignalToAddress(address, num_to_wake); |
| 104 | } | 64 | } |
| 105 | 65 | ||
| 106 | // Signals an address being waited on and modifies its value based on waiting thread count if equal | 66 | ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, |
| 107 | // to the value argument. | 67 | s32 num_to_wake) { |
| 108 | ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, | ||
| 109 | s32 num_to_wake) { | ||
| 110 | // Ensure that we can write to the address. | 68 | // Ensure that we can write to the address. |
| 111 | if (!Memory::IsValidVirtualAddress(address)) { | 69 | if (!Memory::IsValidVirtualAddress(address)) { |
| 112 | return ERR_INVALID_ADDRESS_STATE; | 70 | return ERR_INVALID_ADDRESS_STATE; |
| 113 | } | 71 | } |
| 114 | 72 | ||
| 115 | // Get threads waiting on the address. | 73 | // Get threads waiting on the address. |
| 116 | std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address); | 74 | const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address); |
| 117 | 75 | ||
| 118 | // Determine the modified value depending on the waiting count. | 76 | // Determine the modified value depending on the waiting count. |
| 119 | s32 updated_value; | 77 | s32 updated_value; |
| @@ -125,31 +83,31 @@ ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 valu | |||
| 125 | updated_value = value; | 83 | updated_value = value; |
| 126 | } | 84 | } |
| 127 | 85 | ||
| 128 | if (static_cast<s32>(Memory::Read32(address)) == value) { | 86 | if (static_cast<s32>(Memory::Read32(address)) != value) { |
| 129 | Memory::Write32(address, static_cast<u32>(updated_value)); | ||
| 130 | } else { | ||
| 131 | return ERR_INVALID_STATE; | 87 | return ERR_INVALID_STATE; |
| 132 | } | 88 | } |
| 133 | 89 | ||
| 90 | Memory::Write32(address, static_cast<u32>(updated_value)); | ||
| 134 | WakeThreads(waiting_threads, num_to_wake); | 91 | WakeThreads(waiting_threads, num_to_wake); |
| 135 | return RESULT_SUCCESS; | 92 | return RESULT_SUCCESS; |
| 136 | } | 93 | } |
| 137 | 94 | ||
| 138 | // Waits on an address if the value passed is less than the argument value, optionally decrementing. | 95 | ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, |
| 139 | ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) { | 96 | bool should_decrement) { |
| 140 | // Ensure that we can read the address. | 97 | // Ensure that we can read the address. |
| 141 | if (!Memory::IsValidVirtualAddress(address)) { | 98 | if (!Memory::IsValidVirtualAddress(address)) { |
| 142 | return ERR_INVALID_ADDRESS_STATE; | 99 | return ERR_INVALID_ADDRESS_STATE; |
| 143 | } | 100 | } |
| 144 | 101 | ||
| 145 | s32 cur_value = static_cast<s32>(Memory::Read32(address)); | 102 | const s32 cur_value = static_cast<s32>(Memory::Read32(address)); |
| 146 | if (cur_value < value) { | 103 | if (cur_value >= value) { |
| 147 | if (should_decrement) { | ||
| 148 | Memory::Write32(address, static_cast<u32>(cur_value - 1)); | ||
| 149 | } | ||
| 150 | } else { | ||
| 151 | return ERR_INVALID_STATE; | 104 | return ERR_INVALID_STATE; |
| 152 | } | 105 | } |
| 106 | |||
| 107 | if (should_decrement) { | ||
| 108 | Memory::Write32(address, static_cast<u32>(cur_value - 1)); | ||
| 109 | } | ||
| 110 | |||
| 153 | // Short-circuit without rescheduling, if timeout is zero. | 111 | // Short-circuit without rescheduling, if timeout is zero. |
| 154 | if (timeout == 0) { | 112 | if (timeout == 0) { |
| 155 | return RESULT_TIMEOUT; | 113 | return RESULT_TIMEOUT; |
| @@ -158,8 +116,7 @@ ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool | |||
| 158 | return WaitForAddress(address, timeout); | 116 | return WaitForAddress(address, timeout); |
| 159 | } | 117 | } |
| 160 | 118 | ||
| 161 | // Waits on an address if the value passed is equal to the argument value. | 119 | ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { |
| 162 | ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { | ||
| 163 | // Ensure that we can read the address. | 120 | // Ensure that we can read the address. |
| 164 | if (!Memory::IsValidVirtualAddress(address)) { | 121 | if (!Memory::IsValidVirtualAddress(address)) { |
| 165 | return ERR_INVALID_ADDRESS_STATE; | 122 | return ERR_INVALID_ADDRESS_STATE; |
| @@ -175,4 +132,46 @@ ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { | |||
| 175 | 132 | ||
| 176 | return WaitForAddress(address, timeout); | 133 | return WaitForAddress(address, timeout); |
| 177 | } | 134 | } |
| 178 | } // namespace Kernel::AddressArbiter | 135 | |
| 136 | ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) { | ||
| 137 | SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread(); | ||
| 138 | current_thread->SetArbiterWaitAddress(address); | ||
| 139 | current_thread->SetStatus(ThreadStatus::WaitArb); | ||
| 140 | current_thread->InvalidateWakeupCallback(); | ||
| 141 | |||
| 142 | current_thread->WakeAfterDelay(timeout); | ||
| 143 | |||
| 144 | system.CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); | ||
| 145 | return RESULT_TIMEOUT; | ||
| 146 | } | ||
| 147 | |||
| 148 | std::vector<SharedPtr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const { | ||
| 149 | const auto RetrieveWaitingThreads = [this](std::size_t core_index, | ||
| 150 | std::vector<SharedPtr<Thread>>& waiting_threads, | ||
| 151 | VAddr arb_addr) { | ||
| 152 | const auto& scheduler = system.Scheduler(core_index); | ||
| 153 | const auto& thread_list = scheduler.GetThreadList(); | ||
| 154 | |||
| 155 | for (const auto& thread : thread_list) { | ||
| 156 | if (thread->GetArbiterWaitAddress() == arb_addr) { | ||
| 157 | waiting_threads.push_back(thread); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | |||
| 162 | // Retrieve all threads that are waiting for this address. | ||
| 163 | std::vector<SharedPtr<Thread>> threads; | ||
| 164 | RetrieveWaitingThreads(0, threads, address); | ||
| 165 | RetrieveWaitingThreads(1, threads, address); | ||
| 166 | RetrieveWaitingThreads(2, threads, address); | ||
| 167 | RetrieveWaitingThreads(3, threads, address); | ||
| 168 | |||
| 169 | // Sort them by priority, such that the highest priority ones come first. | ||
| 170 | std::sort(threads.begin(), threads.end(), | ||
| 171 | [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) { | ||
| 172 | return lhs->GetPriority() < rhs->GetPriority(); | ||
| 173 | }); | ||
| 174 | |||
| 175 | return threads; | ||
| 176 | } | ||
| 177 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index b58f21bec..e0c36f2e3 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -5,28 +5,68 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "core/hle/kernel/address_arbiter.h" | ||
| 8 | 9 | ||
| 9 | union ResultCode; | 10 | union ResultCode; |
| 10 | 11 | ||
| 11 | namespace Kernel::AddressArbiter { | 12 | namespace Core { |
| 13 | class System; | ||
| 14 | } | ||
| 12 | 15 | ||
| 13 | enum class ArbitrationType { | 16 | namespace Kernel { |
| 14 | WaitIfLessThan = 0, | ||
| 15 | DecrementAndWaitIfLessThan = 1, | ||
| 16 | WaitIfEqual = 2, | ||
| 17 | }; | ||
| 18 | 17 | ||
| 19 | enum class SignalType { | 18 | class Thread; |
| 20 | Signal = 0, | 19 | |
| 21 | IncrementAndSignalIfEqual = 1, | 20 | class AddressArbiter { |
| 22 | ModifyByWaitingCountAndSignalIfEqual = 2, | 21 | public: |
| 23 | }; | 22 | enum class ArbitrationType { |
| 23 | WaitIfLessThan = 0, | ||
| 24 | DecrementAndWaitIfLessThan = 1, | ||
| 25 | WaitIfEqual = 2, | ||
| 26 | }; | ||
| 27 | |||
| 28 | enum class SignalType { | ||
| 29 | Signal = 0, | ||
| 30 | IncrementAndSignalIfEqual = 1, | ||
| 31 | ModifyByWaitingCountAndSignalIfEqual = 2, | ||
| 32 | }; | ||
| 33 | |||
| 34 | explicit AddressArbiter(Core::System& system); | ||
| 35 | ~AddressArbiter(); | ||
| 36 | |||
| 37 | AddressArbiter(const AddressArbiter&) = delete; | ||
| 38 | AddressArbiter& operator=(const AddressArbiter&) = delete; | ||
| 39 | |||
| 40 | AddressArbiter(AddressArbiter&&) = default; | ||
| 41 | AddressArbiter& operator=(AddressArbiter&&) = delete; | ||
| 24 | 42 | ||
| 25 | ResultCode SignalToAddress(VAddr address, s32 num_to_wake); | 43 | /// Signals an address being waited on. |
| 26 | ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); | 44 | ResultCode SignalToAddress(VAddr address, s32 num_to_wake); |
| 27 | ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); | ||
| 28 | 45 | ||
| 29 | ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement); | 46 | /// Signals an address being waited on and increments its value if equal to the value argument. |
| 30 | ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout); | 47 | ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); |
| 48 | |||
| 49 | /// Signals an address being waited on and modifies its value based on waiting thread count if | ||
| 50 | /// equal to the value argument. | ||
| 51 | ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, | ||
| 52 | s32 num_to_wake); | ||
| 53 | |||
| 54 | /// Waits on an address if the value passed is less than the argument value, | ||
| 55 | /// optionally decrementing. | ||
| 56 | ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, | ||
| 57 | bool should_decrement); | ||
| 58 | |||
| 59 | /// Waits on an address if the value passed is equal to the argument value. | ||
| 60 | ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout); | ||
| 61 | |||
| 62 | private: | ||
| 63 | // Waits on the given address with a timeout in nanoseconds | ||
| 64 | ResultCode WaitForAddress(VAddr address, s64 timeout); | ||
| 65 | |||
| 66 | // Gets the threads waiting on an address. | ||
| 67 | std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const; | ||
| 68 | |||
| 69 | Core::System& system; | ||
| 70 | }; | ||
| 31 | 71 | ||
| 32 | } // namespace Kernel::AddressArbiter | 72 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index dd749eed4..04ea9349e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 15 | #include "core/hle/kernel/address_arbiter.h" | ||
| 15 | #include "core/hle/kernel/client_port.h" | 16 | #include "core/hle/kernel/client_port.h" |
| 16 | #include "core/hle/kernel/handle_table.h" | 17 | #include "core/hle/kernel/handle_table.h" |
| 17 | #include "core/hle/kernel/kernel.h" | 18 | #include "core/hle/kernel/kernel.h" |
| @@ -86,11 +87,13 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_ | |||
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | struct KernelCore::Impl { | 89 | struct KernelCore::Impl { |
| 89 | void Initialize(KernelCore& kernel, Core::Timing::CoreTiming& core_timing) { | 90 | explicit Impl(Core::System& system) : address_arbiter{system}, system{system} {} |
| 91 | |||
| 92 | void Initialize(KernelCore& kernel) { | ||
| 90 | Shutdown(); | 93 | Shutdown(); |
| 91 | 94 | ||
| 92 | InitializeSystemResourceLimit(kernel); | 95 | InitializeSystemResourceLimit(kernel); |
| 93 | InitializeThreads(core_timing); | 96 | InitializeThreads(); |
| 94 | } | 97 | } |
| 95 | 98 | ||
| 96 | void Shutdown() { | 99 | void Shutdown() { |
| @@ -122,9 +125,9 @@ struct KernelCore::Impl { | |||
| 122 | ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); | 125 | ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); |
| 123 | } | 126 | } |
| 124 | 127 | ||
| 125 | void InitializeThreads(Core::Timing::CoreTiming& core_timing) { | 128 | void InitializeThreads() { |
| 126 | thread_wakeup_event_type = | 129 | thread_wakeup_event_type = |
| 127 | core_timing.RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); | 130 | system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); |
| 128 | } | 131 | } |
| 129 | 132 | ||
| 130 | std::atomic<u32> next_object_id{0}; | 133 | std::atomic<u32> next_object_id{0}; |
| @@ -135,6 +138,8 @@ struct KernelCore::Impl { | |||
| 135 | std::vector<SharedPtr<Process>> process_list; | 138 | std::vector<SharedPtr<Process>> process_list; |
| 136 | Process* current_process = nullptr; | 139 | Process* current_process = nullptr; |
| 137 | 140 | ||
| 141 | Kernel::AddressArbiter address_arbiter; | ||
| 142 | |||
| 138 | SharedPtr<ResourceLimit> system_resource_limit; | 143 | SharedPtr<ResourceLimit> system_resource_limit; |
| 139 | 144 | ||
| 140 | Core::Timing::EventType* thread_wakeup_event_type = nullptr; | 145 | Core::Timing::EventType* thread_wakeup_event_type = nullptr; |
| @@ -145,15 +150,18 @@ struct KernelCore::Impl { | |||
| 145 | /// Map of named ports managed by the kernel, which can be retrieved using | 150 | /// Map of named ports managed by the kernel, which can be retrieved using |
| 146 | /// the ConnectToPort SVC. | 151 | /// the ConnectToPort SVC. |
| 147 | NamedPortTable named_ports; | 152 | NamedPortTable named_ports; |
| 153 | |||
| 154 | // System context | ||
| 155 | Core::System& system; | ||
| 148 | }; | 156 | }; |
| 149 | 157 | ||
| 150 | KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {} | 158 | KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system)} {} |
| 151 | KernelCore::~KernelCore() { | 159 | KernelCore::~KernelCore() { |
| 152 | Shutdown(); | 160 | Shutdown(); |
| 153 | } | 161 | } |
| 154 | 162 | ||
| 155 | void KernelCore::Initialize(Core::Timing::CoreTiming& core_timing) { | 163 | void KernelCore::Initialize() { |
| 156 | impl->Initialize(*this, core_timing); | 164 | impl->Initialize(*this); |
| 157 | } | 165 | } |
| 158 | 166 | ||
| 159 | void KernelCore::Shutdown() { | 167 | void KernelCore::Shutdown() { |
| @@ -184,6 +192,14 @@ const Process* KernelCore::CurrentProcess() const { | |||
| 184 | return impl->current_process; | 192 | return impl->current_process; |
| 185 | } | 193 | } |
| 186 | 194 | ||
| 195 | AddressArbiter& KernelCore::AddressArbiter() { | ||
| 196 | return impl->address_arbiter; | ||
| 197 | } | ||
| 198 | |||
| 199 | const AddressArbiter& KernelCore::AddressArbiter() const { | ||
| 200 | return impl->address_arbiter; | ||
| 201 | } | ||
| 202 | |||
| 187 | void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) { | 203 | void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) { |
| 188 | impl->named_ports.emplace(std::move(name), std::move(port)); | 204 | impl->named_ports.emplace(std::move(name), std::move(port)); |
| 189 | } | 205 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 154bced42..4d292aca9 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -11,6 +11,10 @@ | |||
| 11 | template <typename T> | 11 | template <typename T> |
| 12 | class ResultVal; | 12 | class ResultVal; |
| 13 | 13 | ||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } | ||
| 17 | |||
| 14 | namespace Core::Timing { | 18 | namespace Core::Timing { |
| 15 | class CoreTiming; | 19 | class CoreTiming; |
| 16 | struct EventType; | 20 | struct EventType; |
| @@ -18,6 +22,7 @@ struct EventType; | |||
| 18 | 22 | ||
| 19 | namespace Kernel { | 23 | namespace Kernel { |
| 20 | 24 | ||
| 25 | class AddressArbiter; | ||
| 21 | class ClientPort; | 26 | class ClientPort; |
| 22 | class HandleTable; | 27 | class HandleTable; |
| 23 | class Process; | 28 | class Process; |
| @@ -30,7 +35,14 @@ private: | |||
| 30 | using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>; | 35 | using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>; |
| 31 | 36 | ||
| 32 | public: | 37 | public: |
| 33 | KernelCore(); | 38 | /// Constructs an instance of the kernel using the given System |
| 39 | /// instance as a context for any necessary system-related state, | ||
| 40 | /// such as threads, CPU core state, etc. | ||
| 41 | /// | ||
| 42 | /// @post After execution of the constructor, the provided System | ||
| 43 | /// object *must* outlive the kernel instance itself. | ||
| 44 | /// | ||
| 45 | explicit KernelCore(Core::System& system); | ||
| 34 | ~KernelCore(); | 46 | ~KernelCore(); |
| 35 | 47 | ||
| 36 | KernelCore(const KernelCore&) = delete; | 48 | KernelCore(const KernelCore&) = delete; |
| @@ -40,11 +52,7 @@ public: | |||
| 40 | KernelCore& operator=(KernelCore&&) = delete; | 52 | KernelCore& operator=(KernelCore&&) = delete; |
| 41 | 53 | ||
| 42 | /// Resets the kernel to a clean slate for use. | 54 | /// Resets the kernel to a clean slate for use. |
| 43 | /// | 55 | void Initialize(); |
| 44 | /// @param core_timing CoreTiming instance used to create any necessary | ||
| 45 | /// kernel-specific callback events. | ||
| 46 | /// | ||
| 47 | void Initialize(Core::Timing::CoreTiming& core_timing); | ||
| 48 | 56 | ||
| 49 | /// Clears all resources in use by the kernel instance. | 57 | /// Clears all resources in use by the kernel instance. |
| 50 | void Shutdown(); | 58 | void Shutdown(); |
| @@ -67,6 +75,12 @@ public: | |||
| 67 | /// Retrieves a const pointer to the current process. | 75 | /// Retrieves a const pointer to the current process. |
| 68 | const Process* CurrentProcess() const; | 76 | const Process* CurrentProcess() const; |
| 69 | 77 | ||
| 78 | /// Provides a reference to the kernel's address arbiter. | ||
| 79 | Kernel::AddressArbiter& AddressArbiter(); | ||
| 80 | |||
| 81 | /// Provides a const reference to the kernel's address arbiter. | ||
| 82 | const Kernel::AddressArbiter& AddressArbiter() const; | ||
| 83 | |||
| 70 | /// Adds a port to the named port table | 84 | /// Adds a port to the named port table |
| 71 | void AddNamedPort(std::string name, SharedPtr<ClientPort> port); | 85 | void AddNamedPort(std::string name, SharedPtr<ClientPort> port); |
| 72 | 86 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c5d399bab..75b88a333 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -47,23 +47,6 @@ constexpr bool IsValidAddressRange(VAddr address, u64 size) { | |||
| 47 | return address + size > address; | 47 | return address + size > address; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | // Checks if a given address range lies within a larger address range. | ||
| 51 | constexpr bool IsInsideAddressRange(VAddr address, u64 size, VAddr address_range_begin, | ||
| 52 | VAddr address_range_end) { | ||
| 53 | const VAddr end_address = address + size - 1; | ||
| 54 | return address_range_begin <= address && end_address <= address_range_end - 1; | ||
| 55 | } | ||
| 56 | |||
| 57 | bool IsInsideAddressSpace(const VMManager& vm, VAddr address, u64 size) { | ||
| 58 | return IsInsideAddressRange(address, size, vm.GetAddressSpaceBaseAddress(), | ||
| 59 | vm.GetAddressSpaceEndAddress()); | ||
| 60 | } | ||
| 61 | |||
| 62 | bool IsInsideNewMapRegion(const VMManager& vm, VAddr address, u64 size) { | ||
| 63 | return IsInsideAddressRange(address, size, vm.GetNewMapRegionBaseAddress(), | ||
| 64 | vm.GetNewMapRegionEndAddress()); | ||
| 65 | } | ||
| 66 | |||
| 67 | // 8 GiB | 50 | // 8 GiB |
| 68 | constexpr u64 MAIN_MEMORY_SIZE = 0x200000000; | 51 | constexpr u64 MAIN_MEMORY_SIZE = 0x200000000; |
| 69 | 52 | ||
| @@ -105,14 +88,14 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add | |||
| 105 | return ERR_INVALID_ADDRESS_STATE; | 88 | return ERR_INVALID_ADDRESS_STATE; |
| 106 | } | 89 | } |
| 107 | 90 | ||
| 108 | if (!IsInsideAddressSpace(vm_manager, src_addr, size)) { | 91 | if (!vm_manager.IsWithinAddressSpace(src_addr, size)) { |
| 109 | LOG_ERROR(Kernel_SVC, | 92 | LOG_ERROR(Kernel_SVC, |
| 110 | "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", | 93 | "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", |
| 111 | src_addr, size); | 94 | src_addr, size); |
| 112 | return ERR_INVALID_ADDRESS_STATE; | 95 | return ERR_INVALID_ADDRESS_STATE; |
| 113 | } | 96 | } |
| 114 | 97 | ||
| 115 | if (!IsInsideNewMapRegion(vm_manager, dst_addr, size)) { | 98 | if (!vm_manager.IsWithinNewMapRegion(dst_addr, size)) { |
| 116 | LOG_ERROR(Kernel_SVC, | 99 | LOG_ERROR(Kernel_SVC, |
| 117 | "Destination is not within the new map region, addr=0x{:016X}, size=0x{:016X}", | 100 | "Destination is not within the new map region, addr=0x{:016X}, size=0x{:016X}", |
| 118 | dst_addr, size); | 101 | dst_addr, size); |
| @@ -238,7 +221,7 @@ static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) { | |||
| 238 | auto* const current_process = Core::CurrentProcess(); | 221 | auto* const current_process = Core::CurrentProcess(); |
| 239 | auto& vm_manager = current_process->VMManager(); | 222 | auto& vm_manager = current_process->VMManager(); |
| 240 | 223 | ||
| 241 | if (!IsInsideAddressSpace(vm_manager, addr, size)) { | 224 | if (!vm_manager.IsWithinAddressSpace(addr, size)) { |
| 242 | LOG_ERROR(Kernel_SVC, | 225 | LOG_ERROR(Kernel_SVC, |
| 243 | "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, | 226 | "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, |
| 244 | size); | 227 | size); |
| @@ -299,7 +282,7 @@ static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attr | |||
| 299 | } | 282 | } |
| 300 | 283 | ||
| 301 | auto& vm_manager = Core::CurrentProcess()->VMManager(); | 284 | auto& vm_manager = Core::CurrentProcess()->VMManager(); |
| 302 | if (!IsInsideAddressSpace(vm_manager, address, size)) { | 285 | if (!vm_manager.IsWithinAddressSpace(address, size)) { |
| 303 | LOG_ERROR(Kernel_SVC, | 286 | LOG_ERROR(Kernel_SVC, |
| 304 | "Given address (0x{:016X}) is outside the bounds of the address space.", address); | 287 | "Given address (0x{:016X}) is outside the bounds of the address space.", address); |
| 305 | return ERR_INVALID_ADDRESS_STATE; | 288 | return ERR_INVALID_ADDRESS_STATE; |
| @@ -1495,13 +1478,14 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout | |||
| 1495 | return ERR_INVALID_ADDRESS; | 1478 | return ERR_INVALID_ADDRESS; |
| 1496 | } | 1479 | } |
| 1497 | 1480 | ||
| 1481 | auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter(); | ||
| 1498 | switch (static_cast<AddressArbiter::ArbitrationType>(type)) { | 1482 | switch (static_cast<AddressArbiter::ArbitrationType>(type)) { |
| 1499 | case AddressArbiter::ArbitrationType::WaitIfLessThan: | 1483 | case AddressArbiter::ArbitrationType::WaitIfLessThan: |
| 1500 | return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false); | 1484 | return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, false); |
| 1501 | case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan: | 1485 | case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan: |
| 1502 | return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, true); | 1486 | return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, true); |
| 1503 | case AddressArbiter::ArbitrationType::WaitIfEqual: | 1487 | case AddressArbiter::ArbitrationType::WaitIfEqual: |
| 1504 | return AddressArbiter::WaitForAddressIfEqual(address, value, timeout); | 1488 | return address_arbiter.WaitForAddressIfEqual(address, value, timeout); |
| 1505 | default: | 1489 | default: |
| 1506 | LOG_ERROR(Kernel_SVC, | 1490 | LOG_ERROR(Kernel_SVC, |
| 1507 | "Invalid arbitration type, expected WaitIfLessThan, DecrementAndWaitIfLessThan " | 1491 | "Invalid arbitration type, expected WaitIfLessThan, DecrementAndWaitIfLessThan " |
| @@ -1526,13 +1510,14 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to | |||
| 1526 | return ERR_INVALID_ADDRESS; | 1510 | return ERR_INVALID_ADDRESS; |
| 1527 | } | 1511 | } |
| 1528 | 1512 | ||
| 1513 | auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter(); | ||
| 1529 | switch (static_cast<AddressArbiter::SignalType>(type)) { | 1514 | switch (static_cast<AddressArbiter::SignalType>(type)) { |
| 1530 | case AddressArbiter::SignalType::Signal: | 1515 | case AddressArbiter::SignalType::Signal: |
| 1531 | return AddressArbiter::SignalToAddress(address, num_to_wake); | 1516 | return address_arbiter.SignalToAddress(address, num_to_wake); |
| 1532 | case AddressArbiter::SignalType::IncrementAndSignalIfEqual: | 1517 | case AddressArbiter::SignalType::IncrementAndSignalIfEqual: |
| 1533 | return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake); | 1518 | return address_arbiter.IncrementAndSignalToAddressIfEqual(address, value, num_to_wake); |
| 1534 | case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual: | 1519 | case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual: |
| 1535 | return AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(address, value, | 1520 | return address_arbiter.ModifyByWaitingCountAndSignalToAddressIfEqual(address, value, |
| 1536 | num_to_wake); | 1521 | num_to_wake); |
| 1537 | default: | 1522 | default: |
| 1538 | LOG_ERROR(Kernel_SVC, | 1523 | LOG_ERROR(Kernel_SVC, |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6661e2130..eb54d6651 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -184,8 +184,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name | |||
| 184 | return ERR_INVALID_PROCESSOR_ID; | 184 | return ERR_INVALID_PROCESSOR_ID; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | // TODO(yuriks): Other checks, returning 0xD9001BEA | ||
| 188 | |||
| 189 | if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) { | 187 | if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) { |
| 190 | LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); | 188 | LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); |
| 191 | // TODO (bunnei): Find the correct error code to use here | 189 | // TODO (bunnei): Find the correct error code to use here |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 10ad94aa6..05c59af34 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include "core/memory_setup.h" | 17 | #include "core/memory_setup.h" |
| 18 | 18 | ||
| 19 | namespace Kernel { | 19 | namespace Kernel { |
| 20 | 20 | namespace { | |
| 21 | static const char* GetMemoryStateName(MemoryState state) { | 21 | const char* GetMemoryStateName(MemoryState state) { |
| 22 | static constexpr const char* names[] = { | 22 | static constexpr const char* names[] = { |
| 23 | "Unmapped", "Io", | 23 | "Unmapped", "Io", |
| 24 | "Normal", "CodeStatic", | 24 | "Normal", "CodeStatic", |
| @@ -35,6 +35,14 @@ static const char* GetMemoryStateName(MemoryState state) { | |||
| 35 | return names[ToSvcMemoryState(state)]; | 35 | return names[ToSvcMemoryState(state)]; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | // Checks if a given address range lies within a larger address range. | ||
| 39 | constexpr bool IsInsideAddressRange(VAddr address, u64 size, VAddr address_range_begin, | ||
| 40 | VAddr address_range_end) { | ||
| 41 | const VAddr end_address = address + size - 1; | ||
| 42 | return address_range_begin <= address && end_address <= address_range_end - 1; | ||
| 43 | } | ||
| 44 | } // Anonymous namespace | ||
| 45 | |||
| 38 | bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | 46 | bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { |
| 39 | ASSERT(base + size == next.base); | 47 | ASSERT(base + size == next.base); |
| 40 | if (permissions != next.permissions || state != next.state || attribute != next.attribute || | 48 | if (permissions != next.permissions || state != next.state || attribute != next.attribute || |
| @@ -249,8 +257,7 @@ ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_p | |||
| 249 | } | 257 | } |
| 250 | 258 | ||
| 251 | ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { | 259 | ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { |
| 252 | if (target < GetHeapRegionBaseAddress() || target + size > GetHeapRegionEndAddress() || | 260 | if (!IsWithinHeapRegion(target, size)) { |
| 253 | target + size < target) { | ||
| 254 | return ERR_INVALID_ADDRESS; | 261 | return ERR_INVALID_ADDRESS; |
| 255 | } | 262 | } |
| 256 | 263 | ||
| @@ -285,8 +292,7 @@ ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission p | |||
| 285 | } | 292 | } |
| 286 | 293 | ||
| 287 | ResultCode VMManager::HeapFree(VAddr target, u64 size) { | 294 | ResultCode VMManager::HeapFree(VAddr target, u64 size) { |
| 288 | if (target < GetHeapRegionBaseAddress() || target + size > GetHeapRegionEndAddress() || | 295 | if (!IsWithinHeapRegion(target, size)) { |
| 289 | target + size < target) { | ||
| 290 | return ERR_INVALID_ADDRESS; | 296 | return ERR_INVALID_ADDRESS; |
| 291 | } | 297 | } |
| 292 | 298 | ||
| @@ -706,6 +712,11 @@ u64 VMManager::GetAddressSpaceWidth() const { | |||
| 706 | return address_space_width; | 712 | return address_space_width; |
| 707 | } | 713 | } |
| 708 | 714 | ||
| 715 | bool VMManager::IsWithinAddressSpace(VAddr address, u64 size) const { | ||
| 716 | return IsInsideAddressRange(address, size, GetAddressSpaceBaseAddress(), | ||
| 717 | GetAddressSpaceEndAddress()); | ||
| 718 | } | ||
| 719 | |||
| 709 | VAddr VMManager::GetASLRRegionBaseAddress() const { | 720 | VAddr VMManager::GetASLRRegionBaseAddress() const { |
| 710 | return aslr_region_base; | 721 | return aslr_region_base; |
| 711 | } | 722 | } |
| @@ -750,6 +761,11 @@ u64 VMManager::GetCodeRegionSize() const { | |||
| 750 | return code_region_end - code_region_base; | 761 | return code_region_end - code_region_base; |
| 751 | } | 762 | } |
| 752 | 763 | ||
| 764 | bool VMManager::IsWithinCodeRegion(VAddr address, u64 size) const { | ||
| 765 | return IsInsideAddressRange(address, size, GetCodeRegionBaseAddress(), | ||
| 766 | GetCodeRegionEndAddress()); | ||
| 767 | } | ||
| 768 | |||
| 753 | VAddr VMManager::GetHeapRegionBaseAddress() const { | 769 | VAddr VMManager::GetHeapRegionBaseAddress() const { |
| 754 | return heap_region_base; | 770 | return heap_region_base; |
| 755 | } | 771 | } |
| @@ -762,6 +778,11 @@ u64 VMManager::GetHeapRegionSize() const { | |||
| 762 | return heap_region_end - heap_region_base; | 778 | return heap_region_end - heap_region_base; |
| 763 | } | 779 | } |
| 764 | 780 | ||
| 781 | bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { | ||
| 782 | return IsInsideAddressRange(address, size, GetHeapRegionBaseAddress(), | ||
| 783 | GetHeapRegionEndAddress()); | ||
| 784 | } | ||
| 785 | |||
| 765 | VAddr VMManager::GetMapRegionBaseAddress() const { | 786 | VAddr VMManager::GetMapRegionBaseAddress() const { |
| 766 | return map_region_base; | 787 | return map_region_base; |
| 767 | } | 788 | } |
| @@ -774,6 +795,10 @@ u64 VMManager::GetMapRegionSize() const { | |||
| 774 | return map_region_end - map_region_base; | 795 | return map_region_end - map_region_base; |
| 775 | } | 796 | } |
| 776 | 797 | ||
| 798 | bool VMManager::IsWithinMapRegion(VAddr address, u64 size) const { | ||
| 799 | return IsInsideAddressRange(address, size, GetMapRegionBaseAddress(), GetMapRegionEndAddress()); | ||
| 800 | } | ||
| 801 | |||
| 777 | VAddr VMManager::GetNewMapRegionBaseAddress() const { | 802 | VAddr VMManager::GetNewMapRegionBaseAddress() const { |
| 778 | return new_map_region_base; | 803 | return new_map_region_base; |
| 779 | } | 804 | } |
| @@ -786,6 +811,11 @@ u64 VMManager::GetNewMapRegionSize() const { | |||
| 786 | return new_map_region_end - new_map_region_base; | 811 | return new_map_region_end - new_map_region_base; |
| 787 | } | 812 | } |
| 788 | 813 | ||
| 814 | bool VMManager::IsWithinNewMapRegion(VAddr address, u64 size) const { | ||
| 815 | return IsInsideAddressRange(address, size, GetNewMapRegionBaseAddress(), | ||
| 816 | GetNewMapRegionEndAddress()); | ||
| 817 | } | ||
| 818 | |||
| 789 | VAddr VMManager::GetTLSIORegionBaseAddress() const { | 819 | VAddr VMManager::GetTLSIORegionBaseAddress() const { |
| 790 | return tls_io_region_base; | 820 | return tls_io_region_base; |
| 791 | } | 821 | } |
| @@ -798,4 +828,9 @@ u64 VMManager::GetTLSIORegionSize() const { | |||
| 798 | return tls_io_region_end - tls_io_region_base; | 828 | return tls_io_region_end - tls_io_region_base; |
| 799 | } | 829 | } |
| 800 | 830 | ||
| 831 | bool VMManager::IsWithinTLSIORegion(VAddr address, u64 size) const { | ||
| 832 | return IsInsideAddressRange(address, size, GetTLSIORegionBaseAddress(), | ||
| 833 | GetTLSIORegionEndAddress()); | ||
| 834 | } | ||
| 835 | |||
| 801 | } // namespace Kernel | 836 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 6091533bc..88e0b3c02 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -432,18 +432,21 @@ public: | |||
| 432 | /// Gets the address space width in bits. | 432 | /// Gets the address space width in bits. |
| 433 | u64 GetAddressSpaceWidth() const; | 433 | u64 GetAddressSpaceWidth() const; |
| 434 | 434 | ||
| 435 | /// Determines whether or not the given address range lies within the address space. | ||
| 436 | bool IsWithinAddressSpace(VAddr address, u64 size) const; | ||
| 437 | |||
| 435 | /// Gets the base address of the ASLR region. | 438 | /// Gets the base address of the ASLR region. |
| 436 | VAddr GetASLRRegionBaseAddress() const; | 439 | VAddr GetASLRRegionBaseAddress() const; |
| 437 | 440 | ||
| 438 | /// Gets the end address of the ASLR region. | 441 | /// Gets the end address of the ASLR region. |
| 439 | VAddr GetASLRRegionEndAddress() const; | 442 | VAddr GetASLRRegionEndAddress() const; |
| 440 | 443 | ||
| 441 | /// Determines whether or not the specified address range is within the ASLR region. | ||
| 442 | bool IsWithinASLRRegion(VAddr address, u64 size) const; | ||
| 443 | |||
| 444 | /// Gets the size of the ASLR region | 444 | /// Gets the size of the ASLR region |
| 445 | u64 GetASLRRegionSize() const; | 445 | u64 GetASLRRegionSize() const; |
| 446 | 446 | ||
| 447 | /// Determines whether or not the specified address range is within the ASLR region. | ||
| 448 | bool IsWithinASLRRegion(VAddr address, u64 size) const; | ||
| 449 | |||
| 447 | /// Gets the base address of the code region. | 450 | /// Gets the base address of the code region. |
| 448 | VAddr GetCodeRegionBaseAddress() const; | 451 | VAddr GetCodeRegionBaseAddress() const; |
| 449 | 452 | ||
| @@ -453,6 +456,9 @@ public: | |||
| 453 | /// Gets the total size of the code region in bytes. | 456 | /// Gets the total size of the code region in bytes. |
| 454 | u64 GetCodeRegionSize() const; | 457 | u64 GetCodeRegionSize() const; |
| 455 | 458 | ||
| 459 | /// Determines whether or not the specified range is within the code region. | ||
| 460 | bool IsWithinCodeRegion(VAddr address, u64 size) const; | ||
| 461 | |||
| 456 | /// Gets the base address of the heap region. | 462 | /// Gets the base address of the heap region. |
| 457 | VAddr GetHeapRegionBaseAddress() const; | 463 | VAddr GetHeapRegionBaseAddress() const; |
| 458 | 464 | ||
| @@ -462,6 +468,9 @@ public: | |||
| 462 | /// Gets the total size of the heap region in bytes. | 468 | /// Gets the total size of the heap region in bytes. |
| 463 | u64 GetHeapRegionSize() const; | 469 | u64 GetHeapRegionSize() const; |
| 464 | 470 | ||
| 471 | /// Determines whether or not the specified range is within the heap region. | ||
| 472 | bool IsWithinHeapRegion(VAddr address, u64 size) const; | ||
| 473 | |||
| 465 | /// Gets the base address of the map region. | 474 | /// Gets the base address of the map region. |
| 466 | VAddr GetMapRegionBaseAddress() const; | 475 | VAddr GetMapRegionBaseAddress() const; |
| 467 | 476 | ||
| @@ -471,6 +480,9 @@ public: | |||
| 471 | /// Gets the total size of the map region in bytes. | 480 | /// Gets the total size of the map region in bytes. |
| 472 | u64 GetMapRegionSize() const; | 481 | u64 GetMapRegionSize() const; |
| 473 | 482 | ||
| 483 | /// Determines whether or not the specified range is within the map region. | ||
| 484 | bool IsWithinMapRegion(VAddr address, u64 size) const; | ||
| 485 | |||
| 474 | /// Gets the base address of the new map region. | 486 | /// Gets the base address of the new map region. |
| 475 | VAddr GetNewMapRegionBaseAddress() const; | 487 | VAddr GetNewMapRegionBaseAddress() const; |
| 476 | 488 | ||
| @@ -480,6 +492,9 @@ public: | |||
| 480 | /// Gets the total size of the new map region in bytes. | 492 | /// Gets the total size of the new map region in bytes. |
| 481 | u64 GetNewMapRegionSize() const; | 493 | u64 GetNewMapRegionSize() const; |
| 482 | 494 | ||
| 495 | /// Determines whether or not the given address range is within the new map region | ||
| 496 | bool IsWithinNewMapRegion(VAddr address, u64 size) const; | ||
| 497 | |||
| 483 | /// Gets the base address of the TLS IO region. | 498 | /// Gets the base address of the TLS IO region. |
| 484 | VAddr GetTLSIORegionBaseAddress() const; | 499 | VAddr GetTLSIORegionBaseAddress() const; |
| 485 | 500 | ||
| @@ -489,6 +504,9 @@ public: | |||
| 489 | /// Gets the total size of the TLS IO region in bytes. | 504 | /// Gets the total size of the TLS IO region in bytes. |
| 490 | u64 GetTLSIORegionSize() const; | 505 | u64 GetTLSIORegionSize() const; |
| 491 | 506 | ||
| 507 | /// Determines if the given address range is within the TLS IO region. | ||
| 508 | bool IsWithinTLSIORegion(VAddr address, u64 size) const; | ||
| 509 | |||
| 492 | /// Each VMManager has its own page table, which is set as the main one when the owning process | 510 | /// Each VMManager has its own page table, which is set as the main one when the owning process |
| 493 | /// is scheduled. | 511 | /// is scheduled. |
| 494 | Memory::PageTable page_table; | 512 | Memory::PageTable page_table; |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 6831c0735..bbe813490 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -18,17 +18,11 @@ | |||
| 18 | #include "core/hle/kernel/readable_event.h" | 18 | #include "core/hle/kernel/readable_event.h" |
| 19 | #include "core/hle/kernel/writable_event.h" | 19 | #include "core/hle/kernel/writable_event.h" |
| 20 | #include "core/hle/service/audio/audout_u.h" | 20 | #include "core/hle/service/audio/audout_u.h" |
| 21 | #include "core/hle/service/audio/errors.h" | ||
| 21 | #include "core/memory.h" | 22 | #include "core/memory.h" |
| 22 | 23 | ||
| 23 | namespace Service::Audio { | 24 | namespace Service::Audio { |
| 24 | 25 | ||
| 25 | namespace ErrCodes { | ||
| 26 | enum { | ||
| 27 | ErrorUnknown = 2, | ||
| 28 | BufferCountExceeded = 8, | ||
| 29 | }; | ||
| 30 | } | ||
| 31 | |||
| 32 | constexpr std::array<char, 10> DefaultDevice{{"DeviceOut"}}; | 26 | constexpr std::array<char, 10> DefaultDevice{{"DeviceOut"}}; |
| 33 | constexpr int DefaultSampleRate{48000}; | 27 | constexpr int DefaultSampleRate{48000}; |
| 34 | 28 | ||
| @@ -100,7 +94,7 @@ private: | |||
| 100 | 94 | ||
| 101 | if (stream->IsPlaying()) { | 95 | if (stream->IsPlaying()) { |
| 102 | IPC::ResponseBuilder rb{ctx, 2}; | 96 | IPC::ResponseBuilder rb{ctx, 2}; |
| 103 | rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::ErrorUnknown)); | 97 | rb.Push(ERR_OPERATION_FAILED); |
| 104 | return; | 98 | return; |
| 105 | } | 99 | } |
| 106 | 100 | ||
| @@ -143,7 +137,8 @@ private: | |||
| 143 | 137 | ||
| 144 | if (!audio_core.QueueBuffer(stream, tag, std::move(samples))) { | 138 | if (!audio_core.QueueBuffer(stream, tag, std::move(samples))) { |
| 145 | IPC::ResponseBuilder rb{ctx, 2}; | 139 | IPC::ResponseBuilder rb{ctx, 2}; |
| 146 | rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded)); | 140 | rb.Push(ERR_BUFFER_COUNT_EXCEEDED); |
| 141 | return; | ||
| 147 | } | 142 | } |
| 148 | 143 | ||
| 149 | IPC::ResponseBuilder rb{ctx, 2}; | 144 | IPC::ResponseBuilder rb{ctx, 2}; |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index ea8f9d0bb..c9de10a24 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "core/hle/kernel/readable_event.h" | 17 | #include "core/hle/kernel/readable_event.h" |
| 18 | #include "core/hle/kernel/writable_event.h" | 18 | #include "core/hle/kernel/writable_event.h" |
| 19 | #include "core/hle/service/audio/audren_u.h" | 19 | #include "core/hle/service/audio/audren_u.h" |
| 20 | #include "core/hle/service/audio/errors.h" | ||
| 20 | 21 | ||
| 21 | namespace Service::Audio { | 22 | namespace Service::Audio { |
| 22 | 23 | ||
| @@ -146,7 +147,7 @@ private: | |||
| 146 | // code in this case. | 147 | // code in this case. |
| 147 | 148 | ||
| 148 | IPC::ResponseBuilder rb{ctx, 2}; | 149 | IPC::ResponseBuilder rb{ctx, 2}; |
| 149 | rb.Push(ResultCode{ErrorModule::Audio, 201}); | 150 | rb.Push(ERR_NOT_SUPPORTED); |
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | Kernel::EventPair system_event; | 153 | Kernel::EventPair system_event; |
diff --git a/src/core/hle/service/audio/errors.h b/src/core/hle/service/audio/errors.h new file mode 100644 index 000000000..6f8c09bcf --- /dev/null +++ b/src/core/hle/service/audio/errors.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/result.h" | ||
| 8 | |||
| 9 | namespace Service::Audio { | ||
| 10 | |||
| 11 | constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::Audio, 2}; | ||
| 12 | constexpr ResultCode ERR_BUFFER_COUNT_EXCEEDED{ErrorModule::Audio, 8}; | ||
| 13 | constexpr ResultCode ERR_NOT_SUPPORTED{ErrorModule::Audio, 513}; | ||
| 14 | |||
| 15 | } // namespace Service::Audio | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index f809567b6..ec279cef8 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -171,9 +171,6 @@ T Read(const VAddr vaddr) { | |||
| 171 | return value; | 171 | return value; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state | ||
| 175 | std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||
| 176 | |||
| 177 | PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 174 | PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; |
| 178 | switch (type) { | 175 | switch (type) { |
| 179 | case PageType::Unmapped: | 176 | case PageType::Unmapped: |
| @@ -204,9 +201,6 @@ void Write(const VAddr vaddr, const T data) { | |||
| 204 | return; | 201 | return; |
| 205 | } | 202 | } |
| 206 | 203 | ||
| 207 | // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state | ||
| 208 | std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||
| 209 | |||
| 210 | PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 204 | PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; |
| 211 | switch (type) { | 205 | switch (type) { |
| 212 | case PageType::Unmapped: | 206 | case PageType::Unmapped: |
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 9b8a44fa1..ea27ef90d 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp | |||
| @@ -13,11 +13,11 @@ | |||
| 13 | namespace ArmTests { | 13 | namespace ArmTests { |
| 14 | 14 | ||
| 15 | TestEnvironment::TestEnvironment(bool mutable_memory_) | 15 | TestEnvironment::TestEnvironment(bool mutable_memory_) |
| 16 | : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { | 16 | : mutable_memory(mutable_memory_), |
| 17 | 17 | test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} { | |
| 18 | auto process = Kernel::Process::Create(kernel, ""); | 18 | auto process = Kernel::Process::Create(kernel, ""); |
| 19 | kernel.MakeCurrentProcess(process.get()); | 19 | kernel.MakeCurrentProcess(process.get()); |
| 20 | page_table = &Core::CurrentProcess()->VMManager().page_table; | 20 | page_table = &process->VMManager().page_table; |
| 21 | 21 | ||
| 22 | std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr); | 22 | std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr); |
| 23 | page_table->special_regions.clear(); | 23 | page_table->special_regions.clear(); |
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 540dcc52c..03b7ee5d8 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp | |||
| @@ -2,12 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/core.h" | 5 | #include "common/assert.h" |
| 6 | #include "core/memory.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/math_util.h" | ||
| 7 | #include "video_core/engines/fermi_2d.h" | 8 | #include "video_core/engines/fermi_2d.h" |
| 8 | #include "video_core/engines/maxwell_3d.h" | ||
| 9 | #include "video_core/rasterizer_interface.h" | 9 | #include "video_core/rasterizer_interface.h" |
| 10 | #include "video_core/textures/decoders.h" | ||
| 11 | 10 | ||
| 12 | namespace Tegra::Engines { | 11 | namespace Tegra::Engines { |
| 13 | 12 | ||
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index c69f74cc5..80523e320 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include "common/assert.h" | 8 | #include <cstddef> |
| 9 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index 4ca856b6b..b1d950460 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp | |||
| @@ -2,9 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/assert.h" | ||
| 5 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | ||
| 7 | #include "core/memory.h" | ||
| 8 | #include "video_core/engines/kepler_compute.h" | 7 | #include "video_core/engines/kepler_compute.h" |
| 9 | #include "video_core/memory_manager.h" | 8 | #include "video_core/memory_manager.h" |
| 10 | 9 | ||
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index df0a32e0f..6575afd0f 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h | |||
| @@ -5,8 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include "common/assert.h" | 8 | #include <cstddef> |
| 9 | #include "common/bit_field.h" | ||
| 10 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 12 | #include "video_core/gpu.h" | 11 | #include "video_core/gpu.h" |
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index f680c2ad9..9181e9d80 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | ||
| 8 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 9 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 529a14ec7..0474c7ba3 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/memory.h" | 8 | #include "core/memory.h" |
| 8 | #include "video_core/engines/maxwell_3d.h" | 9 | #include "video_core/engines/maxwell_3d.h" |
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index cf75aeb12..34c369320 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | ||
| 8 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 9 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 252592edd..c7eb15b6a 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | #include <bitset> | 7 | #include <bitset> |
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <string> | ||
| 10 | #include <tuple> | 9 | #include <tuple> |
| 11 | #include <vector> | 10 | #include <vector> |
| 12 | 11 | ||
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index 94223f45f..919d1f2d4 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | ||
| 5 | #include "core/frontend/emu_window.h" | 6 | #include "core/frontend/emu_window.h" |
| 6 | #include "core/settings.h" | 7 | #include "core/settings.h" |
| 7 | #include "video_core/renderer_base.h" | 8 | #include "video_core/renderer_base.h" |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c8c1d6911..321d9dd3d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -739,22 +739,10 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 739 | state.Apply(); | 739 | state.Apply(); |
| 740 | 740 | ||
| 741 | res_cache.SignalPreDrawCall(); | 741 | res_cache.SignalPreDrawCall(); |
| 742 | |||
| 743 | // Execute draw call | ||
| 744 | params.DispatchDraw(); | 742 | params.DispatchDraw(); |
| 745 | |||
| 746 | res_cache.SignalPostDrawCall(); | 743 | res_cache.SignalPostDrawCall(); |
| 747 | 744 | ||
| 748 | // Disable scissor test | ||
| 749 | state.viewports[0].scissor.enabled = false; | ||
| 750 | |||
| 751 | accelerate_draw = AccelDraw::Disabled; | 745 | accelerate_draw = AccelDraw::Disabled; |
| 752 | |||
| 753 | // Unbind textures for potential future use as framebuffer attachments | ||
| 754 | for (auto& texture_unit : state.texture_units) { | ||
| 755 | texture_unit.Unbind(); | ||
| 756 | } | ||
| 757 | state.Apply(); | ||
| 758 | } | 746 | } |
| 759 | 747 | ||
| 760 | void RasterizerOpenGL::FlushAll() {} | 748 | void RasterizerOpenGL::FlushAll() {} |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 219f08053..9419326a3 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -461,7 +461,7 @@ void OpenGLState::ApplyTextures() const { | |||
| 461 | 461 | ||
| 462 | if (has_delta) { | 462 | if (has_delta) { |
| 463 | glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), | 463 | glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), |
| 464 | textures.data()); | 464 | textures.data() + first); |
| 465 | } | 465 | } |
| 466 | } | 466 | } |
| 467 | 467 | ||
| @@ -482,7 +482,7 @@ void OpenGLState::ApplySamplers() const { | |||
| 482 | } | 482 | } |
| 483 | if (has_delta) { | 483 | if (has_delta) { |
| 484 | glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), | 484 | glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), |
| 485 | samplers.data()); | 485 | samplers.data() + first); |
| 486 | } | 486 | } |
| 487 | } | 487 | } |
| 488 | 488 | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 18b7b94a1..4a33a6c84 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <tuple> | 8 | #include <tuple> |
| 9 | 9 | ||
| 10 | #include "common/alignment.h" | 10 | #include "common/alignment.h" |
| 11 | #include "core/core.h" | 11 | #include "common/assert.h" |
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | #include "video_core/renderer_vulkan/declarations.h" | 13 | #include "video_core/renderer_vulkan/declarations.h" |
| 14 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 14 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 6cbe21202..d8e916f31 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -44,9 +44,9 @@ struct CachedBufferEntry final : public RasterizerCacheObject { | |||
| 44 | 44 | ||
| 45 | class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> { | 45 | class VKBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> { |
| 46 | public: | 46 | public: |
| 47 | explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, VideoCore::RasterizerInterface& rasterizer, | 47 | explicit VKBufferCache(Tegra::MemoryManager& tegra_memory_manager, |
| 48 | const VKDevice& device, VKMemoryManager& memory_manager, | 48 | VideoCore::RasterizerInterface& rasterizer, const VKDevice& device, |
| 49 | VKScheduler& scheduler, u64 size); | 49 | VKMemoryManager& memory_manager, VKScheduler& scheduler, u64 size); |
| 50 | ~VKBufferCache(); | 50 | ~VKBufferCache(); |
| 51 | 51 | ||
| 52 | /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been | 52 | /// Uploads data from a guest GPU address. Returns host's buffer offset where it's been |
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 044ba116a..a7ac26d71 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp | |||
| @@ -89,8 +89,6 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { | |||
| 89 | 89 | ||
| 90 | PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { | 90 | PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { |
| 91 | switch (format) { | 91 | switch (format) { |
| 92 | // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the | ||
| 93 | // gamma. | ||
| 94 | case Tegra::RenderTargetFormat::RGBA8_SRGB: | 92 | case Tegra::RenderTargetFormat::RGBA8_SRGB: |
| 95 | return PixelFormat::RGBA8_SRGB; | 93 | return PixelFormat::RGBA8_SRGB; |
| 96 | case Tegra::RenderTargetFormat::RGBA8_UNORM: | 94 | case Tegra::RenderTargetFormat::RGBA8_UNORM: |
diff --git a/src/web_service/verify_login.h b/src/web_service/verify_login.h index 39db32dbb..821b345d7 100644 --- a/src/web_service/verify_login.h +++ b/src/web_service/verify_login.h | |||
| @@ -4,8 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <functional> | ||
| 8 | #include <future> | ||
| 9 | #include <string> | 7 | #include <string> |
| 10 | 8 | ||
| 11 | namespace WebService { | 9 | namespace WebService { |
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp index b7737b615..40da1a4e2 100644 --- a/src/web_service/web_backend.cpp +++ b/src/web_service/web_backend.cpp | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/web_result.h" | 12 | #include "common/web_result.h" |
| 13 | #include "core/settings.h" | ||
| 14 | #include "web_service/web_backend.h" | 13 | #include "web_service/web_backend.h" |
| 15 | 14 | ||
| 16 | namespace WebService { | 15 | namespace WebService { |
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index f50225d5f..06ad74ffe 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp | |||
| @@ -81,9 +81,8 @@ QString WaitTreeText::GetText() const { | |||
| 81 | return text; | 81 | return text; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) { | 84 | WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table) |
| 85 | const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); | 85 | : mutex_address(mutex_address) { |
| 86 | |||
| 87 | mutex_value = Memory::Read32(mutex_address); | 86 | mutex_value = Memory::Read32(mutex_address); |
| 88 | owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask); | 87 | owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask); |
| 89 | owner = handle_table.Get<Kernel::Thread>(owner_handle); | 88 | owner = handle_table.Get<Kernel::Thread>(owner_handle); |
| @@ -316,7 +315,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { | |||
| 316 | 315 | ||
| 317 | const VAddr mutex_wait_address = thread.GetMutexWaitAddress(); | 316 | const VAddr mutex_wait_address = thread.GetMutexWaitAddress(); |
| 318 | if (mutex_wait_address != 0) { | 317 | if (mutex_wait_address != 0) { |
| 319 | list.push_back(std::make_unique<WaitTreeMutexInfo>(mutex_wait_address)); | 318 | const auto& handle_table = thread.GetOwnerProcess()->GetHandleTable(); |
| 319 | list.push_back(std::make_unique<WaitTreeMutexInfo>(mutex_wait_address, handle_table)); | ||
| 320 | } else { | 320 | } else { |
| 321 | list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex"))); | 321 | list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex"))); |
| 322 | } | 322 | } |
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 365c3dbfe..62886609d 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | class EmuThread; | 17 | class EmuThread; |
| 18 | 18 | ||
| 19 | namespace Kernel { | 19 | namespace Kernel { |
| 20 | class HandleTable; | ||
| 20 | class ReadableEvent; | 21 | class ReadableEvent; |
| 21 | class WaitObject; | 22 | class WaitObject; |
| 22 | class Thread; | 23 | class Thread; |
| @@ -72,7 +73,7 @@ public: | |||
| 72 | class WaitTreeMutexInfo : public WaitTreeExpandableItem { | 73 | class WaitTreeMutexInfo : public WaitTreeExpandableItem { |
| 73 | Q_OBJECT | 74 | Q_OBJECT |
| 74 | public: | 75 | public: |
| 75 | explicit WaitTreeMutexInfo(VAddr mutex_address); | 76 | explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table); |
| 76 | ~WaitTreeMutexInfo() override; | 77 | ~WaitTreeMutexInfo() override; |
| 77 | 78 | ||
| 78 | QString GetText() const override; | 79 | QString GetText() const override; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 62aafd1d7..0f5a14841 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -561,7 +561,10 @@ void GMainWindow::InitializeHotkeys() { | |||
| 561 | Settings::values.use_frame_limit = !Settings::values.use_frame_limit; | 561 | Settings::values.use_frame_limit = !Settings::values.use_frame_limit; |
| 562 | UpdateStatusBar(); | 562 | UpdateStatusBar(); |
| 563 | }); | 563 | }); |
| 564 | constexpr u16 SPEED_LIMIT_STEP = 5; | 564 | // TODO: Remove this comment/static whenever the next major release of |
| 565 | // MSVC occurs and we make it a requirement (see: | ||
| 566 | // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html) | ||
| 567 | static constexpr u16 SPEED_LIMIT_STEP = 5; | ||
| 565 | connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), | 568 | connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), |
| 566 | &QShortcut::activated, this, [&] { | 569 | &QShortcut::activated, this, [&] { |
| 567 | if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { | 570 | if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { |