mirror of
https://github.com/skyline-emu/skyline.git
synced 2025-04-10 22:50:01 +03:00
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:
parent
694c8ef4e2
commit
003e9c5a01
@ -18,20 +18,18 @@ namespace skyline {
|
|||||||
|
|
||||||
void GroupMutex::lock(Group group) {
|
void GroupMutex::lock(Group group) {
|
||||||
auto none = Group::None;
|
auto none = Group::None;
|
||||||
if (flag == group) {
|
constexpr u64 timeout = 1000; // The timeout in ns
|
||||||
num++;
|
auto start = utils::GetTimeNs();
|
||||||
return;
|
while (next != group && !next.compare_exchange_weak(none, group)) {
|
||||||
}
|
if (flag == group && ((utils::GetTimeNs() - start) > timeout)) {
|
||||||
while (true) {
|
num++;
|
||||||
for (int i = 0; i < 1000; ++i) {
|
return;
|
||||||
if (flag.compare_exchange_weak(none, group)) {
|
|
||||||
num++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
asm volatile("yield");
|
|
||||||
}
|
}
|
||||||
sched_yield();
|
asm volatile("yield");
|
||||||
}
|
}
|
||||||
|
while (flag != group && !flag.compare_exchange_weak(none, group))
|
||||||
|
asm volatile("yield");
|
||||||
|
num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupMutex::unlock() {
|
void GroupMutex::unlock() {
|
||||||
@ -51,11 +49,11 @@ namespace skyline {
|
|||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
boolMap[elem->FindAttribute("name")->Value()] = elem->FindAttribute(
|
boolMap[elem->FindAttribute("name")->Value()] = elem->FindAttribute(
|
||||||
"value")->BoolValue();
|
"value")->BoolValue();
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
intMap[elem->FindAttribute("name")->Value()] = elem->FindAttribute(
|
intMap[elem->FindAttribute("name")->Value()] = elem->FindAttribute(
|
||||||
"value")->IntValue();
|
"value")->IntValue();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syslog(LOG_ALERT, "Settings type is missing: %s for %s", elem->Value(),
|
syslog(LOG_ALERT, "Settings type is missing: %s for %s", elem->Value(),
|
||||||
|
@ -100,12 +100,19 @@ namespace skyline {
|
|||||||
* @brief Returns the current time in nanoseconds
|
* @brief Returns the current time in nanoseconds
|
||||||
* @return The current time in nanoseconds
|
* @return The current time in nanoseconds
|
||||||
*/
|
*/
|
||||||
inline u64 GetCurrTimeNs() {
|
inline u64 GetTimeNs() {
|
||||||
return static_cast<u64>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
|
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
|
* @tparam Type The type of the values
|
||||||
* @param value The value to round up
|
* @param value The value to round up
|
||||||
* @param multiple The multiple to round up to (Should be a multiple of 2)
|
* @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
|
* @tparam TypeMul The type of the multiple
|
||||||
* @return The aligned value
|
* @return The aligned value
|
||||||
*/
|
*/
|
||||||
template <typename TypeVal, typename TypeMul>
|
template<typename TypeVal, typename TypeMul>
|
||||||
inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
|
inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
|
||||||
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
|
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
|
||||||
multiple--;
|
multiple--;
|
||||||
@ -128,7 +135,7 @@ namespace skyline {
|
|||||||
* @tparam TypeMul The type of the multiple
|
* @tparam TypeMul The type of the multiple
|
||||||
* @return The aligned value
|
* @return The aligned value
|
||||||
*/
|
*/
|
||||||
template <typename TypeVal, typename TypeMul>
|
template<typename TypeVal, typename TypeMul>
|
||||||
inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
|
inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
|
||||||
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
|
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
|
||||||
multiple--;
|
multiple--;
|
||||||
@ -207,6 +214,7 @@ namespace skyline {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<Group> flag = Group::None; //!< An atomic flag to hold which group holds the mutex
|
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
|
std::atomic<u8> num = 0; //!< An atomic u8 keeping track of how many users are holding the mutex
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ namespace skyline::kernel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::InitializeRegions(u64 address, u64 size, const memory::AddressSpaceType type) {
|
void MemoryManager::InitializeRegions(u64 address, u64 size, const memory::AddressSpaceType type) {
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case memory::AddressSpaceType::AddressSpace32Bit:
|
case memory::AddressSpaceType::AddressSpace32Bit:
|
||||||
throw exception("32-bit address spaces are not supported");
|
throw exception("32-bit address spaces are not supported");
|
||||||
case memory::AddressSpaceType::AddressSpace36Bit: {
|
case memory::AddressSpaceType::AddressSpace36Bit: {
|
||||||
@ -95,7 +95,7 @@ namespace skyline::kernel {
|
|||||||
base.size = 0xFF8000000;
|
base.size = 0xFF8000000;
|
||||||
code.address = base.address;
|
code.address = base.address;
|
||||||
code.size = 0x78000000;
|
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");
|
throw exception("Code mapping larger than 36-bit code region");
|
||||||
alias.address = code.address + code.size;
|
alias.address = code.address + code.size;
|
||||||
alias.size = 0x180000000;
|
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
|
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) {}
|
MemoryManager::MemoryManager(const DeviceState &state) : state(state) {}
|
||||||
@ -139,7 +139,7 @@ namespace skyline::kernel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memory::Region MemoryManager::GetRegion(memory::Regions region) {
|
memory::Region MemoryManager::GetRegion(memory::Regions region) {
|
||||||
switch(region) {
|
switch (region) {
|
||||||
case memory::Regions::Base:
|
case memory::Regions::Base:
|
||||||
return base;
|
return base;
|
||||||
case memory::Regions::Code:
|
case memory::Regions::Code:
|
||||||
|
@ -120,6 +120,7 @@ namespace skyline {
|
|||||||
*/
|
*/
|
||||||
union MemoryState {
|
union MemoryState {
|
||||||
constexpr MemoryState(const u32 value) : value(value) {};
|
constexpr MemoryState(const u32 value) : value(value) {};
|
||||||
|
|
||||||
constexpr MemoryState() : value(0) {};
|
constexpr MemoryState() : value(0) {};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -226,6 +227,7 @@ namespace skyline {
|
|||||||
|
|
||||||
namespace svc {
|
namespace svc {
|
||||||
void SetMemoryAttribute(DeviceState &state);
|
void SetMemoryAttribute(DeviceState &state);
|
||||||
|
|
||||||
void MapMemory(DeviceState &state);
|
void MapMemory(DeviceState &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +326,9 @@ namespace skyline {
|
|||||||
friend class type::KTransferMemory;
|
friend class type::KTransferMemory;
|
||||||
friend class type::KProcess;
|
friend class type::KProcess;
|
||||||
friend class loader::NroLoader;
|
friend class loader::NroLoader;
|
||||||
|
|
||||||
friend void svc::SetMemoryAttribute(DeviceState &state);
|
friend void svc::SetMemoryAttribute(DeviceState &state);
|
||||||
|
|
||||||
friend void svc::MapMemory(skyline::DeviceState &state);
|
friend void svc::MapMemory(skyline::DeviceState &state);
|
||||||
|
|
||||||
MemoryManager(const DeviceState &state);
|
MemoryManager(const DeviceState &state);
|
||||||
|
@ -377,7 +377,7 @@ namespace skyline::kernel::svc {
|
|||||||
}
|
}
|
||||||
auto timeout = state.ctx->registers.x3;
|
auto timeout = state.ctx->registers.x3;
|
||||||
state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout);
|
state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout);
|
||||||
auto start = utils::GetCurrTimeNs();
|
auto start = utils::GetTimeNs();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (state.thread->cancelSync) {
|
if (state.thread->cancelSync) {
|
||||||
state.thread->cancelSync = false;
|
state.thread->cancelSync = false;
|
||||||
@ -394,7 +394,7 @@ namespace skyline::kernel::svc {
|
|||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if ((utils::GetCurrTimeNs() - start) >= timeout) {
|
if ((utils::GetTimeNs() - start) >= timeout) {
|
||||||
state.logger->Debug("svcWaitSynchronization: Wait has timed out");
|
state.logger->Debug("svcWaitSynchronization: Wait has timed out");
|
||||||
state.ctx->registers.w0 = constant::status::Timeout;
|
state.ctx->registers.w0 = constant::status::Timeout;
|
||||||
return;
|
return;
|
||||||
|
@ -124,7 +124,9 @@ namespace skyline::kernel::type {
|
|||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
}
|
}
|
||||||
auto chunk = state.os->memory.GetChunk(address);
|
auto chunk = state.os->memory.GetChunk(address);
|
||||||
munmap(reinterpret_cast<void *>(chunk->host), chunk->size);
|
if (chunk) {
|
||||||
state.os->memory.DeleteChunk(address);
|
munmap(reinterpret_cast<void *>(chunk->host), chunk->size);
|
||||||
|
state.os->memory.DeleteChunk(address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -211,7 +211,7 @@ namespace skyline::kernel::type {
|
|||||||
auto status = (*mtxWaiters.begin());
|
auto status = (*mtxWaiters.begin());
|
||||||
status->flag = true;
|
status->flag = true;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
while(status->flag);
|
while (status->flag);
|
||||||
lock.lock();
|
lock.lock();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -230,9 +230,9 @@ namespace skyline::kernel::type {
|
|||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
bool timedOut{};
|
bool timedOut{};
|
||||||
auto start = utils::GetCurrTimeNs();
|
auto start = utils::GetTimeNs();
|
||||||
while (!status->flag) {
|
while (!status->flag) {
|
||||||
if ((utils::GetCurrTimeNs() - start) >= timeout)
|
if ((utils::GetTimeNs() - start) >= timeout)
|
||||||
timedOut = true;
|
timedOut = true;
|
||||||
}
|
}
|
||||||
lock.lock();
|
lock.lock();
|
||||||
@ -298,7 +298,7 @@ namespace skyline::kernel::type {
|
|||||||
iter++;
|
iter++;
|
||||||
count++;
|
count++;
|
||||||
condLock.unlock();
|
condLock.unlock();
|
||||||
while(thread->flag);
|
while (thread->flag);
|
||||||
condLock.lock();
|
condLock.lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,8 +186,8 @@ namespace skyline::kernel::type {
|
|||||||
* @note This can return a nullptr if the address is invalid
|
* @note This can return a nullptr if the address is invalid
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
inline Type* GetPointer(const u64 address) const {
|
inline Type *GetPointer(const u64 address) const {
|
||||||
return reinterpret_cast<Type*>(GetHostAddress(address));
|
return reinterpret_cast<Type *>(GetHostAddress(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,6 +93,8 @@ namespace skyline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NCE::ExecuteFunction(ThreadCall call, Registers &funcRegs) {
|
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);
|
auto thread = state.thread ? state.thread : state.process->threads.at(state.process->pid);
|
||||||
ExecuteFunctionCtx(call, funcRegs, reinterpret_cast<ThreadContext *>(thread->ctxMemory->kernel.address));
|
ExecuteFunctionCtx(call, funcRegs, reinterpret_cast<ThreadContext *>(thread->ctxMemory->kernel.address));
|
||||||
}
|
}
|
||||||
|
@ -278,8 +278,10 @@ namespace skyline::guest {
|
|||||||
.sa_sigaction = reinterpret_cast<void (*)(int, struct siginfo *, void *)>(reinterpret_cast<void *>(signalHandler)),
|
.sa_sigaction = reinterpret_cast<void (*)(int, struct siginfo *, void *)>(reinterpret_cast<void *>(signalHandler)),
|
||||||
.sa_flags = SA_SIGINFO,
|
.sa_flags = SA_SIGINFO,
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
for (int signal : {SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV})
|
for (int signal : {SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV})
|
||||||
sigaction(signal, &sigact, nullptr);
|
sigaction(signal, &sigact, nullptr);
|
||||||
|
*/
|
||||||
ctx->state = ThreadState::Running;
|
ctx->state = ThreadState::Running;
|
||||||
asm("MOV LR, %0\n\t"
|
asm("MOV LR, %0\n\t"
|
||||||
"MOV X0, %1\n\t"
|
"MOV X0, %1\n\t"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user