System to specify thread types by the game

This commit is contained in:
Angie 2024-05-31 21:14:43 -04:00 committed by angie
parent c91627740f
commit 9a9585d0f9
3 changed files with 84 additions and 18 deletions

View file

@ -1,14 +1,10 @@
#ifndef __RSP_STUFF_HPP__
#define __RSP_STUFF_HPP__
// TODO: rename
#ifndef __RSP_HPP__
#define __RSP_HPP__
#include <cstdint>
#include "ultra64.h"
// TODO: Move these to ultramodern namespace?
namespace ultramodern {
namespace rsp {
struct callbacks_t {

View file

@ -0,0 +1,40 @@
#ifndef __THREADS_HPP__
#define __THREADS_HPP__
#include <string>
#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

View file

@ -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 <Windows.h>
#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;
}
}