mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-10 03:21:37 -07:00
first pass at more comprehensive async layer, for replacing task system & providing single mechanism for async work, which is currently done ad-hoc in various layers
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Top-Level Layer Initialization
|
||||
|
||||
internal void
|
||||
async_init(void)
|
||||
{
|
||||
Arena *arena = arena_alloc();
|
||||
async_shared = push_array(arena, ASYNC_Shared, 1);
|
||||
async_shared->arena = arena;
|
||||
async_shared->u2w_ring_size = MB(8);
|
||||
async_shared->u2w_ring_base = push_array_no_zero(arena, U8, async_shared->u2w_ring_size);
|
||||
async_shared->u2w_ring_mutex = os_mutex_alloc();
|
||||
async_shared->u2w_ring_cv = os_condition_variable_alloc();
|
||||
async_shared->work_threads_count = Max(1, os_get_system_info()->logical_processor_count-1);
|
||||
async_shared->work_threads = push_array(arena, OS_Handle, async_shared->work_threads_count);
|
||||
for EachIndex(idx, async_shared->work_threads_count)
|
||||
{
|
||||
async_shared->work_threads[idx] = os_thread_launch(async_work_thread__entry_point, (void *)idx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Top-Level Accessors
|
||||
|
||||
internal U64
|
||||
async_thread_count(void)
|
||||
{
|
||||
return async_shared->work_threads_count;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Work Kickoffs
|
||||
|
||||
internal B32
|
||||
async_push_work_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params)
|
||||
{
|
||||
B32 result = 0;
|
||||
ASYNC_Work work = {0};
|
||||
work.work_function = work_function;
|
||||
work.input = params->input;
|
||||
work.output = params->output;
|
||||
work.semaphore = params->semaphore;
|
||||
OS_MutexScope(async_shared->u2w_ring_mutex) for(;;)
|
||||
{
|
||||
U64 unconsumed_size = async_shared->u2w_ring_write_pos - async_shared->u2w_ring_read_pos;
|
||||
U64 available_size = async_shared->u2w_ring_size - unconsumed_size;
|
||||
if(available_size >= sizeof(work))
|
||||
{
|
||||
result = 1;
|
||||
if(!os_handle_match(params->semaphore, os_handle_zero()))
|
||||
{
|
||||
os_semaphore_take(params->semaphore, max_U64);
|
||||
}
|
||||
async_shared->u2w_ring_write_pos += ring_write_struct(async_shared->u2w_ring_base, async_shared->u2w_ring_size, async_shared->u2w_ring_write_pos, &work);
|
||||
break;
|
||||
}
|
||||
if(os_now_microseconds() >= params->endt_us)
|
||||
{
|
||||
break;
|
||||
}
|
||||
os_condition_variable_wait(async_shared->u2w_ring_cv, async_shared->u2w_ring_mutex, params->endt_us);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task-Based Work Helper
|
||||
|
||||
internal void
|
||||
async_task_list_push(Arena *arena, ASYNC_TaskList *list, ASYNC_Task t)
|
||||
{
|
||||
ASYNC_TaskNode *n = push_array(arena, ASYNC_TaskNode, 1);
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
n->v = t;
|
||||
list->count += 1;
|
||||
}
|
||||
|
||||
internal ASYNC_Task
|
||||
async_task_launch_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params)
|
||||
{
|
||||
ASYNC_Task task = {0};
|
||||
task.semaphore = os_semaphore_alloc(1, 1, str8_zero());
|
||||
ASYNC_WorkParams params_refined = {0};
|
||||
MemoryCopyStruct(¶ms_refined, params);
|
||||
params_refined.endt_us = max_U64;
|
||||
params_refined.semaphore = task.semaphore;
|
||||
if(params_refined.output == 0)
|
||||
{
|
||||
params_refined.output = &task.output;
|
||||
}
|
||||
async_push_work_(work_function, ¶ms_refined);
|
||||
return task;
|
||||
}
|
||||
|
||||
internal void *
|
||||
async_task_join(ASYNC_Task task)
|
||||
{
|
||||
os_semaphore_take(task.semaphore, max_U64);
|
||||
os_semaphore_release(task.semaphore);
|
||||
MemoryZeroStruct(&task.semaphore);
|
||||
void *result = (void *)ins_atomic_u64_eval(&task.output);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Work Thread Entry Point
|
||||
|
||||
internal void
|
||||
async_work_thread__entry_point(void *p)
|
||||
{
|
||||
U64 thread_idx = (U64)p;
|
||||
ThreadNameF("[async] work thread #%I64u", thread_idx);
|
||||
for(;;)
|
||||
{
|
||||
//- rjf: grab next work
|
||||
ASYNC_Work work = {0};
|
||||
OS_MutexScope(async_shared->u2w_ring_mutex) for(;;)
|
||||
{
|
||||
U64 unconsumed_size = async_shared->u2w_ring_write_pos - async_shared->u2w_ring_read_pos;
|
||||
if(unconsumed_size >= sizeof(work))
|
||||
{
|
||||
async_shared->u2w_ring_read_pos += ring_read_struct(async_shared->u2w_ring_base, async_shared->u2w_ring_size, async_shared->u2w_ring_read_pos, &work);
|
||||
break;
|
||||
}
|
||||
os_condition_variable_wait(async_shared->u2w_ring_cv, async_shared->u2w_ring_mutex, max_U64);
|
||||
}
|
||||
|
||||
//- rjf: run work
|
||||
void *work_out = work.work_function(thread_idx, work.input);
|
||||
|
||||
//- rjf: store output
|
||||
if(work.output != 0)
|
||||
{
|
||||
ins_atomic_u64_eval_assign((U64 *)work.output, (U64)work_out);
|
||||
}
|
||||
|
||||
//- rjf: release semaphore
|
||||
if(!os_handle_match(work.semaphore, os_handle_zero()))
|
||||
{
|
||||
os_semaphore_drop(work.semaphore);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef ASYNC_H
|
||||
#define ASYNC_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Work Function Type
|
||||
|
||||
#define ASYNC_WORK_SIG(name) void *name(U64 thread_idx, void *input)
|
||||
#define ASYNC_WORK_DEF(name) internal ASYNC_WORK_SIG(name)
|
||||
typedef ASYNC_WORK_SIG(ASYNC_WorkFunctionType);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Work Types
|
||||
|
||||
typedef struct ASYNC_WorkParams ASYNC_WorkParams;
|
||||
struct ASYNC_WorkParams
|
||||
{
|
||||
void *input;
|
||||
void **output;
|
||||
OS_Handle semaphore;
|
||||
U64 endt_us;
|
||||
};
|
||||
|
||||
typedef struct ASYNC_Work ASYNC_Work;
|
||||
struct ASYNC_Work
|
||||
{
|
||||
ASYNC_WorkFunctionType *work_function;
|
||||
void *input;
|
||||
void **output;
|
||||
OS_Handle semaphore;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task-Based Work Types
|
||||
|
||||
typedef struct ASYNC_Task ASYNC_Task;
|
||||
struct ASYNC_Task
|
||||
{
|
||||
OS_Handle semaphore;
|
||||
void *output;
|
||||
};
|
||||
|
||||
typedef struct ASYNC_TaskNode ASYNC_TaskNode;
|
||||
struct ASYNC_TaskNode
|
||||
{
|
||||
ASYNC_TaskNode *next;
|
||||
ASYNC_Task v;
|
||||
};
|
||||
|
||||
typedef struct ASYNC_TaskList ASYNC_TaskList;
|
||||
struct ASYNC_TaskList
|
||||
{
|
||||
ASYNC_TaskNode *first;
|
||||
ASYNC_TaskNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Shared State Bundle
|
||||
|
||||
typedef struct ASYNC_Shared ASYNC_Shared;
|
||||
struct ASYNC_Shared
|
||||
{
|
||||
Arena *arena;
|
||||
|
||||
// rjf: user -> work thread ring buffer
|
||||
U64 u2w_ring_size;
|
||||
U8 *u2w_ring_base;
|
||||
U64 u2w_ring_write_pos;
|
||||
U64 u2w_ring_read_pos;
|
||||
OS_Handle u2w_ring_mutex;
|
||||
OS_Handle u2w_ring_cv;
|
||||
|
||||
// rjf: work threads
|
||||
OS_Handle *work_threads;
|
||||
U64 work_threads_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global ASYNC_Shared *async_shared = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Top-Level Layer Initialization
|
||||
|
||||
internal void async_init(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Top-Level Accessors
|
||||
|
||||
internal U64 async_thread_count(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Work Kickoffs
|
||||
|
||||
internal B32 async_push_work_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params);
|
||||
#define async_push_work(function, ...) async_push_work_((function), &(ASYNC_WorkParams){.endt_us = max_U64, __VA_ARGS__})
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task-Based Work Helper
|
||||
|
||||
internal void async_task_list_push(Arena *arena, ASYNC_TaskList *list, ASYNC_Task t);
|
||||
internal ASYNC_Task async_task_launch_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params);
|
||||
#define async_task_kickoff(work_function, ...) async_task_kickoff_((work_function), &(ASYNC_WorkParams){.endt_us = max_U64, __VA_ARGS__})
|
||||
internal void *async_task_join(ASYNC_Task task);
|
||||
#define async_task_join_struct(task, T) (T *)async_task_join(task)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Work Thread Entry Point
|
||||
|
||||
internal void async_work_thread__entry_point(void *p);
|
||||
|
||||
#endif // ASYNC_H
|
||||
@@ -710,8 +710,13 @@ os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out)
|
||||
internal void
|
||||
os_file_iter_end(OS_FileIter *iter)
|
||||
{
|
||||
OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory;
|
||||
FindClose(w32_iter->handle);
|
||||
OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory;
|
||||
HANDLE zero_handle;
|
||||
MemoryZeroStruct(&zero_handle);
|
||||
if(!MemoryMatchStruct(&zero_handle, &w32_iter->handle))
|
||||
{
|
||||
FindClose(w32_iter->handle);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: directory creation
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
// ability to put "$err, hr" into the watch window, which will just show
|
||||
// the value of GetLastError() as a string. This is super useful for
|
||||
// debugging, so you don't have to litter your own code with it.
|
||||
// (NOTE(rjf): NtQueryInformationThread)
|
||||
//
|
||||
// [ ] Tooltip Coverage:
|
||||
// [ ] lock icon
|
||||
@@ -571,6 +572,7 @@
|
||||
//- rjf: [h]
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "async/async.h"
|
||||
#include "task_system/task_system.h"
|
||||
#include "rdi_format/rdi_format_local.h"
|
||||
#include "rdi_make/rdi_make_local.h"
|
||||
@@ -613,6 +615,7 @@
|
||||
//- rjf: [c]
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "async/async.c"
|
||||
#include "task_system/task_system.c"
|
||||
#include "rdi_format/rdi_format_local.c"
|
||||
#include "rdi_make/rdi_make_local.c"
|
||||
|
||||
@@ -225,11 +225,11 @@ entry_point(CmdLine *cmdline)
|
||||
|
||||
//- rjf: kick off unit vmap baking
|
||||
P2B_BakeUnitVMapIn bake_unit_vmap_in = {¶ms->units};
|
||||
TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2b_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in);
|
||||
TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2b_bake_unit_vmap_task__entry_point, &bake_unit_vmap_in);
|
||||
|
||||
//- rjf: kick off line-table baking
|
||||
P2B_BakeLineTablesIn bake_line_tables_in = {¶ms->line_tables};
|
||||
TS_Ticket bake_line_tables_ticket = ts_kickoff(p2b_bake_line_table_task__entry_point, 0, &bake_line_tables_in);
|
||||
TS_Ticket bake_line_tables_ticket = ts_kickoff(p2b_bake_line_table_task__entry_point, &bake_line_tables_in);
|
||||
|
||||
//- rjf: build unit -> line table idx array
|
||||
U64 unit_count = params->units.total_count;
|
||||
@@ -288,7 +288,7 @@ entry_point(CmdLine *cmdline)
|
||||
dump_proc_chunk_in[task_idx].unit_count = unit_count;
|
||||
dump_proc_chunk_in[task_idx].line_tables_bake = bake_line_tables_out;
|
||||
dump_proc_chunk_in[task_idx].chunk = n;
|
||||
dump_proc_chunk_tickets[task_idx] = ts_kickoff(p2b_dump_proc_chunk_task__entry_point, 0, &dump_proc_chunk_in[task_idx]);
|
||||
dump_proc_chunk_tickets[task_idx] = ts_kickoff(p2b_dump_proc_chunk_task__entry_point, &dump_proc_chunk_in[task_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3184,7 +3184,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
//- rjf: kickoff EXE hash
|
||||
//
|
||||
P2R_EXEHashIn exe_hash_in = {in->input_exe_data};
|
||||
TS_Ticket exe_hash_ticket = ts_kickoff(p2r_exe_hash_task__entry_point, 0, &exe_hash_in);
|
||||
TS_Ticket exe_hash_ticket = ts_kickoff(p2r_exe_hash_task__entry_point, &exe_hash_in);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: kickoff TPI hash parse
|
||||
@@ -3197,7 +3197,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
tpi_hash_in.tpi = tpi;
|
||||
tpi_hash_in.hash_data = msf_data_from_stream(msf, tpi->hash_sn);
|
||||
tpi_hash_in.aux_data = msf_data_from_stream(msf, tpi->hash_sn_aux);
|
||||
tpi_hash_ticket = ts_kickoff(p2r_tpi_hash_parse_task__entry_point, 0, &tpi_hash_in);
|
||||
tpi_hash_ticket = ts_kickoff(p2r_tpi_hash_parse_task__entry_point, &tpi_hash_in);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -3209,7 +3209,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
{
|
||||
tpi_leaf_in.leaf_data = pdb_leaf_data_from_tpi(tpi);
|
||||
tpi_leaf_in.itype_first = tpi->itype_first;
|
||||
tpi_leaf_ticket = ts_kickoff(p2r_tpi_leaf_parse_task__entry_point, 0, &tpi_leaf_in);
|
||||
tpi_leaf_ticket = ts_kickoff(p2r_tpi_leaf_parse_task__entry_point, &tpi_leaf_in);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -3223,7 +3223,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
ipi_hash_in.tpi = ipi;
|
||||
ipi_hash_in.hash_data = msf_data_from_stream(msf, ipi->hash_sn);
|
||||
ipi_hash_in.aux_data = msf_data_from_stream(msf, ipi->hash_sn_aux);
|
||||
ipi_hash_ticket = ts_kickoff(p2r_tpi_hash_parse_task__entry_point, 0, &ipi_hash_in);
|
||||
ipi_hash_ticket = ts_kickoff(p2r_tpi_hash_parse_task__entry_point, &ipi_hash_in);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -3235,22 +3235,22 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
{
|
||||
ipi_leaf_in.leaf_data = pdb_leaf_data_from_tpi(ipi);
|
||||
ipi_leaf_in.itype_first = ipi->itype_first;
|
||||
ipi_leaf_ticket = ts_kickoff(p2r_tpi_leaf_parse_task__entry_point, 0, &ipi_leaf_in);
|
||||
ipi_leaf_ticket = ts_kickoff(p2r_tpi_leaf_parse_task__entry_point, &ipi_leaf_in);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: kickoff top-level global symbol stream parse
|
||||
//
|
||||
P2R_SymbolStreamParseIn sym_parse_in = {dbi ? msf_data_from_stream(msf, dbi->sym_sn) : str8_zero()};
|
||||
TS_Ticket sym_parse_ticket = !dbi ? ts_ticket_zero() : ts_kickoff(p2r_symbol_stream_parse_task__entry_point, 0, &sym_parse_in);
|
||||
TS_Ticket sym_parse_ticket = !dbi ? ts_ticket_zero() : ts_kickoff(p2r_symbol_stream_parse_task__entry_point, &sym_parse_in);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: kickoff compilation unit parses
|
||||
//
|
||||
P2R_CompUnitParseIn comp_unit_parse_in = {dbi ? pdb_data_from_dbi_range(dbi, PDB_DbiRange_ModuleInfo) : str8_zero()};
|
||||
P2R_CompUnitContributionsParseIn comp_unit_contributions_parse_in = {dbi ? pdb_data_from_dbi_range(dbi, PDB_DbiRange_SecCon) : str8_zero(), coff_sections};
|
||||
TS_Ticket comp_unit_parse_ticket = !dbi ? ts_ticket_zero() : ts_kickoff(p2r_comp_unit_parse_task__entry_point, 0, &comp_unit_parse_in);
|
||||
TS_Ticket comp_unit_contributions_parse_ticket = !dbi ? ts_ticket_zero() : ts_kickoff(p2r_comp_unit_contributions_parse_task__entry_point, 0, &comp_unit_contributions_parse_in);
|
||||
TS_Ticket comp_unit_parse_ticket = !dbi ? ts_ticket_zero() : ts_kickoff(p2r_comp_unit_parse_task__entry_point, &comp_unit_parse_in);
|
||||
TS_Ticket comp_unit_contributions_parse_ticket = !dbi ? ts_ticket_zero() : ts_kickoff(p2r_comp_unit_contributions_parse_task__entry_point, &comp_unit_contributions_parse_in);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: join compilation unit parses
|
||||
@@ -3282,11 +3282,11 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
{
|
||||
PDB_CompUnit *unit = comp_units->units[idx];
|
||||
sym_tasks_inputs[idx].data = pdb_data_from_unit_range(msf, unit, PDB_DbiCompUnitRange_Symbols);
|
||||
sym_tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_parse_task__entry_point, 0, &sym_tasks_inputs[idx]);
|
||||
sym_tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_parse_task__entry_point, &sym_tasks_inputs[idx]);
|
||||
c13_tasks_inputs[idx].data = pdb_data_from_unit_range(msf, unit, PDB_DbiCompUnitRange_C13);
|
||||
c13_tasks_inputs[idx].strtbl = raw_strtbl;
|
||||
c13_tasks_inputs[idx].coff_sections = coff_sections;
|
||||
c13_tasks_tickets[idx] = ts_kickoff(p2r_c13_stream_parse_task__entry_point, 0, &c13_tasks_inputs[idx]);
|
||||
c13_tasks_tickets[idx] = ts_kickoff(p2r_c13_stream_parse_task__entry_point, &c13_tasks_inputs[idx]);
|
||||
}
|
||||
|
||||
//- rjf: join tasks
|
||||
@@ -3389,7 +3389,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
//- rjf: kick off unit conversion & source file collection
|
||||
//
|
||||
P2R_UnitConvertIn unit_convert_in = {strtbl, coff_sections, comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit};
|
||||
TS_Ticket unit_convert_ticket = ts_kickoff(p2r_units_convert_task__entry_point, 0, &unit_convert_in);
|
||||
TS_Ticket unit_convert_ticket = ts_kickoff(p2r_units_convert_task__entry_point, &unit_convert_in);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: join global sym stream parse
|
||||
@@ -3432,7 +3432,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
link_name_map_build_in.sym = sym;
|
||||
link_name_map_build_in.coff_sections = coff_sections;
|
||||
link_name_map_build_in.link_name_map = &link_name_map__in_progress;
|
||||
link_name_map_ticket = ts_kickoff(p2r_link_name_map_build_task__entry_point, 0, &link_name_map_build_in);
|
||||
link_name_map_ticket = ts_kickoff(p2r_link_name_map_build_task__entry_point, &link_name_map_build_in);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
@@ -3481,7 +3481,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
tasks_inputs[idx].itype_opl = tasks_inputs[idx].itype_first + task_size_itypes;
|
||||
tasks_inputs[idx].itype_opl = ClampTop(tasks_inputs[idx].itype_opl, itype_opl);
|
||||
tasks_inputs[idx].itype_fwd_map = itype_fwd_map;
|
||||
tasks_tickets[idx] = ts_kickoff(p2r_itype_fwd_map_fill_task__entry_point, 0, &tasks_inputs[idx]);
|
||||
tasks_tickets[idx] = ts_kickoff(p2r_itype_fwd_map_fill_task__entry_point, &tasks_inputs[idx]);
|
||||
}
|
||||
|
||||
//- rjf: join all tasks
|
||||
@@ -3520,7 +3520,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
tasks_inputs[idx].itype_opl = ClampTop(tasks_inputs[idx].itype_opl, itype_opl);
|
||||
tasks_inputs[idx].itype_chains = itype_chains;
|
||||
tasks_inputs[idx].itype_fwd_map = itype_fwd_map;
|
||||
tasks_tickets[idx] = ts_kickoff(p2r_itype_chain_build_task__entry_point, 0, &tasks_inputs[idx]);
|
||||
tasks_tickets[idx] = ts_kickoff(p2r_itype_chain_build_task__entry_point, &tasks_inputs[idx]);
|
||||
}
|
||||
|
||||
//- rjf: join all tasks
|
||||
@@ -3990,7 +3990,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
udt_tasks_inputs[idx].itype_opl = ClampTop(udt_tasks_inputs[idx].itype_opl, itype_opl);
|
||||
udt_tasks_inputs[idx].itype_fwd_map = itype_fwd_map;
|
||||
udt_tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs;
|
||||
udt_tasks_tickets[idx] = ts_kickoff(p2r_udt_convert_task__entry_point, 0, &udt_tasks_inputs[idx]);
|
||||
udt_tasks_tickets[idx] = ts_kickoff(p2r_udt_convert_task__entry_point, &udt_tasks_inputs[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4064,7 +4064,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
|
||||
tasks_inputs[idx].sym_ranges_opl = sym_for_unit[idx-global_stream_subdivision_tasks_count]->sym_ranges.count;
|
||||
tasks_inputs[idx].first_inline_site_line_table = units_first_inline_site_line_tables[idx-global_stream_subdivision_tasks_count];
|
||||
}
|
||||
tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, 0, &tasks_inputs[idx]);
|
||||
tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, &tasks_inputs[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4422,7 +4422,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
{
|
||||
P2R_BakeLineTablesIn *in = push_array(scratch.arena, P2R_BakeLineTablesIn, 1);
|
||||
in->line_tables = &in_params->line_tables;
|
||||
bake_line_tables_ticket = ts_kickoff(p2r_bake_line_tables_task__entry_point, 0, in);
|
||||
bake_line_tables_ticket = ts_kickoff(p2r_bake_line_tables_task__entry_point, in);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@@ -4452,7 +4452,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
in->top = &bake_string_map_topology;
|
||||
in->maps = bake_string_maps__in_progress;
|
||||
in->list = &in_params->src_files;
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_src_files_strings_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_src_files_strings_task__entry_point, in));
|
||||
}
|
||||
|
||||
// rjf: units
|
||||
@@ -4462,7 +4462,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
in->top = &bake_string_map_topology;
|
||||
in->maps = bake_string_maps__in_progress;
|
||||
in->list = &in_params->units;
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_units_strings_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_units_strings_task__entry_point, in));
|
||||
}
|
||||
|
||||
// rjf: types
|
||||
@@ -4493,7 +4493,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
chunk_off = 0;
|
||||
}
|
||||
}
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_types_strings_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_types_strings_task__entry_point, in));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4525,7 +4525,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
chunk_off = 0;
|
||||
}
|
||||
}
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_udts_strings_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_udts_strings_task__entry_point, in));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4565,7 +4565,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
chunk_off = 0;
|
||||
}
|
||||
}
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_symbols_strings_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_symbols_strings_task__entry_point, in));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4598,7 +4598,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
chunk_off = 0;
|
||||
}
|
||||
}
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_scopes_strings_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_scopes_strings_task__entry_point, in));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4614,7 +4614,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
{
|
||||
build_bake_name_map_in[k].k = k;
|
||||
build_bake_name_map_in[k].params = in_params;
|
||||
build_bake_name_map_ticket[k] = ts_kickoff(p2r_build_bake_name_map_task__entry_point, 0, &build_bake_name_map_in[k]);
|
||||
build_bake_name_map_ticket[k] = ts_kickoff(p2r_build_bake_name_map_task__entry_point, &build_bake_name_map_in[k]);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@@ -4680,7 +4680,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
in->dst_map = unsorted_bake_string_map;
|
||||
in->slot_idx_range = r1u64(task_idx*slots_per_task, task_idx*slots_per_task + slots_per_task);
|
||||
in->slot_idx_range.max = Min(in->slot_idx_range.max, in->top->slots_count);
|
||||
task_tickets[task_idx] = ts_kickoff(p2r_bake_string_map_join_task__entry_point, 0, in);
|
||||
task_tickets[task_idx] = ts_kickoff(p2r_bake_string_map_join_task__entry_point, in);
|
||||
}
|
||||
|
||||
// rjf: join tasks
|
||||
@@ -4746,7 +4746,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
in->slot_count = bake_string_map_topology.slots_count - in->slot_idx;
|
||||
}
|
||||
}
|
||||
ts_ticket_list_push(scratch.arena, &sort_bake_string_map_task_tickets, ts_kickoff(p2r_bake_string_map_sort_task__entry_point, 0, in));
|
||||
ts_ticket_list_push(scratch.arena, &sort_bake_string_map_task_tickets, ts_kickoff(p2r_bake_string_map_sort_task__entry_point, in));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4824,31 +4824,31 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
//- rjf: kick off pass 2 tasks
|
||||
//
|
||||
P2R_BakeUnitsIn bake_units_top_level_in = {&bake_strings, path_tree, &in_params->units};
|
||||
TS_Ticket bake_units_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_top_level_in);
|
||||
TS_Ticket bake_units_ticket = ts_kickoff(p2r_bake_units_task__entry_point, &bake_units_top_level_in);
|
||||
P2R_BakeUnitVMapIn bake_unit_vmap_in = {&in_params->units};
|
||||
TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in);
|
||||
TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, &bake_unit_vmap_in);
|
||||
P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, &in_params->src_files};
|
||||
TS_Ticket bake_src_files_ticket = ts_kickoff(p2r_bake_src_files_task__entry_point, 0, &bake_src_files_in);
|
||||
TS_Ticket bake_src_files_ticket = ts_kickoff(p2r_bake_src_files_task__entry_point, &bake_src_files_in);
|
||||
P2R_BakeUDTsIn bake_udts_in = {&bake_strings, &in_params->udts};
|
||||
TS_Ticket bake_udts_ticket = ts_kickoff(p2r_bake_udts_task__entry_point, 0, &bake_udts_in);
|
||||
TS_Ticket bake_udts_ticket = ts_kickoff(p2r_bake_udts_task__entry_point, &bake_udts_in);
|
||||
P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables};
|
||||
TS_Ticket bake_global_variables_ticket = ts_kickoff(p2r_bake_global_variables_task__entry_point, 0, &bake_global_variables_in);
|
||||
TS_Ticket bake_global_variables_ticket = ts_kickoff(p2r_bake_global_variables_task__entry_point, &bake_global_variables_in);
|
||||
P2R_BakeGlobalVMapIn bake_global_vmap_in = {&in_params->global_variables};
|
||||
TS_Ticket bake_global_vmap_ticket = ts_kickoff(p2r_bake_global_vmap_task__entry_point, 0, &bake_global_vmap_in);
|
||||
TS_Ticket bake_global_vmap_ticket = ts_kickoff(p2r_bake_global_vmap_task__entry_point, &bake_global_vmap_in);
|
||||
P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables};
|
||||
TS_Ticket bake_thread_variables_ticket = ts_kickoff(p2r_bake_thread_variables_task__entry_point, 0, &bake_thread_variables_in);
|
||||
TS_Ticket bake_thread_variables_ticket = ts_kickoff(p2r_bake_thread_variables_task__entry_point, &bake_thread_variables_in);
|
||||
P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures};
|
||||
TS_Ticket bake_procedures_ticket = ts_kickoff(p2r_bake_procedures_task__entry_point, 0, &bake_procedures_in);
|
||||
TS_Ticket bake_procedures_ticket = ts_kickoff(p2r_bake_procedures_task__entry_point, &bake_procedures_in);
|
||||
P2R_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes};
|
||||
TS_Ticket bake_scopes_ticket = ts_kickoff(p2r_bake_scopes_task__entry_point, 0, &bake_scopes_in);
|
||||
TS_Ticket bake_scopes_ticket = ts_kickoff(p2r_bake_scopes_task__entry_point, &bake_scopes_in);
|
||||
P2R_BakeScopeVMapIn bake_scope_vmap_in = {&in_params->scopes};
|
||||
TS_Ticket bake_scope_vmap_ticket = ts_kickoff(p2r_bake_scope_vmap_task__entry_point, 0, &bake_scope_vmap_in);
|
||||
TS_Ticket bake_scope_vmap_ticket = ts_kickoff(p2r_bake_scope_vmap_task__entry_point, &bake_scope_vmap_in);
|
||||
P2R_BakeInlineSitesIn bake_inline_sites_in = {&bake_strings, &in_params->inline_sites};
|
||||
TS_Ticket bake_inline_sites_ticket = ts_kickoff(p2r_bake_inline_sites_task__entry_point, 0, &bake_inline_sites_in);
|
||||
TS_Ticket bake_inline_sites_ticket = ts_kickoff(p2r_bake_inline_sites_task__entry_point, &bake_inline_sites_in);
|
||||
P2R_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree};
|
||||
TS_Ticket bake_file_paths_ticket = ts_kickoff(p2r_bake_file_paths_task__entry_point, 0, &bake_file_paths_in);
|
||||
TS_Ticket bake_file_paths_ticket = ts_kickoff(p2r_bake_file_paths_task__entry_point, &bake_file_paths_in);
|
||||
P2R_BakeStringsIn bake_strings_in = {&bake_strings};
|
||||
TS_Ticket bake_strings_ticket = ts_kickoff(p2r_bake_strings_task__entry_point, 0, &bake_strings_in);
|
||||
TS_Ticket bake_strings_ticket = ts_kickoff(p2r_bake_strings_task__entry_point, &bake_strings_in);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: join name map building tasks
|
||||
@@ -4884,7 +4884,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
//- rjf: kick off pass 3 tasks
|
||||
//
|
||||
P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, &in_params->types};
|
||||
TS_Ticket bake_type_nodes_ticket = ts_kickoff(p2r_bake_type_nodes_task__entry_point, 0, &bake_type_nodes_in);
|
||||
TS_Ticket bake_type_nodes_ticket = ts_kickoff(p2r_bake_type_nodes_task__entry_point, &bake_type_nodes_in);
|
||||
TS_Ticket bake_name_maps_tickets[RDI_NameMapKind_COUNT] = {0};
|
||||
{
|
||||
for EachNonZeroEnumVal(RDI_NameMapKind, k)
|
||||
@@ -4898,11 +4898,11 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in)
|
||||
in->idx_runs = idx_runs;
|
||||
in->map = name_maps[k];
|
||||
in->kind = k;
|
||||
bake_name_maps_tickets[k] = ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in);
|
||||
bake_name_maps_tickets[k] = ts_kickoff(p2r_bake_name_map_task__entry_point, in);
|
||||
}
|
||||
}
|
||||
P2R_BakeIdxRunsIn bake_idx_runs_in = {idx_runs};
|
||||
TS_Ticket bake_idx_runs_ticket = ts_kickoff(p2r_bake_idx_runs_task__entry_point, 0, &bake_idx_runs_in);
|
||||
TS_Ticket bake_idx_runs_ticket = ts_kickoff(p2r_bake_idx_runs_task__entry_point, &bake_idx_runs_in);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: join remaining completed bakes
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "task_system/task_system.h"
|
||||
#include "task_system/task_system2.h"
|
||||
#include "rdi_make/rdi_make_local.h"
|
||||
#include "coff/coff.h"
|
||||
#include "codeview/codeview.h"
|
||||
@@ -39,6 +40,7 @@
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "task_system/task_system.c"
|
||||
#include "task_system/task_system2.c"
|
||||
#include "rdi_make/rdi_make_local.c"
|
||||
#include "coff/coff.c"
|
||||
#include "codeview/codeview.c"
|
||||
|
||||
@@ -11,6 +11,13 @@ ts_ticket_zero(void)
|
||||
return ticket;
|
||||
}
|
||||
|
||||
internal B32
|
||||
ts_ticket_match(TS_Ticket a, TS_Ticket b)
|
||||
{
|
||||
B32 result = MemoryMatchStruct(&a, &b);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ts_ticket_list_push(Arena *arena, TS_TicketList *list, TS_Ticket ticket)
|
||||
{
|
||||
@@ -65,7 +72,7 @@ ts_thread_count(void)
|
||||
//~ rjf: High-Level Task Kickoff / Joining
|
||||
|
||||
internal TS_Ticket
|
||||
ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p)
|
||||
ts_kickoff_(TS_TaskFunctionType *entry_point, TS_KickoffParams *params)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
@@ -93,7 +100,7 @@ ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p
|
||||
}
|
||||
artifact->num = artifact_num;
|
||||
artifact->task_is_done = 0;
|
||||
artifact->result = 0;
|
||||
artifact->out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,20 +114,20 @@ ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p
|
||||
{
|
||||
U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos;
|
||||
U64 available_size = ts_shared->u2t_ring_size-unconsumed_size;
|
||||
if(available_size >= sizeof(entry_point) + sizeof(p) + sizeof(ticket))
|
||||
if(available_size >= sizeof(entry_point) + sizeof(Arena *) + sizeof(params->in) + sizeof(ticket))
|
||||
{
|
||||
Arena *task_arena = 0;
|
||||
if(optional_arena_ptr != 0)
|
||||
if(params->optional_arena_ptr != 0)
|
||||
{
|
||||
task_arena = *optional_arena_ptr;
|
||||
task_arena = *params->optional_arena_ptr;
|
||||
}
|
||||
ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &entry_point);
|
||||
ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &task_arena);
|
||||
ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &p);
|
||||
ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, ¶ms->in);
|
||||
ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &ticket);
|
||||
if(optional_arena_ptr != 0)
|
||||
if(params->optional_arena_ptr != 0)
|
||||
{
|
||||
*optional_arena_ptr = 0;
|
||||
*params->optional_arena_ptr = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -133,10 +140,10 @@ ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p
|
||||
return ticket;
|
||||
}
|
||||
|
||||
internal void *
|
||||
internal TS_JoinResult
|
||||
ts_join(TS_Ticket ticket, U64 endt_us)
|
||||
{
|
||||
void *result = 0;
|
||||
TS_JoinResult result = {0};
|
||||
U64 artifact_num = ticket.u64[0];
|
||||
U64 slot_idx = artifact_num%ts_shared->artifact_slots_count;
|
||||
U64 stripe_idx = slot_idx%ts_shared->artifact_stripes_count;
|
||||
@@ -152,7 +159,8 @@ ts_join(TS_Ticket ticket, U64 endt_us)
|
||||
{
|
||||
OS_MutexScopeRWPromote(stripe->rw_mutex)
|
||||
{
|
||||
result = artifact->result;
|
||||
result.good = 1;
|
||||
result.out = artifact->out;
|
||||
SLLStackPush(stripe->free_artifact, artifact);
|
||||
}
|
||||
break;
|
||||
@@ -211,7 +219,7 @@ ts_task_thread__entry_point(void *p)
|
||||
}
|
||||
|
||||
//- rjf: run task
|
||||
void *task_result = task_function(task_arena, thread_idx, task_params);
|
||||
void *task_out = task_function(task_arena, thread_idx, task_params);
|
||||
|
||||
//- rjf: store into artifact
|
||||
U64 artifact_num = task_ticket.u64[0];
|
||||
@@ -223,7 +231,7 @@ ts_task_thread__entry_point(void *p)
|
||||
OS_MutexScopeW(stripe->rw_mutex)
|
||||
{
|
||||
artifact->task_is_done = 1;
|
||||
artifact->result = task_result;
|
||||
artifact->out = task_out;
|
||||
}
|
||||
os_condition_variable_broadcast(stripe->cv);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,26 @@ struct TS_TicketList
|
||||
#define TS_TASK_FUNCTION_DEF(name) void *name(Arena *arena, U64 thread_idx, void *p)
|
||||
typedef TS_TASK_FUNCTION_DEF(TS_TaskFunctionType);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task Kickoff Parameters
|
||||
|
||||
typedef struct TS_KickoffParams TS_KickoffParams;
|
||||
struct TS_KickoffParams
|
||||
{
|
||||
Arena **optional_arena_ptr;
|
||||
void *in;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task Join Result
|
||||
|
||||
typedef struct TS_JoinResult TS_JoinResult;
|
||||
struct TS_JoinResult
|
||||
{
|
||||
B32 good;
|
||||
void *out;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task Artifact Cache Types
|
||||
|
||||
@@ -46,7 +66,7 @@ struct TS_TaskArtifact
|
||||
TS_TaskArtifact *next;
|
||||
U64 num;
|
||||
B64 task_is_done;
|
||||
void *result;
|
||||
void *out;
|
||||
};
|
||||
|
||||
typedef struct TS_TaskArtifactSlot TS_TaskArtifactSlot;
|
||||
@@ -112,6 +132,7 @@ global TS_Shared *ts_shared = 0;
|
||||
//~ rjf: Basic Type Functions
|
||||
|
||||
internal TS_Ticket ts_ticket_zero(void);
|
||||
internal B32 ts_ticket_match(TS_Ticket a, TS_Ticket b);
|
||||
internal void ts_ticket_list_push(Arena *arena, TS_TicketList *list, TS_Ticket ticket);
|
||||
|
||||
////////////////////////////////
|
||||
@@ -127,9 +148,10 @@ internal U64 ts_thread_count(void);
|
||||
////////////////////////////////
|
||||
//~ rjf: High-Level Task Kickoff / Joining
|
||||
|
||||
internal TS_Ticket ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p);
|
||||
internal void *ts_join(TS_Ticket ticket, U64 endt_us);
|
||||
#define ts_join_struct(ticket, endt_us, type) (type *)ts_join((ticket), (endt_us))
|
||||
internal TS_Ticket ts_kickoff_(TS_TaskFunctionType *entry_point, TS_KickoffParams *params);
|
||||
#define ts_kickoff(entry_point, input_ptr, ...) ts_kickoff_((entry_point), &(TS_KickoffParams){.in = (input_ptr), __VA_ARGS__})
|
||||
internal TS_JoinResult ts_join(TS_Ticket ticket, U64 endt_us);
|
||||
#define ts_join_struct(ticket, endt_us, type) (type *)ts_join((ticket), (endt_us)).out
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Task Threads
|
||||
|
||||
Reference in New Issue
Block a user