mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 08:15:29 +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) {
|
||||
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(),
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -124,7 +124,9 @@ namespace skyline::kernel::type {
|
||||
} catch (const std::exception &) {
|
||||
}
|
||||
auto chunk = state.os->memory.GetChunk(address);
|
||||
munmap(reinterpret_cast<void *>(chunk->host), chunk->size);
|
||||
state.os->memory.DeleteChunk(address);
|
||||
if (chunk) {
|
||||
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());
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user