diff options
Diffstat (limited to 'src/core/hle/kernel/process.h')
-rw-r--r-- | src/core/hle/kernel/process.h | 167 |
1 files changed, 116 insertions, 51 deletions
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index e412e58aa..45eefb90e 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -11,11 +11,11 @@ #include <unordered_map> #include <vector> #include "common/common_types.h" -#include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/handle_table.h" -#include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/k_address_arbiter.h" +#include "core/hle/kernel/k_condition_variable.h" +#include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/process_capability.h" -#include "core/hle/kernel/synchronization_object.h" #include "core/hle/result.h" namespace Core { @@ -29,16 +29,13 @@ class ProgramMetadata; namespace Kernel { class KernelCore; -class ResourceLimit; -class Thread; +class KPageTable; +class KResourceLimit; +class KThread; class TLSPage; struct CodeSet; -namespace Memory { -class PageTable; -} - enum class MemoryRegion : u16 { APPLICATION = 1, SYSTEM = 2, @@ -63,7 +60,7 @@ enum class ProcessStatus { DebugBreak, }; -class Process final : public SynchronizationObject { +class Process final : public KSynchronizationObject { public: explicit Process(Core::System& system); ~Process() override; @@ -104,12 +101,12 @@ public: } /// Gets a reference to the process' page table. - Memory::PageTable& PageTable() { + KPageTable& PageTable() { return *page_table; } /// Gets const a reference to the process' page table. - const Memory::PageTable& PageTable() const { + const KPageTable& PageTable() const { return *page_table; } @@ -123,24 +120,30 @@ public: return handle_table; } - /// Gets a reference to the process' address arbiter. - AddressArbiter& GetAddressArbiter() { - return address_arbiter; + ResultCode SignalToAddress(VAddr address) { + return condition_var.SignalToAddress(address); + } + + ResultCode WaitForAddress(Handle handle, VAddr address, u32 tag) { + return condition_var.WaitForAddress(handle, address, tag); + } + + void SignalConditionVariable(u64 cv_key, int32_t count) { + return condition_var.Signal(cv_key, count); } - /// Gets a const reference to the process' address arbiter. - const AddressArbiter& GetAddressArbiter() const { - return address_arbiter; + ResultCode WaitConditionVariable(VAddr address, u64 cv_key, u32 tag, s64 ns) { + return condition_var.Wait(address, cv_key, tag, ns); } - /// Gets a reference to the process' mutex lock. - Mutex& GetMutex() { - return mutex; + ResultCode SignalAddressArbiter(VAddr address, Svc::SignalType signal_type, s32 value, + s32 count) { + return address_arbiter.SignalToAddress(address, signal_type, value, count); } - /// Gets a const reference to the process' mutex lock - const Mutex& GetMutex() const { - return mutex; + ResultCode WaitAddressArbiter(VAddr address, Svc::ArbitrationType arb_type, s32 value, + s64 timeout) { + return address_arbiter.WaitForAddress(address, arb_type, value, timeout); } /// Gets the address to the process' dedicated TLS region. @@ -164,13 +167,18 @@ public: } /// Gets the resource limit descriptor for this process - std::shared_ptr<ResourceLimit> GetResourceLimit() const; + std::shared_ptr<KResourceLimit> GetResourceLimit() const; /// Gets the ideal CPU core ID for this process - u8 GetIdealCore() const { + u8 GetIdealCoreId() const { return ideal_core; } + /// Checks if the specified thread priority is valid. + bool CheckThreadPriority(s32 prio) const { + return ((1ULL << prio) & GetPriorityMask()) != 0; + } + /// Gets the bitmask of allowed cores that this process' threads can run on. u64 GetCoreMask() const { return capabilities.GetCoreMask(); @@ -206,6 +214,14 @@ public: return is_64bit_process; } + [[nodiscard]] bool IsSuspended() const { + return is_suspended; + } + + void SetSuspended(bool suspended) { + is_suspended = suspended; + } + /// Gets the total running time of the process instance in ticks. u64 GetCPUTimeTicks() const { return total_process_running_time_ticks; @@ -226,6 +242,33 @@ public: ++schedule_count; } + void IncrementThreadCount(); + void DecrementThreadCount(); + + void SetRunningThread(s32 core, KThread* thread, u64 idle_count) { + running_threads[core] = thread; + running_thread_idle_counts[core] = idle_count; + } + + void ClearRunningThread(KThread* thread) { + for (size_t i = 0; i < running_threads.size(); ++i) { + if (running_threads[i] == thread) { + running_threads[i] = nullptr; + } + } + } + + [[nodiscard]] KThread* GetRunningThread(s32 core) const { + return running_threads[core]; + } + + bool ReleaseUserException(KThread* thread); + + [[nodiscard]] KThread* GetPinnedThread(s32 core_id) const { + ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); + return pinned_threads[core_id]; + } + /// Gets 8 bytes of random data for svcGetInfo RandomEntropy u64 GetRandomEntropy(std::size_t index) const { return random_entropy.at(index); @@ -246,26 +289,17 @@ public: u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const; /// Gets the list of all threads created with this process as their owner. - const std::list<const Thread*>& GetThreadList() const { + const std::list<const KThread*>& GetThreadList() const { return thread_list; } - /// Insert a thread into the condition variable wait container - void InsertConditionVariableThread(std::shared_ptr<Thread> thread); - - /// Remove a thread from the condition variable wait container - void RemoveConditionVariableThread(std::shared_ptr<Thread> thread); - - /// Obtain all condition variable threads waiting for some address - std::vector<std::shared_ptr<Thread>> GetConditionVariableThreads(VAddr cond_var_addr); - /// Registers a thread as being created under this process, /// adding it to this process' thread list. - void RegisterThread(const Thread* thread); + void RegisterThread(const KThread* thread); /// Unregisters a thread from this process, removing it /// from this process' thread list. - void UnregisterThread(const Thread* thread); + void UnregisterThread(const KThread* thread); /// Clears the signaled state of the process if and only if it's signaled. /// @@ -275,7 +309,7 @@ public: /// @pre The process must be in a signaled state. If this is called on a /// process instance that is not signaled, ERR_INVALID_STATE will be /// returned. - ResultCode ClearSignalState(); + ResultCode Reset(); /** * Loads process-specifics configuration info with metadata provided @@ -304,6 +338,17 @@ public: void LoadModule(CodeSet code_set, VAddr base_addr); + bool IsSignaled() const override; + + void Finalize() override {} + + void PinCurrentThread(); + void UnpinCurrentThread(); + + KLightLock& GetStateLock() { + return state_lock; + } + /////////////////////////////////////////////////////////////////////////////////////////////// // Thread-local storage management @@ -314,11 +359,19 @@ public: void FreeTLSRegion(VAddr tls_address); private: - /// Checks if the specified thread should wait until this process is available. - bool ShouldWait(const Thread* thread) const override; + void PinThread(s32 core_id, KThread* thread) { + ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); + ASSERT(thread != nullptr); + ASSERT(pinned_threads[core_id] == nullptr); + pinned_threads[core_id] = thread; + } - /// Acquires/locks this process for the specified thread if it's available. - void Acquire(Thread* thread) override; + void UnpinThread(s32 core_id, KThread* thread) { + ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); + ASSERT(thread != nullptr); + ASSERT(pinned_threads[core_id] == thread); + pinned_threads[core_id] = nullptr; + } /// Changes the process status. If the status is different /// from the current process status, then this will trigger @@ -329,7 +382,7 @@ private: ResultCode AllocateMainThreadStack(std::size_t stack_size); /// Memory manager for this process - std::unique_ptr<Memory::PageTable> page_table; + std::unique_ptr<KPageTable> page_table; /// Current status of the process ProcessStatus status{}; @@ -346,7 +399,7 @@ private: u32 system_resource_size = 0; /// Resource limit descriptor for this process - std::shared_ptr<ResourceLimit> resource_limit; + std::shared_ptr<KResourceLimit> resource_limit; /// The ideal CPU core for this process, threads are scheduled on this core by default. u8 ideal_core = 0; @@ -373,12 +426,12 @@ private: HandleTable handle_table; /// Per-process address arbiter. - AddressArbiter address_arbiter; + KAddressArbiter address_arbiter; /// The per-process mutex lock instance used for handling various /// forms of services, such as lock arbitration, and condition /// variable related facilities. - Mutex mutex; + KConditionVariable condition_var; /// Address indicating the location of the process' dedicated TLS region. VAddr tls_region_address = 0; @@ -387,10 +440,7 @@ private: std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; /// List of threads that are running with this process as their owner. - std::list<const Thread*> thread_list; - - /// List of threads waiting for a condition variable - std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> cond_var_threads; + std::list<const KThread*> thread_list; /// Address of the top of the main thread's stack VAddr main_thread_stack_top{}; @@ -410,6 +460,21 @@ private: /// Schedule count of this process s64 schedule_count{}; + bool is_signaled{}; + bool is_suspended{}; + + std::atomic<s32> num_created_threads{}; + std::atomic<u16> num_threads{}; + u16 peak_num_threads{}; + + std::array<KThread*, Core::Hardware::NUM_CPU_CORES> running_threads{}; + std::array<u64, Core::Hardware::NUM_CPU_CORES> running_thread_idle_counts{}; + std::array<KThread*, Core::Hardware::NUM_CPU_CORES> pinned_threads{}; + + KThread* exception_thread{}; + + KLightLock state_lock; + /// System context Core::System& system; }; |