From 003e9c5a017935c3b802c82f7053ccead36bb282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Thu, 6 Feb 2020 00:07:45 +0530 Subject: [PATCH] Fix issues with not being able to run ROMs concurrently This commit fixes GroupMutex and by extension issues with trying to run ROMs without quitting the application in between. --- app/src/main/cpp/skyline/common.cpp | 26 +++++++++---------- app/src/main/cpp/skyline/common.h | 18 +++++++++---- app/src/main/cpp/skyline/kernel/memory.cpp | 8 +++--- app/src/main/cpp/skyline/kernel/memory.h | 4 +++ app/src/main/cpp/skyline/kernel/svc.cpp | 4 +-- .../skyline/kernel/types/KPrivateMemory.cpp | 6 +++-- .../cpp/skyline/kernel/types/KProcess.cpp | 8 +++--- .../main/cpp/skyline/kernel/types/KProcess.h | 4 +-- app/src/main/cpp/skyline/nce.cpp | 2 ++ app/src/main/cpp/skyline/nce/guest.cpp | 2 ++ 10 files changed, 49 insertions(+), 33 deletions(-) diff --git a/app/src/main/cpp/skyline/common.cpp b/app/src/main/cpp/skyline/common.cpp index c4ed0a0b..9adb342b 100644 --- a/app/src/main/cpp/skyline/common.cpp +++ b/app/src/main/cpp/skyline/common.cpp @@ -18,20 +18,18 @@ namespace skyline { void GroupMutex::lock(Group group) { auto none = Group::None; - if (flag == group) { - num++; - return; - } - while (true) { - for (int i = 0; i < 1000; ++i) { - if (flag.compare_exchange_weak(none, group)) { - num++; - return; - } - asm volatile("yield"); + constexpr u64 timeout = 1000; // The timeout in ns + auto start = utils::GetTimeNs(); + while (next != group && !next.compare_exchange_weak(none, group)) { + if (flag == group && ((utils::GetTimeNs() - start) > timeout)) { + num++; + return; } - sched_yield(); + asm volatile("yield"); } + while (flag != group && !flag.compare_exchange_weak(none, group)) + asm volatile("yield"); + num++; } void GroupMutex::unlock() { @@ -51,11 +49,11 @@ namespace skyline { break; case 'b': boolMap[elem->FindAttribute("name")->Value()] = elem->FindAttribute( - "value")->BoolValue(); + "value")->BoolValue(); break; case 'i': intMap[elem->FindAttribute("name")->Value()] = elem->FindAttribute( - "value")->IntValue(); + "value")->IntValue(); break; default: syslog(LOG_ALERT, "Settings type is missing: %s for %s", elem->Value(), diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h index 22c6004f..f7a6d9df 100644 --- a/app/src/main/cpp/skyline/common.h +++ b/app/src/main/cpp/skyline/common.h @@ -100,12 +100,19 @@ namespace skyline { * @brief Returns the current time in nanoseconds * @return The current time in nanoseconds */ - inline u64 GetCurrTimeNs() { - return static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); + inline u64 GetTimeNs() { + static u64 frequencyMs{}; + if (!frequencyMs) { + asm("MRS %0, CNTFRQ_EL0" : "=r"(frequencyMs)); + frequencyMs *= 1000000000; + } + u64 ticks; + asm("MRS %0, CNTVCT_EL0" : "=r"(ticks)); + return ticks / frequencyMs; } /** - * @brief Aligns up a value to a multiple of two + * @brief Aligns up a value to a multiple of twoB * @tparam Type The type of the values * @param value The value to round up * @param multiple The multiple to round up to (Should be a multiple of 2) @@ -113,7 +120,7 @@ namespace skyline { * @tparam TypeMul The type of the multiple * @return The aligned value */ - template + template inline TypeVal AlignUp(TypeVal value, TypeMul multiple) { static_assert(std::is_integral() && std::is_integral()); multiple--; @@ -128,7 +135,7 @@ namespace skyline { * @tparam TypeMul The type of the multiple * @return The aligned value */ - template + template inline TypeVal AlignDown(TypeVal value, TypeMul multiple) { static_assert(std::is_integral() && std::is_integral()); multiple--; @@ -207,6 +214,7 @@ namespace skyline { private: std::atomic flag = Group::None; //!< An atomic flag to hold which group holds the mutex + std::atomic next = Group::None; //!< An atomic flag to hold which group will hold the mutex next std::atomic num = 0; //!< An atomic u8 keeping track of how many users are holding the mutex }; diff --git a/app/src/main/cpp/skyline/kernel/memory.cpp b/app/src/main/cpp/skyline/kernel/memory.cpp index 18e20bff..887b9552 100644 --- a/app/src/main/cpp/skyline/kernel/memory.cpp +++ b/app/src/main/cpp/skyline/kernel/memory.cpp @@ -87,7 +87,7 @@ namespace skyline::kernel { } void MemoryManager::InitializeRegions(u64 address, u64 size, const memory::AddressSpaceType type) { - switch(type) { + switch (type) { case memory::AddressSpaceType::AddressSpace32Bit: throw exception("32-bit address spaces are not supported"); case memory::AddressSpaceType::AddressSpace36Bit: { @@ -95,7 +95,7 @@ namespace skyline::kernel { base.size = 0xFF8000000; code.address = base.address; code.size = 0x78000000; - if(code.address > address || (code.size - (address - code.address)) < size) + if (code.address > address || (code.size - (address - code.address)) < size) throw exception("Code mapping larger than 36-bit code region"); alias.address = code.address + code.size; alias.size = 0x180000000; @@ -124,7 +124,7 @@ namespace skyline::kernel { } } state.logger->Debug("Region Map:\nCode Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nAlias Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nHeap Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nStack Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nTLS/IO Region: 0x{:X} - 0x{:X} (Size: 0x{:X})", code.address, code.address + code.size, code.size, alias.address, alias.address + alias.size, alias.size, heap.address, heap - .address + heap.size, heap.size, stack.address, stack.address + stack.size, stack.size, tlsIo.address, tlsIo.address + tlsIo.size, tlsIo.size); + .address + heap.size, heap.size, stack.address, stack.address + stack.size, stack.size, tlsIo.address, tlsIo.address + tlsIo.size, tlsIo.size); } MemoryManager::MemoryManager(const DeviceState &state) : state(state) {} @@ -139,7 +139,7 @@ namespace skyline::kernel { } memory::Region MemoryManager::GetRegion(memory::Regions region) { - switch(region) { + switch (region) { case memory::Regions::Base: return base; case memory::Regions::Code: diff --git a/app/src/main/cpp/skyline/kernel/memory.h b/app/src/main/cpp/skyline/kernel/memory.h index 1387881b..ed53fbd8 100644 --- a/app/src/main/cpp/skyline/kernel/memory.h +++ b/app/src/main/cpp/skyline/kernel/memory.h @@ -120,6 +120,7 @@ namespace skyline { */ union MemoryState { constexpr MemoryState(const u32 value) : value(value) {}; + constexpr MemoryState() : value(0) {}; struct { @@ -226,6 +227,7 @@ namespace skyline { namespace svc { void SetMemoryAttribute(DeviceState &state); + void MapMemory(DeviceState &state); } @@ -324,7 +326,9 @@ namespace skyline { friend class type::KTransferMemory; friend class type::KProcess; friend class loader::NroLoader; + friend void svc::SetMemoryAttribute(DeviceState &state); + friend void svc::MapMemory(skyline::DeviceState &state); MemoryManager(const DeviceState &state); diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index 683ce3d4..7f4f52a3 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -377,7 +377,7 @@ namespace skyline::kernel::svc { } auto timeout = state.ctx->registers.x3; state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout); - auto start = utils::GetCurrTimeNs(); + auto start = utils::GetTimeNs(); while (true) { if (state.thread->cancelSync) { state.thread->cancelSync = false; @@ -394,7 +394,7 @@ namespace skyline::kernel::svc { } index++; } - if ((utils::GetCurrTimeNs() - start) >= timeout) { + if ((utils::GetTimeNs() - start) >= timeout) { state.logger->Debug("svcWaitSynchronization: Wait has timed out"); state.ctx->registers.w0 = constant::status::Timeout; return; diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp index 9e4b9bf3..aab6bc2a 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp @@ -124,7 +124,9 @@ namespace skyline::kernel::type { } catch (const std::exception &) { } auto chunk = state.os->memory.GetChunk(address); - munmap(reinterpret_cast(chunk->host), chunk->size); - state.os->memory.DeleteChunk(address); + if (chunk) { + munmap(reinterpret_cast(chunk->host), chunk->size); + state.os->memory.DeleteChunk(address); + } } }; diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp index dbefc216..0cdb99bb 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp @@ -211,7 +211,7 @@ namespace skyline::kernel::type { auto status = (*mtxWaiters.begin()); status->flag = true; lock.unlock(); - while(status->flag); + while (status->flag); lock.lock(); } return true; @@ -230,9 +230,9 @@ namespace skyline::kernel::type { } lock.unlock(); bool timedOut{}; - auto start = utils::GetCurrTimeNs(); + auto start = utils::GetTimeNs(); while (!status->flag) { - if ((utils::GetCurrTimeNs() - start) >= timeout) + if ((utils::GetTimeNs() - start) >= timeout) timedOut = true; } lock.lock(); @@ -298,7 +298,7 @@ namespace skyline::kernel::type { iter++; count++; condLock.unlock(); - while(thread->flag); + while (thread->flag); condLock.lock(); } } diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.h b/app/src/main/cpp/skyline/kernel/types/KProcess.h index 8a8c654c..30e36e91 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.h +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.h @@ -186,8 +186,8 @@ namespace skyline::kernel::type { * @note This can return a nullptr if the address is invalid */ template - inline Type* GetPointer(const u64 address) const { - return reinterpret_cast(GetHostAddress(address)); + inline Type *GetPointer(const u64 address) const { + return reinterpret_cast(GetHostAddress(address)); } /** diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp index f77310bc..8e23e364 100644 --- a/app/src/main/cpp/skyline/nce.cpp +++ b/app/src/main/cpp/skyline/nce.cpp @@ -93,6 +93,8 @@ namespace skyline { } void NCE::ExecuteFunction(ThreadCall call, Registers &funcRegs) { + if(state.process->status == kernel::type::KProcess::Status::Exiting) + throw exception("Executing function on Exiting process"); auto thread = state.thread ? state.thread : state.process->threads.at(state.process->pid); ExecuteFunctionCtx(call, funcRegs, reinterpret_cast(thread->ctxMemory->kernel.address)); } diff --git a/app/src/main/cpp/skyline/nce/guest.cpp b/app/src/main/cpp/skyline/nce/guest.cpp index 63226960..e9a0c670 100644 --- a/app/src/main/cpp/skyline/nce/guest.cpp +++ b/app/src/main/cpp/skyline/nce/guest.cpp @@ -278,8 +278,10 @@ namespace skyline::guest { .sa_sigaction = reinterpret_cast(reinterpret_cast(signalHandler)), .sa_flags = SA_SIGINFO, }; + /* for (int signal : {SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV}) sigaction(signal, &sigact, nullptr); + */ ctx->state = ThreadState::Running; asm("MOV LR, %0\n\t" "MOV X0, %1\n\t"