Fix Circular Queue Destructor + Memory Infos + Improve Priority Documentation

This commit is contained in:
◱ PixelyIon 2020-11-21 20:55:57 +05:30 committed by ◱ PixelyIon
parent 7167393e3c
commit a3dd759a1c
7 changed files with 34 additions and 33 deletions

View File

@ -21,19 +21,14 @@ namespace skyline {
std::condition_variable produceCondition; std::condition_variable produceCondition;
public: public:
inline CircularQueue(size_t size) : vector(size * sizeof(Type)) {} inline CircularQueue(size_t size) : vector((size + 1) * sizeof(Type)) {}
inline ~CircularQueue() { inline ~CircularQueue() {
ssize_t size{}; while (start != end) {
if (start < end) auto next{start + 1};
size = end - start; next = (next == reinterpret_cast<Type *>(vector.end().base())) ? reinterpret_cast<Type *>(vector.begin().base()) : next;
else std::destroy_at(next);
size = (reinterpret_cast<Type *>(vector.end().base()) - start) + (end - reinterpret_cast<Type *>(vector.begin().base())); start = next;
while (size--) {
std::destroy_at(start);
if (start + 1 == reinterpret_cast<Type *>(vector.end().base()))
start = reinterpret_cast<Type *>(vector.begin().base());
} }
} }

View File

@ -195,18 +195,18 @@ namespace skyline::kernel {
return std::nullopt; return std::nullopt;
} }
size_t MemoryManager::GetMemoryUsage() { size_t MemoryManager::GetUserMemoryUsage() {
std::shared_lock lock(mutex); std::shared_lock lock(mutex);
size_t size{}; size_t size{};
for (const auto &chunk : chunks) 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; 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); std::shared_lock lock(mutex);
constexpr size_t KMemoryBlockSize{0x40}; constexpr size_t KMemoryBlockSize{0x40};
return util::AlignUp(chunks.size() * KMemoryBlockSize, PAGE_SIZE); return std::min(static_cast<size_t>(state.process->npdm.meta.systemResourceSize), util::AlignUp(chunks.size() * KMemoryBlockSize, PAGE_SIZE));
} }
} }

View File

@ -240,14 +240,15 @@ namespace skyline {
std::optional<ChunkDescriptor> Get(void *ptr); std::optional<ChunkDescriptor> 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 * @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();
}; };
} }
} }

View File

@ -13,15 +13,19 @@ namespace skyline {
namespace kernel { namespace kernel {
using CoreMask = std::bitset<constant::CoreCount>; using CoreMask = std::bitset<constant::CoreCount>;
/**
* @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 { struct Priority {
u8 min; u8 min; //!< Numerically lowest priority, highest scheduler priority
u8 max; 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 { constexpr u64 Mask() const {
u64 mask{}; return (std::numeric_limits<u64>::max() >> ((std::numeric_limits<u64>::digits - 1 + min) - max)) << min;
for (u8 i{min}; i <= max; i++)
mask |= 1 << i;
return mask;
} }
constexpr bool Valid(i8 value) const { constexpr bool Valid(i8 value) const {

View File

@ -367,7 +367,7 @@ namespace skyline::kernel::svc {
} }
auto processMask{state.process->npdm.threadInfo.coreMask}; 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.logger->Warn("svcSetThreadCoreMask: 'affinityMask' invalid: {} (Process Mask: {})", affinityMask, processMask);
state.ctx->gpr.w0 = result::InvalidCoreId; state.ctx->gpr.w0 = result::InvalidCoreId;
return; return;
@ -790,11 +790,11 @@ namespace skyline::kernel::svc {
break; break;
case InfoState::TotalMemoryAvailable: case InfoState::TotalMemoryAvailable:
out = totalPhysicalMemory; out = std::min(totalPhysicalMemory, state.process->memory.heap.size);
break; break;
case InfoState::TotalMemoryUsage: case InfoState::TotalMemoryUsage:
out = state.process->memory.GetMemoryUsage() + state.process->memory.GetKMemoryBlockSize(); out = state.process->memory.GetUserMemoryUsage() + state.process->memory.GetSystemResourceUsage();
break; break;
case InfoState::RandomEntropy: case InfoState::RandomEntropy:
@ -823,7 +823,7 @@ namespace skyline::kernel::svc {
case InfoState::TotalSystemResourceUsage: 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) // 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<size_t>(state.process->npdm.meta.systemResourceSize), state.process->memory.GetKMemoryBlockSize()); out = state.process->memory.GetSystemResourceUsage();
break; break;
case InfoState::ProgramId: case InfoState::ProgramId:
@ -831,11 +831,11 @@ namespace skyline::kernel::svc {
break; break;
case InfoState::TotalMemoryAvailableWithoutSystemResource: 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; break;
case InfoState::TotalMemoryUsageWithoutSystemResource: case InfoState::TotalMemoryUsageWithoutSystemResource:
out = state.process->memory.GetMemoryUsage(); // Our regular estimates don't contain the system resources out = state.process->memory.GetUserMemoryUsage();
break; break;
case InfoState::UserExceptionContextAddr: case InfoState::UserExceptionContextAddr:

View File

@ -54,7 +54,7 @@ namespace skyline::vfs {
auto trailingOnes{__builtin_ctz(~capability.raw)}; auto trailingOnes{__builtin_ctz(~capability.raw)};
switch (trailingOnes) { switch (trailingOnes) {
case 3: case 3:
threadInfo.priority = kernel::Priority{capability.threadInfo.lowestPriority, capability.threadInfo.highestPriority}; threadInfo.priority = kernel::Priority{capability.threadInfo.highestPriority, capability.threadInfo.lowestPriority};
threadInfo.coreMask = {}; threadInfo.coreMask = {};
for (u8 core{capability.threadInfo.minCoreId}; core <= capability.threadInfo.maxCoreId; core++) for (u8 core{capability.threadInfo.minCoreId}; core <= capability.threadInfo.maxCoreId; core++)

View File

@ -81,11 +81,12 @@ namespace skyline {
union __attribute__((packed)) NpdmKernelCapability { union __attribute__((packed)) NpdmKernelCapability {
/** /**
* @url https://switchbrew.org/wiki/NPDM#ThreadInfo * @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)) { struct __attribute__((packed)) {
u8 pattern : 4; //!< 0b0111 u8 pattern : 4; //!< 0b0111
u8 highestPriority : 6;
u8 lowestPriority : 6; u8 lowestPriority : 6;
u8 highestPriority : 6;
u8 minCoreId : 8; u8 minCoreId : 8;
u8 maxCoreId : 8; u8 maxCoreId : 8;
} threadInfo; } threadInfo;