diff --git a/app/src/main/cpp/skyline/common/circular_queue.h b/app/src/main/cpp/skyline/common/circular_queue.h index 9d8c878a..069f66f6 100644 --- a/app/src/main/cpp/skyline/common/circular_queue.h +++ b/app/src/main/cpp/skyline/common/circular_queue.h @@ -21,19 +21,14 @@ namespace skyline { std::condition_variable produceCondition; public: - inline CircularQueue(size_t size) : vector(size * sizeof(Type)) {} + inline CircularQueue(size_t size) : vector((size + 1) * sizeof(Type)) {} inline ~CircularQueue() { - ssize_t size{}; - if (start < end) - size = end - start; - else - size = (reinterpret_cast(vector.end().base()) - start) + (end - reinterpret_cast(vector.begin().base())); - - while (size--) { - std::destroy_at(start); - if (start + 1 == reinterpret_cast(vector.end().base())) - start = reinterpret_cast(vector.begin().base()); + while (start != end) { + auto next{start + 1}; + next = (next == reinterpret_cast(vector.end().base())) ? reinterpret_cast(vector.begin().base()) : next; + std::destroy_at(next); + start = next; } } diff --git a/app/src/main/cpp/skyline/kernel/memory.cpp b/app/src/main/cpp/skyline/kernel/memory.cpp index 88021455..9d1edb9d 100644 --- a/app/src/main/cpp/skyline/kernel/memory.cpp +++ b/app/src/main/cpp/skyline/kernel/memory.cpp @@ -195,18 +195,18 @@ namespace skyline::kernel { return std::nullopt; } - size_t MemoryManager::GetMemoryUsage() { + size_t MemoryManager::GetUserMemoryUsage() { std::shared_lock lock(mutex); size_t size{}; for (const auto &chunk : chunks) - if (chunk.state != memory::states::Unmapped && chunk.state != memory::states::Reserved) + if (chunk.state == memory::states::Heap) size += chunk.size; - return size; + return size + code.size + state.process->mainThreadStack->size; } - size_t MemoryManager::GetKMemoryBlockSize() { + size_t MemoryManager::GetSystemResourceUsage() { std::shared_lock lock(mutex); constexpr size_t KMemoryBlockSize{0x40}; - return util::AlignUp(chunks.size() * KMemoryBlockSize, PAGE_SIZE); + return std::min(static_cast(state.process->npdm.meta.systemResourceSize), util::AlignUp(chunks.size() * KMemoryBlockSize, PAGE_SIZE)); } } diff --git a/app/src/main/cpp/skyline/kernel/memory.h b/app/src/main/cpp/skyline/kernel/memory.h index 47d17088..5a3501fb 100644 --- a/app/src/main/cpp/skyline/kernel/memory.h +++ b/app/src/main/cpp/skyline/kernel/memory.h @@ -240,14 +240,15 @@ namespace skyline { std::optional Get(void *ptr); /** - * @return The cumulative size of all memory mappings in bytes + * @return The cumulative size of all heap (Physical Memory + Process Heap) memory mappings, the code region and the main thread stack in bytes */ - size_t GetMemoryUsage(); + size_t GetUserMemoryUsage(); /** * @return The total page-aligned size used to store memory block metadata, if they were KMemoryBlocks rather than ChunkDescriptor + * @note There is a ceiling of SystemResourceSize as specified in the NPDM, this value will be clipped to that */ - size_t GetKMemoryBlockSize(); + size_t GetSystemResourceUsage(); }; } } diff --git a/app/src/main/cpp/skyline/kernel/scheduler.h b/app/src/main/cpp/skyline/kernel/scheduler.h index f8cd4206..6ad63db6 100644 --- a/app/src/main/cpp/skyline/kernel/scheduler.h +++ b/app/src/main/cpp/skyline/kernel/scheduler.h @@ -13,15 +13,19 @@ namespace skyline { namespace kernel { using CoreMask = std::bitset; + /** + * @brief Priority on HOS determines scheduling behavior relative to other threads + * @note Lower priority values result in a higher priority, similar to niceness on Linux + */ struct Priority { - u8 min; - u8 max; + u8 min; //!< Numerically lowest priority, highest scheduler priority + u8 max; //!< Numerically highest priority, lowest scheduler priority + /** + * @return A bitmask with each bit corresponding to if scheduler priority with the same index is valid + */ constexpr u64 Mask() const { - u64 mask{}; - for (u8 i{min}; i <= max; i++) - mask |= 1 << i; - return mask; + return (std::numeric_limits::max() >> ((std::numeric_limits::digits - 1 + min) - max)) << min; } constexpr bool Valid(i8 value) const { diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index 9014f030..04a16606 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -367,7 +367,7 @@ namespace skyline::kernel::svc { } auto processMask{state.process->npdm.threadInfo.coreMask}; - if ((processMask | affinityMask) == processMask) { + if ((processMask | affinityMask) != processMask) { state.logger->Warn("svcSetThreadCoreMask: 'affinityMask' invalid: {} (Process Mask: {})", affinityMask, processMask); state.ctx->gpr.w0 = result::InvalidCoreId; return; @@ -790,11 +790,11 @@ namespace skyline::kernel::svc { break; case InfoState::TotalMemoryAvailable: - out = totalPhysicalMemory; + out = std::min(totalPhysicalMemory, state.process->memory.heap.size); break; case InfoState::TotalMemoryUsage: - out = state.process->memory.GetMemoryUsage() + state.process->memory.GetKMemoryBlockSize(); + out = state.process->memory.GetUserMemoryUsage() + state.process->memory.GetSystemResourceUsage(); break; case InfoState::RandomEntropy: @@ -823,7 +823,7 @@ namespace skyline::kernel::svc { case InfoState::TotalSystemResourceUsage: // A very rough approximation of what this should be on the Switch, the amount of memory allocated for storing the memory blocks (https://switchbrew.org/wiki/Kernel_objects#KMemoryBlockManager) - out = std::min(static_cast(state.process->npdm.meta.systemResourceSize), state.process->memory.GetKMemoryBlockSize()); + out = state.process->memory.GetSystemResourceUsage(); break; case InfoState::ProgramId: @@ -831,11 +831,11 @@ namespace skyline::kernel::svc { break; case InfoState::TotalMemoryAvailableWithoutSystemResource: - out = totalPhysicalMemory - state.process->npdm.meta.systemResourceSize; + out = std::min(totalPhysicalMemory, state.process->memory.heap.size) - state.process->npdm.meta.systemResourceSize; break; case InfoState::TotalMemoryUsageWithoutSystemResource: - out = state.process->memory.GetMemoryUsage(); // Our regular estimates don't contain the system resources + out = state.process->memory.GetUserMemoryUsage(); break; case InfoState::UserExceptionContextAddr: diff --git a/app/src/main/cpp/skyline/vfs/npdm.cpp b/app/src/main/cpp/skyline/vfs/npdm.cpp index a7946a93..46c22e2c 100644 --- a/app/src/main/cpp/skyline/vfs/npdm.cpp +++ b/app/src/main/cpp/skyline/vfs/npdm.cpp @@ -54,7 +54,7 @@ namespace skyline::vfs { auto trailingOnes{__builtin_ctz(~capability.raw)}; switch (trailingOnes) { case 3: - threadInfo.priority = kernel::Priority{capability.threadInfo.lowestPriority, capability.threadInfo.highestPriority}; + threadInfo.priority = kernel::Priority{capability.threadInfo.highestPriority, capability.threadInfo.lowestPriority}; threadInfo.coreMask = {}; for (u8 core{capability.threadInfo.minCoreId}; core <= capability.threadInfo.maxCoreId; core++) diff --git a/app/src/main/cpp/skyline/vfs/npdm.h b/app/src/main/cpp/skyline/vfs/npdm.h index 947d483b..c66b8ca1 100644 --- a/app/src/main/cpp/skyline/vfs/npdm.h +++ b/app/src/main/cpp/skyline/vfs/npdm.h @@ -81,11 +81,12 @@ namespace skyline { union __attribute__((packed)) NpdmKernelCapability { /** * @url https://switchbrew.org/wiki/NPDM#ThreadInfo + * @note Priority field names are based on real scheduler priority (Lower value is higher priority) */ struct __attribute__((packed)) { u8 pattern : 4; //!< 0b0111 - u8 highestPriority : 6; u8 lowestPriority : 6; + u8 highestPriority : 6; u8 minCoreId : 8; u8 maxCoreId : 8; } threadInfo;