From 9a9585d0f97960a70513a4041358c599d4d3d1ae Mon Sep 17 00:00:00 2001 From: Angie Date: Fri, 31 May 2024 21:14:43 -0400 Subject: [PATCH] System to specify thread types by the game --- ultramodern/include/ultramodern/rsp.hpp | 8 +-- ultramodern/include/ultramodern/threads.hpp | 40 +++++++++++++++ ultramodern/src/threads.cpp | 54 ++++++++++++++++----- 3 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 ultramodern/include/ultramodern/threads.hpp diff --git a/ultramodern/include/ultramodern/rsp.hpp b/ultramodern/include/ultramodern/rsp.hpp index be1a85c..dda1b08 100644 --- a/ultramodern/include/ultramodern/rsp.hpp +++ b/ultramodern/include/ultramodern/rsp.hpp @@ -1,14 +1,10 @@ -#ifndef __RSP_STUFF_HPP__ -#define __RSP_STUFF_HPP__ - -// TODO: rename +#ifndef __RSP_HPP__ +#define __RSP_HPP__ #include #include "ultra64.h" -// TODO: Move these to ultramodern namespace? - namespace ultramodern { namespace rsp { struct callbacks_t { diff --git a/ultramodern/include/ultramodern/threads.hpp b/ultramodern/include/ultramodern/threads.hpp new file mode 100644 index 0000000..5f2a726 --- /dev/null +++ b/ultramodern/include/ultramodern/threads.hpp @@ -0,0 +1,40 @@ +#ifndef __THREADS_HPP__ +#define __THREADS_HPP__ + +#include + +#include "ultra64.h" + +namespace ultramodern { + namespace threads { + enum class GameThreadType { + Normal, + Temporary, + Permanent + }; + + struct callbacks_t { + using get_game_thread_type_t = GameThreadType(OSThread* t); + using get_game_thread_name_t = std::string(OSThread* t); + + /** + * TODO: document, I don't understand what this is used for. + */ + get_game_thread_type_t *get_game_thread_type; + + /** + * Allows specifying a custom name for each thread. + * + * If this function is not provided then the thread id will be used as the name. + */ + get_game_thread_name_t *get_game_thread_name; + }; + + void set_callbacks(const callbacks_t& callbacks); + + GameThreadType get_game_thread_type(OSThread* t); + std::string get_game_thread_name(OSThread* t); + } +} + +#endif diff --git a/ultramodern/src/threads.cpp b/ultramodern/src/threads.cpp index adb898a..14e244d 100644 --- a/ultramodern/src/threads.cpp +++ b/ultramodern/src/threads.cpp @@ -7,11 +7,33 @@ #include "ultramodern/ultramodern.hpp" #include "blockingconcurrentqueue.h" +#include "ultramodern/threads.hpp" + // Native APIs only used to set thread names for easier debugging #ifdef _WIN32 #include #endif +static ultramodern::threads::callbacks_t threads_callbacks; + +void ultramodern::threads::set_callbacks(const callbacks_t& callbacks) { + threads_callbacks = callbacks; +} + +ultramodern::threads::GameThreadType ultramodern::threads::get_game_thread_type(OSThread* t) { + if (threads_callbacks.get_game_thread_type == nullptr) { + return GameThreadType::Normal; + } + return threads_callbacks.get_game_thread_type(t); +} + +std::string ultramodern::threads::get_game_thread_name(OSThread* t) { + if (threads_callbacks.get_game_thread_name == nullptr) { + return std::to_string(t->id); + } + return threads_callbacks.get_game_thread_name(t); +} + extern "C" void bootproc(); thread_local bool is_main_thread = false; @@ -165,15 +187,18 @@ static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entry is_game_thread = true; // Set the thread name - ultramodern::set_native_thread_name("Game Thread " + std::to_string(self->id)); + ultramodern::set_native_thread_name("Game Thread " + ultramodern::threads::get_game_thread_name(self)); ultramodern::set_native_thread_priority(ultramodern::ThreadPriority::High); - // TODO fix these being hardcoded (this is only used for quicksaving) - if ((self->id == 2 && self->priority == 5) || self->id == 13) { // slowly, flashrom - temporary_threads.fetch_add(1); - } - else if (self->id != 1 && self->id != 2) { // ignore idle and fault - permanent_threads.fetch_add(1); + switch (ultramodern::threads::get_game_thread_type(self)) { + case ultramodern::threads::GameThreadType::Normal: + break; + case ultramodern::threads::GameThreadType::Temporary: + temporary_threads.fetch_add(1); + break; + case ultramodern::threads::GameThreadType::Permanent: + permanent_threads.fetch_add(1); + break; } // Signal the initialized semaphore to indicate that this thread can be started. @@ -183,7 +208,7 @@ static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entry // Wait until the thread is marked as running. wait_for_resumed(PASS_RDRAM thread_context); - + // Make sure the thread wasn't replaced or destroyed before it was started. if (self->context == thread_context) { debug_printf("[Thread] Thread started: %d\n", self->id); @@ -206,10 +231,15 @@ static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entry // Dispose of this thread now that it's completed or terminated. ultramodern::cleanup_thread(thread_context); - - // TODO fix these being hardcoded (this is only used for quicksaving) - if ((self->id == 2 && self->priority == 5) || self->id == 13) { // slowly, flashrom - temporary_threads.fetch_sub(1); + + switch (ultramodern::threads::get_game_thread_type(self)) { + case ultramodern::threads::GameThreadType::Normal: + break; + case ultramodern::threads::GameThreadType::Temporary: + temporary_threads.fetch_sub(1); + break; + case ultramodern::threads::GameThreadType::Permanent: + break; } }