mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-18 07:01:31 -07:00
eliminate bifurcated rw lock path based on exclusive mode; promote thread operations to base layer, use os layer as impl; first pass on moving file streaming layer to base layer's async wavefront
This commit is contained in:
+57
-12
@@ -2,18 +2,23 @@
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
global U64 global_update_tick_idx = 0;
|
||||
global CondVar async_tick_cond_var = {0};
|
||||
global Mutex async_tick_mutex = {0};
|
||||
global CondVar async_tick_start_cond_var = {0};
|
||||
global CondVar async_tick_stop_cond_var = {0};
|
||||
global Mutex async_tick_start_mutex = {0};
|
||||
global Mutex async_tick_stop_mutex = {0};
|
||||
global B32 global_async_exit = 0;
|
||||
|
||||
internal void
|
||||
main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
{
|
||||
ThreadNameF("main_thread");
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
ThreadNameF("[main thread]");
|
||||
|
||||
//- rjf: set up async thread group info
|
||||
async_tick_cond_var = cond_var_alloc();
|
||||
async_tick_mutex = mutex_alloc();
|
||||
async_tick_start_cond_var = cond_var_alloc();
|
||||
async_tick_start_mutex = mutex_alloc();
|
||||
async_tick_stop_cond_var = cond_var_alloc();
|
||||
async_tick_stop_mutex = mutex_alloc();
|
||||
|
||||
//- rjf: set up telemetry
|
||||
#if PROFILE_TELEMETRY
|
||||
@@ -29,7 +34,13 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
#endif
|
||||
|
||||
//- rjf: parse command line
|
||||
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments);
|
||||
String8List command_line_argument_strings = {0};
|
||||
{
|
||||
for EachIndex(idx, arguments_count)
|
||||
{
|
||||
str8_list_push(scratch.arena, &command_line_argument_strings, str8_cstring(arguments[idx]));
|
||||
}
|
||||
}
|
||||
CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings);
|
||||
|
||||
//- rjf: begin captures
|
||||
@@ -37,12 +48,9 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
if(capture)
|
||||
{
|
||||
ProfBeginCapture(arguments[0]);
|
||||
ProfMsg(BUILD_TITLE);
|
||||
}
|
||||
|
||||
#if PROFILE_TELEMETRY
|
||||
tmMessage(0, TMMF_ICON_NOTE, BUILD_TITLE);
|
||||
#endif
|
||||
|
||||
//- rjf: initialize all included layers
|
||||
#if defined(ASYNC_H) && !defined(ASYNC_INIT_MANUAL)
|
||||
async_init(&cmdline);
|
||||
@@ -96,9 +104,42 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
rd_init(&cmdline);
|
||||
#endif
|
||||
|
||||
//- rjf: launch async threads
|
||||
Thread *async_threads = 0;
|
||||
U64 async_threads_count = 0;
|
||||
{
|
||||
U64 num_main_threads = 1;
|
||||
#if defined(CTRL_CORE_H)
|
||||
num_main_threads += 1;
|
||||
#endif
|
||||
U64 num_async_threads = os_get_system_info()->logical_processor_count;
|
||||
U64 num_main_threads_clamped = Min(num_async_threads, num_main_threads);
|
||||
num_async_threads -= num_main_threads_clamped;
|
||||
num_async_threads = Max(1, num_async_threads);
|
||||
Barrier barrier = barrier_alloc(num_async_threads);
|
||||
LaneCtx *lane_ctxs = push_array(scratch.arena, LaneCtx, num_async_threads);
|
||||
async_threads_count = num_async_threads;
|
||||
async_threads = push_array(scratch.arena, Thread, async_threads_count);
|
||||
for EachIndex(idx, num_async_threads)
|
||||
{
|
||||
lane_ctxs[idx].lane_idx = idx;
|
||||
lane_ctxs[idx].lane_count = num_async_threads;
|
||||
lane_ctxs[idx].barrier = barrier;
|
||||
async_threads[idx] = thread_launch(async_thread_entry_point, &lane_ctxs[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: call into entry point
|
||||
entry_point(&cmdline);
|
||||
|
||||
//- rjf: join async threads
|
||||
ins_atomic_u32_inc_eval(&global_async_exit);
|
||||
cond_var_broadcast(async_tick_start_cond_var);
|
||||
for EachIndex(idx, async_threads_count)
|
||||
{
|
||||
thread_join(async_threads[idx], max_U64);
|
||||
}
|
||||
|
||||
//- rjf: end captures
|
||||
if(capture)
|
||||
{
|
||||
@@ -143,11 +184,15 @@ update(void)
|
||||
internal void
|
||||
async_thread_entry_point(void *params)
|
||||
{
|
||||
MutexScope(async_tick_mutex) for(;;)
|
||||
LaneCtx lctx = *(LaneCtx *)params;
|
||||
lane_ctx(lctx);
|
||||
ThreadNameF("async_thread_%I64u", lane_idx());
|
||||
for(;!ins_atomic_u32_eval(&global_async_exit);)
|
||||
{
|
||||
cond_var_wait(async_tick_cond_var, async_tick_mutex, max_U64);
|
||||
MutexScope(async_tick_start_mutex) cond_var_wait(async_tick_start_cond_var, async_tick_start_mutex, os_now_microseconds()+100000);
|
||||
#if defined(FILE_STREAM_H)
|
||||
fs_async_tick();
|
||||
#endif
|
||||
cond_var_broadcast(async_tick_stop_cond_var);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
#include "base_arena.c"
|
||||
#include "base_math.c"
|
||||
#include "base_strings.c"
|
||||
#include "base_sync.c"
|
||||
#include "base_threads.c"
|
||||
#include "base_thread_context.c"
|
||||
#include "base_command_line.c"
|
||||
#include "base_markup.c"
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include "base_arena.h"
|
||||
#include "base_math.h"
|
||||
#include "base_strings.h"
|
||||
#include "base_sync.h"
|
||||
#include "base_threads.h"
|
||||
#include "base_thread_context.h"
|
||||
#include "base_command_line.h"
|
||||
#include "base_markup.h"
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Functions
|
||||
|
||||
internal Thread
|
||||
thread_launch(ThreadEntryPointFunctionType *f, void *p)
|
||||
{
|
||||
Thread thread = os_thread_launch(f, p);
|
||||
return thread;
|
||||
}
|
||||
|
||||
internal B32
|
||||
thread_join(Thread thread, U64 endt_us)
|
||||
{
|
||||
B32 result = os_thread_join(thread, endt_us);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
thread_detach(Thread thread)
|
||||
{
|
||||
os_thread_detach(thread);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Synchronization Primitive Functions
|
||||
|
||||
@@ -15,20 +38,17 @@ internal void mutex_drop(Mutex mutex) {os_mutex_drop(mutex);}
|
||||
|
||||
internal RWMutex rw_mutex_alloc(void) {return os_rw_mutex_alloc();}
|
||||
internal void rw_mutex_release(RWMutex mutex) {os_rw_mutex_release(mutex);}
|
||||
internal void rw_mutex_take_r(RWMutex mutex) {os_rw_mutex_take_r(mutex);}
|
||||
internal void rw_mutex_drop_r(RWMutex mutex) {os_rw_mutex_drop_r(mutex);}
|
||||
internal void rw_mutex_take_w(RWMutex mutex) {os_rw_mutex_take_w(mutex);}
|
||||
internal void rw_mutex_drop_w(RWMutex mutex) {os_rw_mutex_drop_w(mutex);}
|
||||
internal void rw_mutex_take(RWMutex mutex, B32 write_mode) {os_rw_mutex_take(mutex, write_mode);}
|
||||
internal void rw_mutex_drop(RWMutex mutex, B32 write_mode) {os_rw_mutex_drop(mutex, write_mode);}
|
||||
|
||||
//- rjf: condition variables
|
||||
|
||||
internal CondVar cond_var_alloc(void) {return os_cond_var_alloc();}
|
||||
internal void cond_var_release(CondVar cv) {os_cond_var_release(cv);}
|
||||
internal B32 cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us) {return os_cond_var_wait(cv, mutex, endt_us);}
|
||||
internal B32 cond_var_wait_rw_r(CondVar cv, RWMutex mutex_rw, U64 endt_us) {return os_cond_var_wait_rw_r(cv, mutex_rw, endt_us);}
|
||||
internal B32 cond_var_wait_rw_w(CondVar cv, RWMutex mutex_rw, U64 endt_us) {return os_cond_var_wait_rw_w(cv, mutex_rw, endt_us);}
|
||||
internal void cond_var_signal(CondVar cv) {os_cond_var_signal(cv);}
|
||||
internal void cond_var_broadcast(CondVar cv) {os_cond_var_broadcast(cv);}
|
||||
internal CondVar cond_var_alloc(void) {return os_cond_var_alloc();}
|
||||
internal void cond_var_release(CondVar cv) {os_cond_var_release(cv);}
|
||||
internal B32 cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us) {return os_cond_var_wait(cv, mutex, endt_us);}
|
||||
internal B32 cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us) {return os_cond_var_wait_rw(cv, mutex_rw, write_mode, endt_us);}
|
||||
internal void cond_var_signal(CondVar cv) {os_cond_var_signal(cv);}
|
||||
internal void cond_var_broadcast(CondVar cv) {os_cond_var_broadcast(cv);}
|
||||
|
||||
//- rjf: cross-process semaphores
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_SYNC_H
|
||||
#define BASE_SYNC_H
|
||||
#ifndef BASE_THREADS_H
|
||||
#define BASE_THREADS_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Types
|
||||
|
||||
typedef struct Thread Thread;
|
||||
struct Thread
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
typedef void ThreadEntryPointFunctionType(void *p);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Synchronization Primitive Types
|
||||
@@ -37,6 +47,13 @@ struct Barrier
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Functions
|
||||
|
||||
internal Thread thread_launch(ThreadEntryPointFunctionType *f, void *p);
|
||||
internal B32 thread_join(Thread thread, U64 endt_us);
|
||||
internal void thread_detach(Thread thread);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Synchronization Primitive Functions
|
||||
|
||||
@@ -49,18 +66,21 @@ internal void mutex_drop(Mutex mutex);
|
||||
//- rjf: reader/writer mutexes
|
||||
internal RWMutex rw_mutex_alloc(void);
|
||||
internal void rw_mutex_release(RWMutex mutex);
|
||||
internal void rw_mutex_take_r(RWMutex mutex);
|
||||
internal void rw_mutex_drop_r(RWMutex mutex);
|
||||
internal void rw_mutex_take_w(RWMutex mutex);
|
||||
internal void rw_mutex_drop_w(RWMutex mutex);
|
||||
internal void rw_mutex_take(RWMutex mutex, B32 write_mode);
|
||||
internal void rw_mutex_drop(RWMutex mutex, B32 write_mode);
|
||||
#define rw_mutex_take_r(m) rw_mutex_take((m), (0))
|
||||
#define rw_mutex_take_w(m) rw_mutex_take((m), (1))
|
||||
#define rw_mutex_drop_r(m) rw_mutex_drop((m), (0))
|
||||
#define rw_mutex_drop_w(m) rw_mutex_drop((m), (1))
|
||||
|
||||
//- rjf: condition variables
|
||||
internal CondVar cond_var_alloc(void);
|
||||
internal void cond_var_release(CondVar cv);
|
||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||
internal B32 cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us);
|
||||
internal B32 cond_var_wait_rw_r(CondVar cv, RWMutex mutex_rw, U64 endt_us);
|
||||
internal B32 cond_var_wait_rw_w(CondVar cv, RWMutex mutex_rw, U64 endt_us);
|
||||
internal B32 cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us);
|
||||
#define cond_var_wait_rw_r(cv, m, endt) cond_var_wait_rw((cv), (m), (0), (endt))
|
||||
#define cond_var_wait_rw_w(cv, m, endt) cond_var_wait_rw((cv), (m), (1), (endt))
|
||||
internal void cond_var_signal(CondVar cv);
|
||||
internal void cond_var_broadcast(CondVar cv);
|
||||
|
||||
@@ -79,8 +99,9 @@ internal void barrier_wait(Barrier barrier);
|
||||
|
||||
//- rjf: scope macros
|
||||
#define MutexScope(mutex) DeferLoop(mutex_take(mutex), mutex_drop(mutex))
|
||||
#define RWMutexScope(mutex, write_mode) DeferLoop(rw_mutex_take((mutex), (write_mode)), rw_mutex_drop((mutex), (write_mode)))
|
||||
#define MutexScopeR(mutex) DeferLoop(rw_mutex_take_r(mutex), rw_mutex_drop_r(mutex))
|
||||
#define MutexScopeW(mutex) DeferLoop(rw_mutex_take_w(mutex), rw_mutex_drop_w(mutex))
|
||||
#define MutexScopeRWPromote(mutex) DeferLoop((rw_mutex_drop_r(mutex), rw_mutex_take_w(mutex)), (rw_mutex_drop_w(mutex), rw_mutex_take_r(mutex)))
|
||||
|
||||
#endif // BASE_SYNC_H
|
||||
#endif // BASE_THREADS_H
|
||||
Reference in New Issue
Block a user