From b657d4adb5a8e32bc723ea95248ee43a02b5fe99 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 3 May 2018 23:58:25 -0600 Subject: [PATCH] ProcessManager: Implement core process management logic. --- include/stratosphere.hpp | 1 + include/stratosphere/hossynch.hpp | 120 +++++++++++++++++++++++ include/stratosphere/ievent.hpp | 2 +- include/stratosphere/systemevent.hpp | 2 +- include/stratosphere/waitablemanager.hpp | 5 +- source/waitablemanager.cpp | 13 ++- 6 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 include/stratosphere/hossynch.hpp diff --git a/include/stratosphere.hpp b/include/stratosphere.hpp index 2b460711..0b627440 100644 --- a/include/stratosphere.hpp +++ b/include/stratosphere.hpp @@ -10,6 +10,7 @@ #include "stratosphere/ievent.hpp" #include "stratosphere/systemevent.hpp" +#include "stratosphere/hossynch.hpp" #include "stratosphere/waitablemanager.hpp" diff --git a/include/stratosphere/hossynch.hpp b/include/stratosphere/hossynch.hpp new file mode 100644 index 00000000..6a1c6e32 --- /dev/null +++ b/include/stratosphere/hossynch.hpp @@ -0,0 +1,120 @@ +#pragma once +#include + +class HosMutex { + private: + Mutex m; + public: + HosMutex() { + mutexInit(&this->m); + } + + void Lock() { + mutexLock(&this->m); + } + + void Unlock() { + mutexUnlock(&this->m); + } + + bool TryLock() { + return mutexTryLock(&this->m); + } +}; + +class HosRecursiveMutex { + private: + RMutex m; + public: + HosRecursiveMutex() { + rmutexInit(&this->m); + } + + void Lock() { + rmutexLock(&this->m); + } + + void Unlock() { + rmutexUnlock(&this->m); + } + + bool TryLock() { + return rmutexTryLock(&this->m); + } +}; + +class HosCondVar { + private: + CondVar cv; + Mutex m; + public: + HosCondVar() { + mutexInit(&m); + condvarInit(&cv, &m); + } + + Result WaitTimeout(u64 timeout) { + return condvarWaitTimeout(&cv, timeout); + } + + Result Wait() { + return condvarWait(&cv); + } + + Result Wake(int num) { + return condvarWake(&cv, num); + } + + Result WakeOne() { + return condvarWakeOne(&cv); + } + + Result WakeAll() { + return condvarWakeAll(&cv); + } +}; + +class HosSemaphore { + private: + CondVar cv; + Mutex m; + u64 count; + public: + HosSemaphore() { + count = 0; + mutexInit(&m); + condvarInit(&cv, &m); + } + + HosSemaphore(u64 c) : count(c) { + mutexInit(&m); + condvarInit(&cv, &m); + } + + void Signal() { + mutexLock(&this->m); + count++; + condvarWakeOne(&cv); + mutexUnlock(&this->m); + } + + void Wait() { + mutexLock(&this->m); + while (!count) { + condvarWait(&cv); + } + count--; + mutexUnlock(&this->m); + } + + bool TryWait() { + mutexLock(&this->m); + bool success = false; + if (count) { + count--; + success = true; + } + mutexUnlock(&this->m); + return success; + } +}; diff --git a/include/stratosphere/ievent.hpp b/include/stratosphere/ievent.hpp index a8f4e46c..c30f11bb 100644 --- a/include/stratosphere/ievent.hpp +++ b/include/stratosphere/ievent.hpp @@ -6,7 +6,7 @@ typedef Result (*EventCallback)(Handle *handles, size_t num_handles, u64 timeout); -class IEvent : IWaitable { +class IEvent : public IWaitable { protected: std::vector handles; EventCallback callback; diff --git a/include/stratosphere/systemevent.hpp b/include/stratosphere/systemevent.hpp index 23d2139b..21545c5d 100644 --- a/include/stratosphere/systemevent.hpp +++ b/include/stratosphere/systemevent.hpp @@ -7,7 +7,7 @@ #define SYSTEMEVENT_INDEX_WAITHANDLE 0 #define SYSTEMEVENT_INDEX_SGNLHANDLE 1 -class SystemEvent : IEvent { +class SystemEvent : public IEvent { public: SystemEvent(EventCallback callback) : IEvent(0, callback) { Handle wait_h; diff --git a/include/stratosphere/waitablemanager.hpp b/include/stratosphere/waitablemanager.hpp index 0971c8b8..407c7c24 100644 --- a/include/stratosphere/waitablemanager.hpp +++ b/include/stratosphere/waitablemanager.hpp @@ -6,9 +6,9 @@ class WaitableManager { std::vector waitables; - u64 timeout; - + private: + void process_internal(bool break_on_timeout); public: WaitableManager(u64 t) : waitables(0), timeout(t) { } ~WaitableManager() { @@ -22,4 +22,5 @@ class WaitableManager { unsigned int get_num_signalable(); void add_waitable(IWaitable *waitable); void process(); + void process_until_timeout(); }; \ No newline at end of file diff --git a/source/waitablemanager.cpp b/source/waitablemanager.cpp index bc80e27e..eb272730 100644 --- a/source/waitablemanager.cpp +++ b/source/waitablemanager.cpp @@ -17,7 +17,7 @@ void WaitableManager::add_waitable(IWaitable *waitable) { this->waitables.push_back(waitable); } -void WaitableManager::process() { +void WaitableManager::process_internal(bool break_on_timeout) { std::vector signalables; std::vector handles; @@ -56,6 +56,9 @@ void WaitableManager::process() { for (auto & waitable : signalables) { waitable->update_priority(); } + if (break_on_timeout) { + return; + } } else if (rc != 0xF601) { /* TODO: Panic. When can this happen? */ } @@ -91,4 +94,12 @@ void WaitableManager::process() { } } } +} + +void WaitableManager::process() { + WaitableManager::process_internal(false); +} + +void WaitableManager::process_until_timeout() { + WaitableManager::process_internal(true); } \ No newline at end of file