diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index 13eb4ff52..2b460711e 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -7,6 +7,10 @@ #include "stratosphere/serviceserver.hpp" #include "stratosphere/managedportserver.hpp" #include "stratosphere/existingportserver.hpp" + +#include "stratosphere/ievent.hpp" +#include "stratosphere/systemevent.hpp" + #include "stratosphere/waitablemanager.hpp" #include "stratosphere/ipc_templating.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp new file mode 100644 index 000000000..a8f4e46c5 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp @@ -0,0 +1,68 @@ +#pragma once +#include +#include + +#include "iwaitable.hpp" + +typedef Result (*EventCallback)(Handle *handles, size_t num_handles, u64 timeout); + +class IEvent : IWaitable { + protected: + std::vector handles; + EventCallback callback; + + public: + IEvent(Handle wait_h, EventCallback callback) { + if (wait_h) { + this->handles.push_back(wait_h); + } + this->callback = callback; + } + + ~IEvent() { + for (auto &h : this->handles) { + svcCloseHandle(h); + } + } + + virtual Result signal_event() = 0; + + /* IWaitable */ + virtual unsigned int get_num_waitables() { + if (handles.size() > 0) { + return 1; + } + return 0; + } + + virtual void get_waitables(IWaitable **dst) { + if (handles.size() > 0) { + dst[0] = this; + } + } + + virtual void delete_child(IWaitable *child) { + /* TODO: Panic, an event can never be a parent. */ + } + + virtual Handle get_handle() { + if (handles.size() > 0) { + return this->handles[0]; + } + return 0; + } + + + virtual void handle_deferred() { + /* TODO: Panic, because we can never defer an event. */ + } + + virtual Result handle_signaled(u64 timeout) { + return this->callback(this->handles.data(), this->handles.size(), timeout); + } + + static Result PanicCallback(Handle *handles, size_t num_handles, u64 timeout) { + /* TODO: Panic. */ + return 0xCAFE; + } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp b/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp new file mode 100644 index 000000000..23d2139bb --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp @@ -0,0 +1,26 @@ +#pragma once +#include + +#include "iwaitable.hpp" +#include "ievent.hpp" + +#define SYSTEMEVENT_INDEX_WAITHANDLE 0 +#define SYSTEMEVENT_INDEX_SGNLHANDLE 1 + +class SystemEvent : IEvent { + public: + SystemEvent(EventCallback callback) : IEvent(0, callback) { + Handle wait_h; + Handle sig_h; + if (R_FAILED(svcCreateEvent(&wait_h, &sig_h))) { + /* TODO: Panic. */ + } + + this->handles.push_back(wait_h); + this->handles.push_back(sig_h); + } + + virtual Result signal_event() { + return svcSignalEvent(this->handles[SYSTEMEVENT_INDEX_SGNLHANDLE]); + } +}; \ No newline at end of file diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 561cc1459..2ea756504 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -83,10 +83,18 @@ void __appExit(void) { int main(int argc, char **argv) { + Thread process_track_thread = {0}; consoleDebugInit(debugDevice_SVC); /* Initialize and spawn the Process Tracking thread. */ ProcessTracking::Initialize(); + if (R_FAILED(threadCreate(&process_track_thread, &ProcessTracking::MainLoop, NULL, 0x4000, 0x15, 0))) { + /* TODO: Panic. */ + } + if (R_FAILED(threadStart(&process_track_thread))) { + /* TODO: Panic. */ + } + /* TODO: What's a good timeout value to use here? */ WaitableManager *server_manager = new WaitableManager(U64_MAX); diff --git a/stratosphere/pm/source/pm_process_track.cpp b/stratosphere/pm/source/pm_process_track.cpp index de76c4883..e4a442401 100644 --- a/stratosphere/pm/source/pm_process_track.cpp +++ b/stratosphere/pm/source/pm_process_track.cpp @@ -1,15 +1,92 @@ #include +#include #include "pm_process_track.hpp" +static SystemEvent *g_process_event = NULL; +static SystemEvent *g_debug_title_event = NULL; +static SystemEvent *g_debug_application_event = NULL; + +static const u64 g_memory_resource_limits[5][3] = { + {0x010D00000ULL, 0x0CD500000ULL, 0x021700000ULL}, + {0x01E100000ULL, 0x080000000ULL, 0x061800000ULL}, + {0x014800000ULL, 0x0CD500000ULL, 0x01DC00000ULL}, + {0x028D00000ULL, 0x133400000ULL, 0x023800000ULL}, + {0x028D00000ULL, 0x0CD500000ULL, 0x089700000ULL} +}; + +/* These are the limits for LimitableResources. */ +/* Memory, Threads, Events, TransferMemories, Sessions. */ +static u64 g_resource_limits[3][5] = { + {0x0, 0x1FC, 0x258, 0x80, 0x31A}, + {0x0, 0x60, 0x0, 0x20, 0x1}, + {0x0, 0x60, 0x0, 0x20, 0x5}, +}; + +static Handle g_resource_limit_handles[5] = {0}; + void ProcessTracking::Initialize() { /* TODO: Setup ResourceLimit values, create MainLoop thread. */ + g_process_event = new SystemEvent(&IEvent::PanicCallback); + g_debug_title_event = new SystemEvent(&IEvent::PanicCallback); + g_debug_application_event = new SystemEvent(&IEvent::PanicCallback); + + /* Get memory limits. */ + u64 memory_arrangement; + if (R_FAILED(splGetConfig(SplConfigItem_MemoryArrange, &memory_arrangement))) { + /* TODO: panic. */ + } + memory_arrangement &= 0x3F; + int memory_limit_type; + switch (memory_arrangement) { + case 2: + memory_limit_type = 1; + break; + case 3: + memory_limit_type = 2; + break; + case 17: + memory_limit_type = 3; + break; + case 18: + memory_limit_type = 4; + break; + default: + memory_limit_type = 0; + break; + } + for (unsigned int i = 0; i < 3; i++) { + g_resource_limits[i][0] = g_memory_resource_limits[memory_limit_type][i]; + } + + /* Create resource limits. */ + for (unsigned int i = 0; i < 3; i++) { + if (i > 0) { + if (R_FAILED(svcCreateResourceLimit(&g_resource_limit_handles[i]))) { + /* TODO: Panic. */ + } + } else { + u64 out = 0; + if (R_FAILED(svcGetInfo(&out, 9, 0, 0))) { + /* TODO: Panic. */ + } + g_resource_limit_handles[i] = (Handle)out; + } + for (unsigned int r = 0; r < 5; r++) { + if (R_FAILED(svcSetResourceLimitLimitValue(g_resource_limit_handles[i], r, g_resource_limits[i][r]))) { + /* TODO: Panic. */ + } + } + } } -void ProcessTracking::MainLoop() { +void ProcessTracking::MainLoop(void *arg) { /* TODO */ while (true) { /* PM, as a sysmodule, is basically just a while loop. */ + /* TODO: Properly implement this. */ + svcSleepThread(100000ULL); + /* This is that while loop. */ } } \ No newline at end of file diff --git a/stratosphere/pm/source/pm_process_track.hpp b/stratosphere/pm/source/pm_process_track.hpp index 4f43ff0ac..55f4f092f 100644 --- a/stratosphere/pm/source/pm_process_track.hpp +++ b/stratosphere/pm/source/pm_process_track.hpp @@ -4,5 +4,5 @@ class ProcessTracking { public: static void Initialize(); - static void MainLoop(); + static void MainLoop(void *arg); }; \ No newline at end of file