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.
This commit is contained in:
◱ PixelyIon 2020-02-06 00:07:45 +05:30 committed by ◱ PixelyIon
parent 694c8ef4e2
commit 003e9c5a01
10 changed files with 49 additions and 33 deletions

View File

@ -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)) {
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;
}
asm volatile("yield");
}
sched_yield();
}
while (flag != group && !flag.compare_exchange_weak(none, group))
asm volatile("yield");
num++;
}
void GroupMutex::unlock() {

View File

@ -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<u64>(std::chrono::duration_cast<std::chrono::nanoseconds>(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 <typename TypeVal, typename TypeMul>
template<typename TypeVal, typename TypeMul>
inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
multiple--;
@ -128,7 +135,7 @@ namespace skyline {
* @tparam TypeMul The type of the multiple
* @return The aligned value
*/
template <typename TypeVal, typename TypeMul>
template<typename TypeVal, typename TypeMul>
inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
multiple--;
@ -207,6 +214,7 @@ namespace skyline {
private:
std::atomic<Group> flag = Group::None; //!< An atomic flag to hold which group holds the mutex
std::atomic<Group> next = Group::None; //!< An atomic flag to hold which group will hold the mutex next
std::atomic<u8> num = 0; //!< An atomic u8 keeping track of how many users are holding the mutex
};

View File

@ -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;
@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -124,7 +124,9 @@ namespace skyline::kernel::type {
} catch (const std::exception &) {
}
auto chunk = state.os->memory.GetChunk(address);
if (chunk) {
munmap(reinterpret_cast<void *>(chunk->host), chunk->size);
state.os->memory.DeleteChunk(address);
}
}
};

View File

@ -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();
}
}

View File

@ -186,8 +186,8 @@ namespace skyline::kernel::type {
* @note This can return a nullptr if the address is invalid
*/
template<typename Type>
inline Type* GetPointer(const u64 address) const {
return reinterpret_cast<Type*>(GetHostAddress(address));
inline Type *GetPointer(const u64 address) const {
return reinterpret_cast<Type *>(GetHostAddress(address));
}
/**

View File

@ -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<ThreadContext *>(thread->ctxMemory->kernel.address));
}

View File

@ -278,8 +278,10 @@ namespace skyline::guest {
.sa_sigaction = reinterpret_cast<void (*)(int, struct siginfo *, void *)>(reinterpret_cast<void *>(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"