diff options
Diffstat (limited to 'src/core/hle/kernel')
30 files changed, 568 insertions, 457 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 5c3c47acf..37eec4c84 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -4,12 +4,10 @@ #include "common/common_types.h" #include "common/logging/log.h" - -#include "core/memory.h" - #include "core/hle/hle.h" #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/thread.h" +#include "core/memory.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Kernel namespace @@ -28,7 +26,7 @@ SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { } ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, - u64 nanoseconds) { + u64 nanoseconds) { switch (type) { // Signal thread(s) waiting for arbitrate address... @@ -38,7 +36,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, ArbitrateAllThreads(address); } else { // Resume first N threads - for(int i = 0; i < value; i++) + for (int i = 0; i < value; i++) ArbitrateHighestPriorityThread(address); } break; @@ -55,8 +53,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, GetCurrentThread()->WakeAfterDelay(nanoseconds); } break; - case ArbitrationType::DecrementAndWaitIfLessThan: - { + case ArbitrationType::DecrementAndWaitIfLessThan: { s32 memory_value = Memory::Read32(address); if (memory_value < value) { // Only change the memory value if the thread should wait @@ -65,8 +62,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, } break; } - case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: - { + case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: { s32 memory_value = Memory::Read32(address); if (memory_value < value) { // Only change the memory value if the thread should wait @@ -79,17 +75,19 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, default: LOG_ERROR(Kernel, "unknown type=%d", type); - return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); + return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, + ErrorSummary::WrongArgument, ErrorLevel::Usage); } HLE::Reschedule(__func__); - // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep + // The calls that use a timeout seem to always return a Timeout error even if they did not put + // the thread to sleep if (type == ArbitrationType::WaitIfLessThanWithTimeout || type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { - return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, - ErrorSummary::StatusChanged, ErrorLevel::Info); + return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged, + ErrorLevel::Info); } return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 8f6a1a8df..6a7af93a9 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -5,7 +5,6 @@ #pragma once #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" // Address arbiters are an underlying kernel synchronization object that can be created/used via @@ -36,13 +35,19 @@ public: */ static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); - std::string GetTypeName() const override { return "Arbiter"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "Arbiter"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } - std::string name; ///< Name of address arbiter object (optional) + std::string name; ///< Name of address arbiter object (optional) ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 444ce8d45..aedc6f989 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include "common/assert.h" - #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/server_port.h" diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 480b6ddae..d28147718 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h @@ -5,9 +5,7 @@ #pragma once #include <string> - #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" namespace Kernel { @@ -17,16 +15,22 @@ class ServerPort; class ClientPort : public Object { public: friend class ServerPort; - std::string GetTypeName() const override { return "ClientPort"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "ClientPort"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::ClientPort; - HandleType GetHandleType() const override { return HANDLE_TYPE; } - - SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. - u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have - u32 active_sessions; ///< Number of currently open sessions to this port - std::string name; ///< Name of client port (optional) + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + + SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. + u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have + u32 active_sessions; ///< Number of currently open sessions to this port + std::string name; ///< Name of client port (optional) protected: ClientPort(); diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 2b7c6992a..1489c7002 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -2,14 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <map> #include <algorithm> +#include <map> #include <vector> - #include "common/assert.h" - -#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/event.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" namespace Kernel { diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 73d0da419..6fe74065d 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -5,7 +5,6 @@ #pragma once #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" namespace Kernel { @@ -16,7 +15,6 @@ enum class ResetType { Pulse, }; - class Event final : public WaitObject { public: /** @@ -26,16 +24,22 @@ public: */ static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); - std::string GetTypeName() const override { return "Event"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "Event"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::Event; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } - ResetType reset_type; ///< Current ResetType + ResetType reset_type; ///< Current ResetType - bool signaled; ///< Whether the event has already been signaled - std::string name; ///< Name of event (optional) + bool signaled; ///< Whether the event has already been signaled + std::string name; ///< Name of event (optional) bool ShouldWait() override; void Acquire() override; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 7a401a965..9a2c8ce05 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -3,10 +3,8 @@ // Refer to the license.txt file included. #include <algorithm> - #include "common/assert.h" #include "common/logging/log.h" - #include "core/hle/config_mem.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory.h" @@ -61,7 +59,8 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. // CTR-OS doesn't use generation 0, so skip straight to 1. - if (next_generation >= (1 << 15)) next_generation = 1; + if (next_generation >= (1 << 15)) + next_generation = 1; generations[slot] = generation; objects[slot] = std::move(obj); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 27ba3f912..0e95f7ff0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -4,16 +4,13 @@ #pragma once -#include <boost/smart_ptr/intrusive_ptr.hpp> - #include <algorithm> #include <array> #include <cstddef> #include <string> #include <vector> - +#include <boost/smart_ptr/intrusive_ptr.hpp> #include "common/common_types.h" - #include "core/hle/hle.h" #include "core/hle/result.h" @@ -23,37 +20,37 @@ class Thread; // TODO: Verify code const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, - ErrorSummary::OutOfResource, ErrorLevel::Temporary); + ErrorSummary::OutOfResource, ErrorLevel::Temporary); // TOOD: Verify code const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + ErrorSummary::InvalidArgument, ErrorLevel::Permanent); enum KernelHandle : Handle { - CurrentThread = 0xFFFF8000, - CurrentProcess = 0xFFFF8001, + CurrentThread = 0xFFFF8000, + CurrentProcess = 0xFFFF8001, }; enum class HandleType : u32 { - Unknown = 0, - - Session = 2, - Event = 3, - Mutex = 4, - SharedMemory = 5, - Redirection = 6, - Thread = 7, - Process = 8, - AddressArbiter = 9, - Semaphore = 10, - Timer = 11, - ResourceLimit = 12, - CodeSet = 13, - ClientPort = 14, - ServerPort = 15, + Unknown = 0, + + Session = 2, + Event = 3, + Mutex = 4, + SharedMemory = 5, + Redirection = 6, + Thread = 7, + Process = 8, + AddressArbiter = 9, + Semaphore = 10, + Timer = 11, + ResourceLimit = 12, + CodeSet = 13, + ClientPort = 14, + ServerPort = 15, }; enum { - DEFAULT_STACK_SIZE = 0x4000, + DEFAULT_STACK_SIZE = 0x4000, }; class Object : NonCopyable { @@ -61,10 +58,16 @@ public: virtual ~Object() {} /// Returns a unique identifier for the object. For debugging purposes only. - unsigned int GetObjectId() const { return object_id; } + unsigned int GetObjectId() const { + return object_id; + } - virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } - virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } + virtual std::string GetTypeName() const { + return "[BAD KERNEL OBJECT TYPE]"; + } + virtual std::string GetName() const { + return "[UNKNOWN KERNEL OBJECT]"; + } virtual Kernel::HandleType GetHandleType() const = 0; /** @@ -122,7 +125,6 @@ using SharedPtr = boost::intrusive_ptr<T>; /// Class that represents a Kernel object that a thread can be waiting on class WaitObject : public Object { public: - /** * Check if the current thread should wait until the object is available * @return True if the current thread should wait due to this object being unavailable @@ -247,8 +249,12 @@ private: */ static const size_t MAX_COUNT = 4096; - static u16 GetSlot(Handle handle) { return handle >> 15; } - static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } + static u16 GetSlot(Handle handle) { + return handle >> 15; + } + static u16 GetGeneration(Handle handle) { + return handle & 0x7FFF; + } /// Stores the Object referenced by the handle or null if the slot is empty. std::array<SharedPtr<Object>, MAX_COUNT> objects; diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 17ae87aef..e65fd5c41 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp @@ -6,12 +6,9 @@ #include <memory> #include <utility> #include <vector> - #include "audio_core/audio_core.h" - #include "common/common_types.h" #include "common/logging/log.h" - #include "core/hle/config_mem.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/vm_manager.h" @@ -31,7 +28,7 @@ static MemoryRegionInfo memory_regions[3]; static const u32 memory_region_sizes[8][3] = { // Old 3DS layouts {0x04000000, 0x02C00000, 0x01400000}, // 0 - { /* This appears to be unused. */ }, // 1 + {/* This appears to be unused. */}, // 1 {0x06000000, 0x00C00000, 0x01400000}, // 2 {0x05000000, 0x01C00000, 0x01400000}, // 3 {0x04800000, 0x02400000, 0x01400000}, // 4 @@ -95,7 +92,6 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { UNREACHABLE(); } } - } namespace Memory { @@ -110,9 +106,8 @@ struct MemoryArea { // We don't declare the IO regions in here since its handled by other means. static MemoryArea memory_areas[] = { - {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) + {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) }; - } void Init() { @@ -125,15 +120,21 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) { for (MemoryArea& area : memory_areas) { auto block = std::make_shared<std::vector<u8>>(area.size); - address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap(); + address_space + .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private) + .Unwrap(); } - auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, - (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); + auto cfg_mem_vma = address_space + .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem, + CONFIG_MEMORY_SIZE, MemoryState::Shared) + .MoveFrom(); address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); - auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, - (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); + auto shared_page_vma = address_space + .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page, + SHARED_PAGE_SIZE, MemoryState::Shared) + .MoveFrom(); address_space.Reprotect(shared_page_vma, VMAPermission::Read); AudioCore::AddAddressSpace(address_space); diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h index 091c1f89f..4e1856a41 100644 --- a/src/core/hle/kernel/memory.h +++ b/src/core/hle/kernel/memory.h @@ -5,9 +5,7 @@ #pragma once #include <memory> - #include "common/common_types.h" - #include "core/hle/kernel/process.h" namespace Kernel { @@ -25,7 +23,6 @@ struct MemoryRegionInfo { void MemoryInit(u32 mem_type); void MemoryShutdown(); MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); - } namespace Memory { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index edb97d324..736944bae 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -4,11 +4,8 @@ #include <map> #include <vector> - #include <boost/range/algorithm_ext/erase.hpp> - #include "common/assert.h" - #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/thread.h" diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 1746360e4..53c3dc1f1 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -5,9 +5,7 @@ #pragma once #include <string> - #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" namespace Kernel { @@ -24,15 +22,21 @@ public: */ static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); - std::string GetTypeName() const override { return "Mutex"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "Mutex"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::Mutex; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } - int lock_count; ///< Number of times the mutex has been acquired - std::string name; ///< Name of mutex (optional) - SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex + int lock_count; ///< Number of times the mutex has been acquired + std::string name; ///< Name of mutex (optional) + SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex bool ShouldWait() override; void Acquire() override; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 69302cc82..ba80fe7f8 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -3,11 +3,9 @@ // Refer to the license.txt file included. #include <memory> - #include "common/assert.h" #include "common/common_funcs.h" #include "common/logging/log.h" - #include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" @@ -60,7 +58,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { while (bits && index < svc_access_mask.size()) { svc_access_mask.set(index, bits & 1); - ++index; bits >>= 1; + ++index; + bits >>= 1; } } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF // Handle table size @@ -70,11 +69,11 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { flags.raw = descriptor & 0xFFFF; } else if ((type & 0xFFE) == 0xFF8) { // 0x001F // Mapped memory range - if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { + if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) { LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); continue; } - u32 end_desc = kernel_caps[i+1]; + u32 end_desc = kernel_caps[i + 1]; ++i; // Skip over the second descriptor on the next iteration AddressMapping mapping; @@ -107,23 +106,28 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { void Process::Run(s32 main_thread_priority, u32 stack_size) { memory_region = GetMemoryRegion(flags.memory_region); - auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { - auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, - segment.offset, segment.size, memory_state).Unwrap(); + auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, + MemoryState memory_state) { + auto vma = vm_manager + .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size, + memory_state) + .Unwrap(); vm_manager.Reprotect(vma, permissions); misc_memory_used += segment.size; memory_region->used += segment.size; }; // Map CodeSet segments - MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); - MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); - MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); + MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); + MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); + MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); // Allocate and map stack - vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, - std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked - ).Unwrap(); + vm_manager + .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, + std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, + MemoryState::Locked) + .Unwrap(); misc_memory_used += stack_size; memory_region->used += stack_size; @@ -143,7 +147,8 @@ VAddr Process::GetLinearHeapLimit() const { } ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { - if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { + if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || + target + size < target) { return ERR_INVALID_ADDRESS; } @@ -166,7 +171,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per } ASSERT(heap_end - heap_start == heap_memory->size()); - CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); + CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, + size, MemoryState::Private)); vm_manager.Reprotect(vma, perms); heap_used += size; @@ -176,7 +182,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per } ResultCode Process::HeapFree(VAddr target, u32 size) { - if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { + if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || + target + size < target) { return ERR_INVALID_ADDRESS; } @@ -185,7 +192,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { } ResultCode result = vm_manager.UnmapRange(target, size); - if (result.IsError()) return result; + if (result.IsError()) + return result; heap_used -= size; memory_region->used -= size; @@ -203,8 +211,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p target = heap_end; } - if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || - target > heap_end || target + size < target) { + if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end || + target + size < target) { return ERR_INVALID_ADDRESS; } @@ -220,7 +228,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the // same region. It is unknown if or how the 3DS kernel checks against this. size_t offset = target - GetLinearHeapBase(); - CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); + CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, + MemoryState::Continuous)); vm_manager.Reprotect(vma, perms); linear_heap_used += size; @@ -248,7 +257,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { } ResultCode result = vm_manager.UnmapRange(target, size); - if (result.IsError()) return result; + if (result.IsError()) + return result; linear_heap_used -= size; memory_region->used -= size; @@ -272,5 +282,4 @@ Kernel::Process::Process() {} Kernel::Process::~Process() {} SharedPtr<Process> g_current_process; - } diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index d781ef32c..b566950b0 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -8,12 +8,9 @@ #include <cstddef> #include <memory> #include <string> - #include <boost/container/static_vector.hpp> - #include "common/bit_field.h" #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/vm_manager.h" @@ -36,15 +33,18 @@ enum class MemoryRegion : u16 { union ProcessFlags { u16 raw; - BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. - BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set. - BitField< 2, 1, u16> allow_nonalphanum; - BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. - BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. - BitField< 5, 1, u16> allow_main_args; - BitField< 6, 1, u16> shared_device_mem; - BitField< 7, 1, u16> runnable_on_sleep; - BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process + BitField<0, 1, u16> + allow_debug; ///< Allows other processes to attach to and debug this process. + BitField<1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they + /// don't have allow_debug set. + BitField<2, 1, u16> allow_nonalphanum; + BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. + BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. + BitField<5, 1, u16> allow_main_args; + BitField<6, 1, u16> shared_device_mem; + BitField<7, 1, u16> runnable_on_sleep; + BitField<8, 4, MemoryRegion> + memory_region; ///< Default region for memory allocations for this process BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). }; @@ -54,11 +54,17 @@ struct MemoryRegionInfo; struct CodeSet final : public Object { static SharedPtr<CodeSet> Create(std::string name, u64 program_id); - std::string GetTypeName() const override { return "CodeSet"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "CodeSet"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::CodeSet; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } /// Name of the process std::string name; @@ -85,11 +91,17 @@ class Process final : public Object { public: static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); - std::string GetTypeName() const override { return "Process"; } - std::string GetName() const override { return codeset->name; } + std::string GetTypeName() const override { + return "Process"; + } + std::string GetName() const override { + return codeset->name; + } static const HandleType HANDLE_TYPE = HandleType::Process; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } static u32 next_process_id; @@ -124,7 +136,6 @@ public: */ void Run(s32 main_thread_priority, u32 stack_size); - /////////////////////////////////////////////////////////////////////////////////////////////// // Memory Management @@ -144,7 +155,8 @@ public: /// The Thread Local Storage area is allocated as processes create threads, /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part - /// holds the TLS for a specific thread. This vector contains which parts are in use for each page as a bitmask. + /// holds the TLS for a specific thread. This vector contains which parts are in use for each + /// page as a bitmask. /// This vector will grow as more pages are allocated for new threads. std::vector<std::bitset<8>> tls_slots; @@ -164,5 +176,4 @@ private: }; extern SharedPtr<Process> g_current_process; - } diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index 67dde08c2..253ab7045 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp @@ -3,9 +3,7 @@ // Refer to the license.txt file included. #include <cstring> - #include "common/logging/log.h" - #include "core/hle/kernel/resource_limit.h" namespace Kernel { @@ -23,70 +21,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { } SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { - switch (category) - { - case ResourceLimitCategory::APPLICATION: - case ResourceLimitCategory::SYS_APPLET: - case ResourceLimitCategory::LIB_APPLET: - case ResourceLimitCategory::OTHER: - return resource_limits[static_cast<u8>(category)]; - default: - LOG_CRITICAL(Kernel, "Unknown resource limit category"); - UNREACHABLE(); + switch (category) { + case ResourceLimitCategory::APPLICATION: + case ResourceLimitCategory::SYS_APPLET: + case ResourceLimitCategory::LIB_APPLET: + case ResourceLimitCategory::OTHER: + return resource_limits[static_cast<u8>(category)]; + default: + LOG_CRITICAL(Kernel, "Unknown resource limit category"); + UNREACHABLE(); } } s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { switch (resource) { - case COMMIT: - return current_commit; - case THREAD: - return current_threads; - case EVENT: - return current_events; - case MUTEX: - return current_mutexes; - case SEMAPHORE: - return current_semaphores; - case TIMER: - return current_timers; - case SHARED_MEMORY: - return current_shared_mems; - case ADDRESS_ARBITER: - return current_address_arbiters; - case CPU_TIME: - return current_cpu_time; - default: - LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); - UNIMPLEMENTED(); - return 0; + case COMMIT: + return current_commit; + case THREAD: + return current_threads; + case EVENT: + return current_events; + case MUTEX: + return current_mutexes; + case SEMAPHORE: + return current_semaphores; + case TIMER: + return current_timers; + case SHARED_MEMORY: + return current_shared_mems; + case ADDRESS_ARBITER: + return current_address_arbiters; + case CPU_TIME: + return current_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; } } s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { switch (resource) { - case COMMIT: - return max_commit; - case THREAD: - return max_threads; - case EVENT: - return max_events; - case MUTEX: - return max_mutexes; - case SEMAPHORE: - return max_semaphores; - case TIMER: - return max_timers; - case SHARED_MEMORY: - return max_shared_mems; - case ADDRESS_ARBITER: - return max_address_arbiters; - case CPU_TIME: - return max_cpu_time; - default: - LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); - UNIMPLEMENTED(); - return 0; + case COMMIT: + return max_commit; + case THREAD: + return max_threads; + case EVENT: + return max_events; + case MUTEX: + return max_mutexes; + case SEMAPHORE: + return max_semaphores; + case TIMER: + return max_timers; + case SHARED_MEMORY: + return max_shared_mems; + case ADDRESS_ARBITER: + return max_address_arbiters; + case CPU_TIME: + return max_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; } } @@ -149,8 +146,6 @@ void ResourceLimitsInit() { resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; } -void ResourceLimitsShutdown() { - -} +void ResourceLimitsShutdown() {} } // namespace diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h index 1b8249c74..6cdfbcf8d 100644 --- a/src/core/hle/kernel/resource_limit.h +++ b/src/core/hle/kernel/resource_limit.h @@ -5,29 +5,28 @@ #pragma once #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" namespace Kernel { enum class ResourceLimitCategory : u8 { APPLICATION = 0, - SYS_APPLET = 1, - LIB_APPLET = 2, - OTHER = 3 + SYS_APPLET = 1, + LIB_APPLET = 2, + OTHER = 3 }; enum ResourceTypes { - PRIORITY = 0, - COMMIT = 1, - THREAD = 2, - EVENT = 3, - MUTEX = 4, - SEMAPHORE = 5, - TIMER = 6, - SHARED_MEMORY = 7, - ADDRESS_ARBITER = 8, - CPU_TIME = 9, + PRIORITY = 0, + COMMIT = 1, + THREAD = 2, + EVENT = 3, + MUTEX = 4, + SEMAPHORE = 5, + TIMER = 6, + SHARED_MEMORY = 7, + ADDRESS_ARBITER = 8, + CPU_TIME = 9, }; class ResourceLimit final : public Object { @@ -44,11 +43,17 @@ public: */ static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); - std::string GetTypeName() const override { return "ResourceLimit"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "ResourceLimit"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } /** * Gets the current value for the specified resource. @@ -85,10 +90,12 @@ public: /// Max CPU time that the processes in this category can utilize s32 max_cpu_time = 0; - // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that - // APPLICATION resource limits should not be affected by the objects created by service modules. + // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind + // that APPLICATION resource limits should not be affected by the objects created by service + // modules. // Currently we have no way of distinguishing if a Create was called by the running application, - // or by a service module. Approach this once we have separated the service modules into their own processes + // or by a service module. Approach this once we have separated the service modules into their + // own processes /// Current memory that the processes in this category are using s32 current_commit = 0; diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 4b359ed07..bf7600780 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include "common/assert.h" - #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/thread.h" @@ -14,7 +13,7 @@ Semaphore::Semaphore() {} Semaphore::~Semaphore() {} ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, - std::string name) { + std::string name) { if (initial_count > max_count) return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 390f5e495..e01908a25 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -6,9 +6,7 @@ #include <queue> #include <string> - #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" namespace Kernel { @@ -23,17 +21,23 @@ public: * @return The created semaphore */ static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, - std::string name = "Unknown"); + std::string name = "Unknown"); - std::string GetTypeName() const override { return "Semaphore"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "Semaphore"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::Semaphore; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } - s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have - s32 available_count; ///< Number of free slots left in the semaphore - std::string name; ///< Name of semaphore (optional) + s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have + s32 available_count; ///< Number of free slots left in the semaphore + std::string name; ///< Name of semaphore (optional) bool ShouldWait() override; void Acquire() override; diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index fcc684a20..8e3ec8a14 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -3,9 +3,7 @@ // Refer to the license.txt file included. #include <tuple> - #include "common/assert.h" - #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/server_port.h" @@ -25,7 +23,9 @@ void ServerPort::Acquire() { ASSERT_MSG(!ShouldWait(), "object unavailable!"); } -std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { +std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair( + u32 max_sessions, std::string name) { + SharedPtr<ServerPort> server_port(new ServerPort); SharedPtr<ClientPort> client_port(new ClientPort); diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index e9c972ce6..fa9448ca0 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h @@ -6,9 +6,7 @@ #include <string> #include <tuple> - #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" namespace Kernel { @@ -23,17 +21,25 @@ public: * @param name Optional name of the ports * @return The created port tuple */ - static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); + static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair( + u32 max_sessions, std::string name = "UnknownPort"); - std::string GetTypeName() const override { return "ServerPort"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "ServerPort"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::ServerPort; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } - std::string name; ///< Name of port (optional) + std::string name; ///< Name of port (optional) - std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port + std::vector<SharedPtr<WaitObject>> + pending_sessions; ///< ServerSessions waiting to be accepted by the port bool ShouldWait() override; void Acquire() override; diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp index 0594967f8..8a2a7e3fd 100644 --- a/src/core/hle/kernel/session.cpp +++ b/src/core/hle/kernel/session.cpp @@ -9,5 +9,4 @@ namespace Kernel { Session::Session() {} Session::~Session() {} - } diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 8ec889967..ec025f732 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -5,10 +5,8 @@ #pragma once #include <string> - #include "common/assert.h" #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" #include "core/hle/result.h" @@ -19,12 +17,13 @@ namespace IPC { enum DescriptorType : u32 { // Buffer related desciptors types (mask : 0x0F) StaticBuffer = 0x02, - PXIBuffer = 0x04, + PXIBuffer = 0x04, MappedBuffer = 0x08, - // Handle related descriptors types (mask : 0x30, but need to check for buffer related descriptors first ) - CopyHandle = 0x00, - MoveHandle = 0x10, - CallingPid = 0x20, + // Handle related descriptors types (mask : 0x30, but need to check for buffer related + // descriptors first ) + CopyHandle = 0x00, + MoveHandle = 0x10, + CallingPid = 0x20, }; /** @@ -34,24 +33,28 @@ enum DescriptorType : u32 { * @param translate_params_size Size of the translate parameters in words. Up to 63. * @return The created IPC header. * - * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. + * Normal parameters are sent directly to the process while the translate parameters might go + * through modifications and checks by the kernel. * The translate parameters are described by headers generated with the IPC::*Desc functions. * - * @note While #normal_params is equivalent to the number of normal parameters, #translate_params_size includes the size occupied by the translate parameters headers. + * @note While #normal_params is equivalent to the number of normal parameters, + * #translate_params_size includes the size occupied by the translate parameters headers. */ -constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { - return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | (u32(translate_params_size) & 0x3F); +constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, + unsigned int translate_params_size) { + return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | + (u32(translate_params_size) & 0x3F); } union Header { u32 raw; - BitField< 0, 6, u32> translate_params_size; - BitField< 6, 6, u32> normal_params; + BitField<0, 6, u32> translate_params_size; + BitField<6, 6, u32> normal_params; BitField<16, 16, u32> command_id; }; inline Header ParseHeader(u32 header) { - return{ header }; + return {header}; } constexpr u32 MoveHandleDesc(u32 num_handles = 1) { @@ -80,27 +83,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) { union StaticBufferDescInfo { u32 raw; - BitField< 10, 4, u32> buffer_id; - BitField< 14, 18, u32> size; + BitField<10, 4, u32> buffer_id; + BitField<14, 18, u32> size; }; inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { - return{ desc }; + return {desc}; } /** * @brief Creates a header describing a buffer to be sent over PXI. * @param size Size of the buffer. Max 0x00FFFFFF. * @param buffer_id The Id of the buffer. Max 0xF. - * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have read-write access. + * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have + * read-write access. * @return The created PXI buffer header. * * The next value is a phys-address of a table located in the BASE memregion. */ inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { u32 type = PXIBuffer; - if (is_read_only) type |= 0x2; - return type | (size << 8) | ((buffer_id & 0xF) << 4); + if (is_read_only) + type |= 0x2; + return type | (size << 8) | ((buffer_id & 0xF) << 4); } enum MappedBufferPermissions { @@ -115,12 +120,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { union MappedBufferDescInfo { u32 raw; - BitField< 4, 28, u32> size; - BitField< 1, 2, MappedBufferPermissions> perms; + BitField<4, 28, u32> size; + BitField<1, 2, MappedBufferPermissions> perms; }; inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { - return{ desc }; + return {desc}; } inline DescriptorType GetDescriptorType(u32 descriptor) { @@ -153,7 +158,8 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of * @return Pointer to command buffer */ inline u32* GetCommandBuffer(const int offset = 0) { - return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + offset); + return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + + offset); } /** @@ -183,10 +189,14 @@ public: Session(); ~Session() override; - std::string GetTypeName() const override { return "Session"; } + std::string GetTypeName() const override { + return "Session"; + } static const HandleType HANDLE_TYPE = HandleType::Session; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } /** * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls @@ -205,5 +215,4 @@ public: ASSERT_MSG(!ShouldWait(), "object unavailable!"); } }; - } diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 6a22c8986..bc1560d12 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -3,20 +3,20 @@ // Refer to the license.txt file included. #include <cstring> - #include "common/logging/log.h" - -#include "core/memory.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/shared_memory.h" +#include "core/memory.h" namespace Kernel { SharedMemory::SharedMemory() {} SharedMemory::~SharedMemory() {} -SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, - MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { +SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, + MemoryPermission permissions, + MemoryPermission other_permissions, VAddr address, + MemoryRegion region, std::string name) { SharedPtr<SharedMemory> shared_memory(new SharedMemory); shared_memory->owner_process = owner_process; @@ -31,7 +31,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u MemoryRegionInfo* memory_region = GetMemoryRegion(region); auto& linheap_memory = memory_region->linear_heap_memory; - ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!"); + ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, + "Not enough space in region to allocate shared memory!"); shared_memory->backing_block = linheap_memory; shared_memory->backing_block_offset = linheap_memory->size(); @@ -39,7 +40,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u linheap_memory->insert(linheap_memory->end(), size, 0); memory_region->used += size; - shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; + shared_memory->linear_heap_phys_address = + Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; // Increase the amount of used linear heap memory for the owner process. if (shared_memory->owner_process != nullptr) { @@ -51,18 +53,20 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); } } else { - // TODO(Subv): What happens if an application tries to create multiple memory blocks pointing to the same address? + // TODO(Subv): What happens if an application tries to create multiple memory blocks + // pointing to the same address? auto& vm_manager = shared_memory->owner_process->vm_manager; // The memory is already available and mapped in the owner process. auto vma = vm_manager.FindVMA(address)->second; // Copy it over to our own storage - shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset, - vma.backing_block->data() + vma.offset + size); + shared_memory->backing_block = std::make_shared<std::vector<u8>>( + vma.backing_block->data() + vma.offset, vma.backing_block->data() + vma.offset + size); shared_memory->backing_block_offset = 0; // Unmap the existing pages vm_manager.UnmapRange(address, size); // Map our own block into the address space - vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared); + vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, + MemoryState::Shared); // Reprotect the block with the new permissions vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); } @@ -71,8 +75,11 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u return shared_memory; } -SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, - MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { +SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, + u32 offset, u32 size, + MemoryPermission permissions, + MemoryPermission other_permissions, + std::string name) { SharedPtr<SharedMemory> shared_memory(new SharedMemory); shared_memory->owner_process = nullptr; @@ -88,27 +95,31 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vecto } ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, - MemoryPermission other_permissions) { + MemoryPermission other_permissions) { - MemoryPermission own_other_permissions = target_process == owner_process ? this->permissions : this->other_permissions; + MemoryPermission own_other_permissions = + target_process == owner_process ? this->permissions : this->other_permissions; // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); } // Error out if the requested permissions don't match what the creator process allows. if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); } // Heap-backed memory blocks can not be mapped with other_permissions = DontCare if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); } // Error out if the provided permissions are not compatible with what the creator process needs. @@ -116,12 +127,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent); } // TODO(Subv): Check for the Shared Device Mem flag in the creator process. /*if (was_created_with_shared_device_mem && address != 0) { - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); }*/ // TODO(Subv): The same process that created a SharedMemory object @@ -144,23 +157,29 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi } // Map the memory block into the target process - auto result = target_process->vm_manager.MapMemoryBlock(target_address, backing_block, backing_block_offset, size, MemoryState::Shared); + auto result = target_process->vm_manager.MapMemoryBlock( + target_address, backing_block, backing_block_offset, size, MemoryState::Shared); if (result.Failed()) { - LOG_ERROR(Kernel, "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", - GetObjectId(), target_address, name.c_str()); + LOG_ERROR( + Kernel, + "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", + GetObjectId(), target_address, name.c_str()); return result.Code(); } - return target_process->vm_manager.ReprotectRange(target_address, size, ConvertPermissions(permissions)); + return target_process->vm_manager.ReprotectRange(target_address, size, + ConvertPermissions(permissions)); } ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { - // TODO(Subv): Verify what happens if the application tries to unmap an address that is not mapped to a SharedMemory. + // TODO(Subv): Verify what happens if the application tries to unmap an address that is not + // mapped to a SharedMemory. return target_process->vm_manager.UnmapRange(address, size); } VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { - u32 masked_permissions = static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); + u32 masked_permissions = + static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); return static_cast<VMAPermission>(masked_permissions); }; diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 0c404a9f8..94b335ed1 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -5,9 +5,7 @@ #pragma once #include <string> - #include "common/common_types.h" - #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/result.h" @@ -16,15 +14,15 @@ namespace Kernel { /// Permissions for mapped shared memory blocks enum class MemoryPermission : u32 { - None = 0, - Read = (1u << 0), - Write = (1u << 1), - ReadWrite = (Read | Write), - Execute = (1u << 2), - ReadExecute = (Read | Execute), - WriteExecute = (Write | Execute), + None = 0, + Read = (1u << 0), + Write = (1u << 1), + ReadWrite = (Read | Write), + Execute = (1u << 2), + ReadExecute = (Read | Execute), + WriteExecute = (Write | Execute), ReadWriteExecute = (Read | Write | Execute), - DontCare = (1u << 28) + DontCare = (1u << 28) }; class SharedMemory final : public Object { @@ -34,13 +32,18 @@ public: * @param owner_process Process that created this shared memory object. * @param size Size of the memory block. Must be page-aligned. * @param permissions Permission restrictions applied to the process which created the block. - * @param other_permissions Permission restrictions applied to other processes mapping the block. + * @param other_permissions Permission restrictions applied to other processes mapping the + * block. * @param address The address from which to map the Shared Memory. - * @param region If the address is 0, the shared memory will be allocated in this region of the linear heap. + * @param region If the address is 0, the shared memory will be allocated in this region of the + * linear heap. * @param name Optional object name, used for debugging purposes. */ - static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, - MemoryPermission other_permissions, VAddr address = 0, MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown"); + static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, + MemoryPermission permissions, + MemoryPermission other_permissions, VAddr address = 0, + MemoryRegion region = MemoryRegion::BASE, + std::string name = "Unknown"); /** * Creates a shared memory object from a block of memory managed by an HLE applet. @@ -48,17 +51,27 @@ public: * @param offset The offset into the heap block that the SharedMemory will map. * @param size Size of the memory block. Must be page-aligned. * @param permissions Permission restrictions applied to the process which created the block. - * @param other_permissions Permission restrictions applied to other processes mapping the block. + * @param other_permissions Permission restrictions applied to other processes mapping the + * block. * @param name Optional object name, used for debugging purposes. */ - static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, - MemoryPermission permissions, MemoryPermission other_permissions, std::string name = "Unknown Applet"); - - std::string GetTypeName() const override { return "SharedMemory"; } - std::string GetName() const override { return name; } + static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, + u32 offset, u32 size, + MemoryPermission permissions, + MemoryPermission other_permissions, + std::string name = "Unknown Applet"); + + std::string GetTypeName() const override { + return "SharedMemory"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::SharedMemory; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } /** * Converts the specified MemoryPermission into the equivalent VMAPermission. @@ -73,7 +86,8 @@ public: * @param permissions Memory block map permissions (specified by SVC field) * @param other_permissions Memory block map other permissions (specified by SVC field) */ - ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); + ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, + MemoryPermission other_permissions); /** * Unmaps a shared memory block from the specified address in system memory @@ -94,7 +108,8 @@ public: SharedPtr<Process> owner_process; /// Address of shared memory block in the owner process if specified. VAddr base_address; - /// Physical address of the shared memory block in the linear heap if no address was specified during creation. + /// Physical address of the shared memory block in the linear heap if no address was specified + /// during creation. PAddr linear_heap_phys_address; /// Backing memory for this shared memory block. std::shared_ptr<std::vector<u8>> backing_block; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f1e5cf3cb..4486a812c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -5,23 +5,21 @@ #include <algorithm> #include <list> #include <vector> - #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" #include "common/math_util.h" #include "common/thread_queue_list.h" - #include "core/arm/arm_interface.h" #include "core/arm/skyeye_common/armstate.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/hle.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/thread.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/process.h" +#include "core/hle/kernel/thread.h" #include "core/hle/result.h" #include "core/memory.h" @@ -46,7 +44,7 @@ static Kernel::HandleTable wakeup_callback_handle_table; static std::vector<SharedPtr<Thread>> thread_list; // Lists only ready thread ids. -static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; +static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue; static Thread* current_thread; @@ -103,7 +101,7 @@ void Thread::Stop() { // Clean up thread from ready queue // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) - if (status == THREADSTATUS_READY){ + if (status == THREADSTATUS_READY) { ready_queue.remove(current_priority, this); } @@ -119,7 +117,8 @@ void Thread::Stop() { // Mark the TLS slot in the thread's page as free. u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; - u32 tls_slot = ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; + u32 tls_slot = + ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); HLE::Reschedule(__func__); @@ -137,7 +136,7 @@ Thread* ArbitrateHighestPriorityThread(u32 address) { if (thread == nullptr) continue; - if(thread->current_priority <= priority) { + if (thread->current_priority <= priority) { highest_priority_thread = thread.get(); priority = thread->current_priority; } @@ -170,7 +169,7 @@ static void PriorityBoostStarvedThreads() { // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler // should probably be reversed to verify this. - const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long + const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long u64 delta = current_ticks - thread->last_running_ticks; @@ -193,10 +192,12 @@ static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* threa if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { // svc #0x24 (WaitSynchronization1) - return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); + return std::make_tuple(&thread->context.cpu_registers[2], + &thread->context.cpu_registers[3]); } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { // svc #0x25 (WaitSynchronizationN) - return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); + return std::make_tuple(&thread->context.cpu_registers[0], + &thread->context.cpu_registers[4]); } UNREACHABLE(); @@ -245,7 +246,8 @@ static void SwitchContext(Thread* new_thread) { // Load context of new thread if (new_thread) { - DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); + DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, + "Thread must be ready to become running."); // Cancel any outstanding wakeup events for this thread CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); @@ -263,7 +265,7 @@ static void SwitchContext(Thread* new_thread) { new_thread->context.pc -= thumb_mode ? 2 : 4; // Get the register for timeout parameter - u32* timeout_low, *timeout_high; + u32 *timeout_low, *timeout_high; std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); // Update the timeout parameter @@ -307,7 +309,7 @@ static Thread* PopNextReadyThread() { // Otherwise just keep going with the current thread next = thread; } - } else { + } else { next = ready_queue.pop_first(); } @@ -321,7 +323,8 @@ void WaitCurrentThread_Sleep() { HLE::Reschedule(__func__); } -void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { +void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, + bool wait_set_output, bool wait_all) { Thread* thread = GetCurrentThread(); thread->wait_set_output = wait_set_output; thread->wait_all = wait_all; @@ -352,7 +355,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, - ErrorSummary::StatusChanged, ErrorLevel::Info)); + ErrorSummary::StatusChanged, + ErrorLevel::Info)); if (thread->wait_set_output) thread->SetWaitSynchronizationOutput(-1); @@ -372,25 +376,25 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { void Thread::ResumeFromWait() { switch (status) { - case THREADSTATUS_WAIT_SYNCH: - case THREADSTATUS_WAIT_ARB: - case THREADSTATUS_WAIT_SLEEP: - break; - - case THREADSTATUS_READY: - // If the thread is waiting on multiple wait objects, it might be awoken more than once - // before actually resuming. We can ignore subsequent wakeups if the thread status has - // already been set to THREADSTATUS_READY. - return; - - case THREADSTATUS_RUNNING: - DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); - return; - case THREADSTATUS_DEAD: - // This should never happen, as threads must complete before being stopped. - DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", - GetObjectId()); - return; + case THREADSTATUS_WAIT_SYNCH: + case THREADSTATUS_WAIT_ARB: + case THREADSTATUS_WAIT_SLEEP: + break; + + case THREADSTATUS_READY: + // If the thread is waiting on multiple wait objects, it might be awoken more than once + // before actually resuming. We can ignore subsequent wakeups if the thread status has + // already been set to THREADSTATUS_READY. + return; + + case THREADSTATUS_RUNNING: + DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); + return; + case THREADSTATUS_DEAD: + // This should never happen, as threads must complete before being stopped. + DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", + GetObjectId()); + return; } ready_queue.push_back(current_priority, this); @@ -405,7 +409,8 @@ static void DebugThreadQueue() { if (!thread) { LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); } else { - LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); + LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, + GetCurrentThread()->GetObjectId()); } for (auto& t : thread_list) { @@ -448,7 +453,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t * @param entry_point Address of entry point for execution * @param arg User argument for thread */ -static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { +static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, + u32 arg) { memset(&context, 0, sizeof(Core::ThreadContext)); context.cpu_registers[0] = arg; @@ -458,11 +464,11 @@ static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 } ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, - u32 arg, s32 processor_id, VAddr stack_top) { + u32 arg, s32 processor_id, VAddr stack_top) { if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); - LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", - name.c_str(), priority, new_priority); + LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", name.c_str(), + priority, new_priority); // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm // validity of this priority = new_priority; @@ -472,7 +478,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); // TODO: Verify error return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + ErrorSummary::InvalidArgument, ErrorLevel::Permanent); } SharedPtr<Thread> thread(new Thread); @@ -511,8 +517,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, auto& linheap_memory = memory_region->linear_heap_memory; if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { - LOG_ERROR(Kernel_SVC, "Not enough space in region to allocate a new TLS page for thread"); - return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Permanent); + LOG_ERROR(Kernel_SVC, + "Not enough space in region to allocate a new TLS page for thread"); + return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, + ErrorSummary::OutOfResource, ErrorLevel::Permanent); } u32 offset = linheap_memory->size(); @@ -537,7 +545,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, // Mark the slot as used tls_slots[available_page].set(available_slot); - thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; + thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + + available_slot * Memory::TLS_ENTRY_SIZE; // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used // to initialize the context @@ -551,10 +560,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, return MakeResult<SharedPtr<Thread>>(std::move(thread)); } -// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned. +// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be +// returned. static void ClampPriority(const Thread* thread, s32* priority) { if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { - DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); + DEBUG_ASSERT_MSG( + false, "Application passed an out of range priority. An error should be returned."); s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", @@ -586,12 +597,13 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { DEBUG_ASSERT(!GetCurrentThread()); // Initialize new "main" thread - auto thread_res = Thread::Create("main", entry_point, priority, 0, - THREADPROCESSORID_0, Memory::HEAP_VADDR_END); + auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, + Memory::HEAP_VADDR_END); SharedPtr<Thread> thread = thread_res.MoveFrom(); - thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 + thread->context.fpscr = + FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 // Run new "main" thread SwitchContext(thread.get()); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index deab5d5a6..f63131716 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -6,40 +6,36 @@ #include <string> #include <vector> - #include <boost/container/flat_set.hpp> - #include "common/common_types.h" - #include "core/core.h" - #include "core/hle/hle.h" #include "core/hle/kernel/kernel.h" #include "core/hle/result.h" -enum ThreadPriority : s32{ - THREADPRIO_HIGHEST = 0, ///< Highest thread priority - THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps - THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps - THREADPRIO_LOWEST = 63, ///< Lowest thread priority +enum ThreadPriority : s32 { + THREADPRIO_HIGHEST = 0, ///< Highest thread priority + THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps + THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps + THREADPRIO_LOWEST = 63, ///< Lowest thread priority }; enum ThreadProcessorId : s32 { - THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader - THREADPROCESSORID_ALL = -1, ///< Run thread on either core - THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) - THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) - THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this + THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader + THREADPROCESSORID_ALL = -1, ///< Run thread on either core + THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) + THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) + THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this }; enum ThreadStatus { - THREADSTATUS_RUNNING, ///< Currently running - THREADSTATUS_READY, ///< Ready to run - THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter - THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC - THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC - THREADSTATUS_DORMANT, ///< Created but not yet made ready - THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated + THREADSTATUS_RUNNING, ///< Currently running + THREADSTATUS_READY, ///< Ready to run + THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter + THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC + THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC + THREADSTATUS_DORMANT, ///< Created but not yet made ready + THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated }; namespace Kernel { @@ -60,13 +56,19 @@ public: * @return A shared pointer to the newly created thread */ static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, - u32 arg, s32 processor_id, VAddr stack_top); + u32 arg, s32 processor_id, VAddr stack_top); - std::string GetName() const override { return name; } - std::string GetTypeName() const override { return "Thread"; } + std::string GetName() const override { + return name; + } + std::string GetTypeName() const override { + return "Thread"; + } static const HandleType HANDLE_TYPE = HandleType::Thread; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } bool ShouldWait() override; void Acquire() override; @@ -75,7 +77,9 @@ public: * Gets the thread's current priority * @return The current thread's priority */ - s32 GetPriority() const { return current_priority; } + s32 GetPriority() const { + return current_priority; + } /** * Sets the thread's current priority @@ -93,7 +97,9 @@ public: * Gets the thread's thread ID * @return The thread's ID */ - u32 GetThreadId() const { return thread_id; } + u32 GetThreadId() const { + return thread_id; + } /** * Resumes a thread from waiting @@ -127,7 +133,9 @@ public: * Returns the Thread Local Storage address of the current thread * @returns VAddr of the thread's TLS */ - VAddr GetTLSAddress() const { return tls_address; } + VAddr GetTLSAddress() const { + return tls_address; + } Core::ThreadContext context; @@ -137,8 +145,8 @@ public: u32 entry_point; u32 stack_top; - s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application - s32 current_priority; ///< Current thread priority, can be temporarily changed + s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application + s32 current_priority; ///< Current thread priority, can be temporarily changed u64 last_running_ticks; ///< CPU tick when thread was last running @@ -151,11 +159,11 @@ public: /// Mutexes currently held by this thread, which will be released when it exits. boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; - SharedPtr<Process> owner_process; ///< Process that owns this thread + SharedPtr<Process> owner_process; ///< Process that owns this thread std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on - VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address - bool wait_all; ///< True if the thread is waiting on all objects before resuming - bool wait_set_output; ///< True if the output parameter should be set on thread wakeup + VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address + bool wait_all; ///< True if the thread is waiting on all objects before resuming + bool wait_set_output; ///< True if the output parameter should be set on thread wakeup std::string name; @@ -205,10 +213,12 @@ void WaitCurrentThread_Sleep(); /** * Waits the current thread from a WaitSynchronization call * @param wait_objects Kernel objects that we are waiting on - * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only) + * @param wait_set_output If true, set the output parameter on thread wakeup (for + * WaitSynchronizationN only) * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) */ -void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); +void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, + bool wait_set_output, bool wait_all); /** * Waits the current thread from an ArbitrateAddress call diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index b8daaeede..a9f98223c 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -3,14 +3,12 @@ // Refer to the license.txt file included. #include <cinttypes> - #include "common/assert.h" #include "common/logging/log.h" - #include "core/core_timing.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/timer.h" #include "core/hle/kernel/thread.h" +#include "core/hle/kernel/timer.h" namespace Kernel { @@ -41,7 +39,7 @@ bool Timer::ShouldWait() { } void Timer::Acquire() { - ASSERT_MSG( !ShouldWait(), "object unavailable!"); + ASSERT_MSG(!ShouldWait(), "object unavailable!"); if (reset_type == ResetType::OneShot) signaled = false; @@ -55,8 +53,8 @@ void Timer::Set(s64 initial, s64 interval) { interval_delay = interval; u64 initial_microseconds = initial / 1000; - CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), - timer_callback_event_type, callback_handle); + CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, + callback_handle); HLE::Reschedule(__func__); } @@ -73,7 +71,8 @@ void Timer::Clear() { /// The timer callback event, called when a timer is fired static void TimerCallback(u64 timer_handle, int cycles_late) { - SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); + SharedPtr<Timer> timer = + timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); if (timer == nullptr) { LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); @@ -91,7 +90,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { // Reschedule the timer with the interval delay u64 interval_microseconds = timer->interval_delay / 1000; CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, - timer_callback_event_type, timer_handle); + timer_callback_event_type, timer_handle); } } @@ -100,7 +99,6 @@ void TimersInit() { timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); } -void TimersShutdown() { -} +void TimersShutdown() {} } // namespace diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index b1db60e8f..59a77aad3 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -5,7 +5,6 @@ #pragma once #include "common/common_types.h" - #include "core/hle/kernel/event.h" #include "core/hle/kernel/kernel.h" @@ -21,19 +20,25 @@ public: */ static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); - std::string GetTypeName() const override { return "Timer"; } - std::string GetName() const override { return name; } + std::string GetTypeName() const override { + return "Timer"; + } + std::string GetName() const override { + return name; + } static const HandleType HANDLE_TYPE = HandleType::Timer; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } - ResetType reset_type; ///< The ResetType of this timer + ResetType reset_type; ///< The ResetType of this timer - bool signaled; ///< Whether the timer has been signaled or not - std::string name; ///< Name of timer (optional) + bool signaled; ///< Whether the timer has been signaled or not + std::string name; ///< Name of timer (optional) - u64 initial_delay; ///< The delay until the timer fires for the first time - u64 interval_delay; ///< The delay until the timer fires after the first time + u64 initial_delay; ///< The delay until the timer fires for the first time + u64 interval_delay; ///< The delay until the timer fires after the first time bool ShouldWait() override; void Acquire() override; diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 066146cff..6dd24f846 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -3,9 +3,7 @@ // Refer to the license.txt file included. #include <iterator> - #include "common/assert.h" - #include "core/hle/kernel/vm_manager.h" #include "core/memory.h" #include "core/memory_setup.h" @@ -15,8 +13,8 @@ namespace Kernel { static const char* GetMemoryStateName(MemoryState state) { static const char* names[] = { - "Free", "Reserved", "IO", "Static", "Code", "Private", "Shared", "Continuous", "Aliased", - "Alias", "AliasCode", "Locked", + "Free", "Reserved", "IO", "Static", "Code", "Private", + "Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked", }; return names[(int)state]; @@ -24,13 +22,12 @@ static const char* GetMemoryStateName(MemoryState state) { bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { ASSERT(base + size == next.base); - if (permissions != next.permissions || - meminfo_state != next.meminfo_state || - type != next.type) { + if (permissions != next.permissions || meminfo_state != next.meminfo_state || + type != next.type) { return false; } if (type == VMAType::AllocatedMemoryBlock && - (backing_block != next.backing_block || offset + size != next.offset)) { + (backing_block != next.backing_block || offset + size != next.offset)) { return false; } if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { @@ -70,7 +67,9 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { } ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, - std::shared_ptr<std::vector<u8>> block, size_t offset, u32 size, MemoryState state) { + std::shared_ptr<std::vector<u8>> block, + size_t offset, u32 size, + MemoryState state) { ASSERT(block != nullptr); ASSERT(offset + size <= block->size()); @@ -89,7 +88,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); } -ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { +ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size, + MemoryState state) { ASSERT(memory != nullptr); // This is the appropriately sized VMA that will turn into our allocation. @@ -106,7 +106,9 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); } -ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { +ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, + MemoryState state, + Memory::MMIORegionPointer mmio_handler) { // This is the appropriately sized VMA that will turn into our allocation. CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); VirtualMemoryArea& final_vma = vma_handle->second; @@ -191,15 +193,16 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) { void VMManager::LogLayout(Log::Level log_level) const { for (const auto& p : vma_map) { const VirtualMemoryArea& vma = p.second; - LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", - vma.base, vma.base + vma.size, vma.size, - (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', - (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', - (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', GetMemoryStateName(vma.meminfo_state)); + LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", vma.base, + vma.base + vma.size, vma.size, + (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', + (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', + (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', + GetMemoryStateName(vma.meminfo_state)); } } -VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { +VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) { // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given // non-const access to its container. return vma_map.erase(iter, iter); // Erases an empty range of elements @@ -337,5 +340,4 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { break; } } - } diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 91d40655b..9055664b2 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -7,21 +7,19 @@ #include <map> #include <memory> #include <vector> - #include "common/common_types.h" - #include "core/hle/result.h" #include "core/mmio.h" namespace Kernel { -const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 - ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage}; +const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5 + ErrorDescription::InvalidAddress, ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage}; -const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 - ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidState, ErrorLevel::Usage}; +const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5 + ErrorDescription::InvalidAddress, ErrorModule::OS, + ErrorSummary::InvalidState, ErrorLevel::Usage}; enum class VMAType : u8 { /// VMA represents an unmapped region of the address space. @@ -115,7 +113,8 @@ class VMManager final { // TODO(yuriks): Make page tables switchable to support multiple VMManagers public: /** - * The maximum amount of address space managed by the kernel. Addresses above this are never used. + * The maximum amount of address space managed by the kernel. Addresses above this are never + * used. * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. */ static const u32 MAX_ADDRESS = 0x40000000; @@ -151,7 +150,7 @@ public: * @param state MemoryState tag to attach to the VMA. */ ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, - size_t offset, u32 size, MemoryState state); + size_t offset, u32 size, MemoryState state); /** * Maps an unmanaged host memory pointer at a given address. @@ -172,7 +171,8 @@ public: * @param state MemoryState tag to attach to the VMA. * @param mmio_handler The handler that will implement read and write for this MMIO region. */ - ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); + ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, + Memory::MMIORegionPointer mmio_handler); /// Unmaps a range of addresses, splitting VMAs as necessary. ResultCode UnmapRange(VAddr target, u32 size); @@ -228,5 +228,4 @@ private: /// Updates the pages corresponding to this VMA so they match the VMA's attributes. void UpdatePageTableForVMA(const VirtualMemoryArea& vma); }; - } |