mirror of
				https://github.com/N64Recomp/N64ModernRuntime.git
				synced 2025-10-30 08:02:29 +00:00 
			
		
		
		
	Remove "permanent" and "temporary" threads tagging and add a way to name game threads (#45)
* System to specify thread types by the game * Register threads callbacks * Remove temporary and permanent threads * Fix `pthread_setname_np` not liking names longer than 16 bytes * Singular * Rename events_callbacks arg * Use `prctl` instead of `pthread_setname_np` for naming a thread * Fix typo
This commit is contained in:
		
							parent
							
								
									c91627740f
								
							
						
					
					
						commit
						27282afa2b
					
				
					 7 changed files with 76 additions and 43 deletions
				
			
		|  | @ -56,7 +56,8 @@ namespace recomp { | |||
|         const ultramodern::input::callbacks_t& input_callbacks, | ||||
|         const ultramodern::gfx_callbacks_t& gfx_callbacks, | ||||
|         const ultramodern::events::callbacks_t& events_callbacks, | ||||
|         const ultramodern::error_handling::callbacks_t& error_handling_callbacks_ | ||||
|         const ultramodern::error_handling::callbacks_t& error_handling_callbacks, | ||||
|         const ultramodern::threads::callbacks_t& threads_callbacks | ||||
|     ); | ||||
| 
 | ||||
| 	void start_game(const std::u8string& game_id); | ||||
|  |  | |||
|  | @ -381,7 +381,8 @@ void recomp::start( | |||
|     const ultramodern::input::callbacks_t& input_callbacks, | ||||
|     const ultramodern::gfx_callbacks_t& gfx_callbacks_, | ||||
|     const ultramodern::events::callbacks_t& events_callbacks, | ||||
|     const ultramodern::error_handling::callbacks_t& error_handling_callbacks_ | ||||
|     const ultramodern::error_handling::callbacks_t& error_handling_callbacks, | ||||
|     const ultramodern::threads::callbacks_t& threads_callbacks | ||||
| ) { | ||||
|     recomp::check_all_stored_roms(); | ||||
| 
 | ||||
|  | @ -392,7 +393,7 @@ void recomp::start( | |||
|         .run_task = recomp::rsp::run_task, | ||||
|     }; | ||||
| 
 | ||||
|     ultramodern::set_callbacks(ultramodern_rsp_callbacks, renderer_callbacks, audio_callbacks, input_callbacks, gfx_callbacks_, events_callbacks, error_handling_callbacks_); | ||||
|     ultramodern::set_callbacks(ultramodern_rsp_callbacks, renderer_callbacks, audio_callbacks, input_callbacks, gfx_callbacks_, events_callbacks, error_handling_callbacks, threads_callbacks); | ||||
| 
 | ||||
|     ultramodern::gfx_callbacks_t gfx_callbacks = gfx_callbacks_; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
							
								
								
									
										29
									
								
								ultramodern/include/ultramodern/threads.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								ultramodern/include/ultramodern/threads.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| #ifndef __THREADS_HPP__ | ||||
| #define __THREADS_HPP__ | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "ultra64.h" | ||||
| 
 | ||||
| namespace ultramodern { | ||||
|     namespace threads { | ||||
|         struct callbacks_t { | ||||
|             using get_game_thread_name_t = std::string(const OSThread* t); | ||||
| 
 | ||||
|             /**
 | ||||
|              * Allows to specifying a custom name for each thread. Mainly for debugging purposes. | ||||
|              * | ||||
|              * For maximum cross-platform compatibility the returned name should be at most 15 bytes long (16 bytes including the null terminator). | ||||
|              * | ||||
|              * If this function is not provided then the thread id will be used as the name of the thread. | ||||
|              */ | ||||
|             get_game_thread_name_t *get_game_thread_name; | ||||
|         }; | ||||
| 
 | ||||
|         void set_callbacks(const callbacks_t& callbacks); | ||||
| 
 | ||||
|         std::string get_game_thread_name(const OSThread* t); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -9,13 +9,15 @@ | |||
| #undef MOODYCAMEL_DELETE_FUNCTION | ||||
| #define MOODYCAMEL_DELETE_FUNCTION = delete | ||||
| #include "lightweightsemaphore.h" | ||||
| 
 | ||||
| #include "ultra64.h" | ||||
| 
 | ||||
| #include "ultramodern/error_handling.hpp" | ||||
| #include "ultramodern/events.hpp" | ||||
| #include "ultramodern/input.hpp" | ||||
| #include "ultramodern/rsp.hpp" | ||||
| #include "ultramodern/renderer_context.hpp" | ||||
| #include "ultramodern/rsp.hpp" | ||||
| #include "ultramodern/threads.hpp" | ||||
| 
 | ||||
| struct UltraThreadContext { | ||||
|     std::thread host_thread; | ||||
|  | @ -58,8 +60,6 @@ void run_next_thread_and_wait(RDRAM_ARG1); | |||
| void resume_thread_and_wait(RDRAM_ARG OSThread* t); | ||||
| void schedule_running_thread(RDRAM_ARG PTR(OSThread) t); | ||||
| void cleanup_thread(UltraThreadContext* thread_context); | ||||
| uint32_t permanent_thread_count(); | ||||
| uint32_t temporary_thread_count(); | ||||
| struct thread_terminated : std::exception {}; | ||||
| 
 | ||||
| enum class ThreadPriority { | ||||
|  | @ -144,7 +144,8 @@ void set_callbacks( | |||
|     const input::callbacks_t& input_callbacks, | ||||
|     const gfx_callbacks_t& gfx_callbacks, | ||||
|     const events::callbacks_t& events_callbacks, | ||||
|     const error_handling::callbacks_t& error_handling_callbacks | ||||
|     const error_handling::callbacks_t& error_handling_callbacks, | ||||
|     const threads::callbacks_t& threads_callbacks | ||||
| ); | ||||
| } // namespace ultramodern
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,11 +7,26 @@ | |||
| #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; | ||||
| } | ||||
| 
 | ||||
| std::string ultramodern::threads::get_game_thread_name(const OSThread* t) { | ||||
|     if (threads_callbacks.get_game_thread_name == nullptr) { | ||||
|         return "Game Thread " + std::to_string(t->id); | ||||
|     } | ||||
|     return threads_callbacks.get_game_thread_name(t); | ||||
| } | ||||
| 
 | ||||
| extern "C" void bootproc(); | ||||
| 
 | ||||
| thread_local bool is_main_thread = false; | ||||
|  | @ -80,8 +95,15 @@ void ultramodern::set_native_thread_priority(ThreadPriority pri) { | |||
|     // SetThreadPriority(GetCurrentThread(), nPriority);
 | ||||
| } | ||||
| #elif defined(__linux__) | ||||
| #include <sys/prctl.h> | ||||
| 
 | ||||
| void ultramodern::set_native_thread_name(const std::string& name) { | ||||
|     pthread_setname_np(pthread_self(), name.c_str()); | ||||
|     if (name.length() > 15) { | ||||
|         // Linux only accepts up to 16 characters including the null terminator for a thread name.
 | ||||
|         debug_printf("[Thread] The thread name '%s' will be truncated to 15 characters", name.c_str()); | ||||
|     } | ||||
| 
 | ||||
|     prctl(PR_SET_NAME, name.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ultramodern::set_native_thread_priority(ThreadPriority pri) { | ||||
|  | @ -113,15 +135,17 @@ void ultramodern::set_native_thread_priority(ThreadPriority pri) { | |||
| } | ||||
| #elif defined(__APPLE__) | ||||
| void ultramodern::set_native_thread_name(const std::string& name) { | ||||
|     if (name.length() > 15) { | ||||
|         // Macs seem to only accept up to 16 characters including the null terminator for a thread name.
 | ||||
|         debug_printf("[Thread] The thread name '%s' will be truncated to 15 characters", name.c_str()); | ||||
|     } | ||||
| 
 | ||||
|     pthread_setname_np(name.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ultramodern::set_native_thread_priority(ThreadPriority pri) {} | ||||
| #endif | ||||
| 
 | ||||
| std::atomic_int temporary_threads = 0; | ||||
| std::atomic_int permanent_threads = 0; | ||||
| 
 | ||||
| void wait_for_resumed(RDRAM_ARG UltraThreadContext* thread_context) { | ||||
|     TO_PTR(OSThread, ultramodern::this_thread())->context->running.wait(); | ||||
|     // If this thread's context was replaced by another thread or deleted, destroy it again from its own context.
 | ||||
|  | @ -165,17 +189,9 @@ 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(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); | ||||
|     } | ||||
| 
 | ||||
|     // Signal the initialized semaphore to indicate that this thread can be started.
 | ||||
|     thread_context->initialized.signal(); | ||||
| 
 | ||||
|  | @ -206,19 +222,6 @@ 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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| uint32_t ultramodern::permanent_thread_count() { | ||||
|     return permanent_threads.load(); | ||||
| } | ||||
| 
 | ||||
| uint32_t ultramodern::temporary_thread_count() { | ||||
|     return temporary_threads.load(); | ||||
| } | ||||
| 
 | ||||
| extern "C" void osStartThread(RDRAM_ARG PTR(OSThread) t_) { | ||||
|  |  | |||
|  | @ -7,16 +7,18 @@ void ultramodern::set_callbacks( | |||
|     const audio_callbacks_t& audio_callbacks, | ||||
|     const input::callbacks_t& input_callbacks, | ||||
|     const gfx_callbacks_t& gfx_callbacks, | ||||
|     const events::callbacks_t& thread_callbacks, | ||||
|     const error_handling::callbacks_t& error_handling_callbacks | ||||
|     const events::callbacks_t& events_callbacks, | ||||
|     const error_handling::callbacks_t& error_handling_callbacks, | ||||
|     const threads::callbacks_t& threads_callbacks | ||||
| ) { | ||||
|     ultramodern::rsp::set_callbacks(rsp_callbacks); | ||||
|     ultramodern::renderer::set_callbacks(renderer_callbacks); | ||||
|     ultramodern::set_audio_callbacks(audio_callbacks); | ||||
|     ultramodern::input::set_callbacks(input_callbacks); | ||||
|     (void)gfx_callbacks; // nothing yet
 | ||||
|     ultramodern::events::set_callbacks(thread_callbacks); | ||||
|     ultramodern::events::set_callbacks(events_callbacks); | ||||
|     ultramodern::error_handling::set_callbacks(error_handling_callbacks); | ||||
|     ultramodern::threads::set_callbacks(threads_callbacks); | ||||
| } | ||||
| 
 | ||||
| void ultramodern::preinit(RDRAM_ARG ultramodern::renderer::WindowHandle window_handle) { | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Anghelo Carvajal
						Anghelo Carvajal