unlock fiber wake while wait list locked

This commit is contained in:
jacob 2025-07-12 20:21:13 -05:00
parent c3f94380c2
commit 66586f9cf5
17 changed files with 123 additions and 98 deletions

View File

@ -36,9 +36,9 @@ GLOBAL struct {
struct asset_cache_startup_receipt asset_cache_startup(void) struct asset_cache_startup_receipt asset_cache_startup(void)
{ {
__prof;
/* Init store */ /* Init store */
G.store_arena = arena_alloc(GIBI(64)); G.store_arena = arena_alloc(GIBI(64));
return (struct asset_cache_startup_receipt) { 0 }; return (struct asset_cache_startup_receipt) { 0 };
} }

View File

@ -15,6 +15,7 @@ GLOBAL struct {
struct draw_startup_receipt draw_startup(struct font_startup_receipt *font_sr) struct draw_startup_receipt draw_startup(struct font_startup_receipt *font_sr)
{ {
__prof;
(UNUSED)font_sr; (UNUSED)font_sr;
u32 pixel_white = 0xFFFFFFFF; u32 pixel_white = 0xFFFFFFFF;
G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32(1, 1), &pixel_white); G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32(1, 1), &pixel_white);

View File

@ -42,11 +42,10 @@ GLOBAL struct {
struct font_startup_receipt font_startup(struct asset_cache_startup_receipt *asset_cache_sr, struct font_startup_receipt font_startup(struct asset_cache_startup_receipt *asset_cache_sr,
struct ttf_startup_receipt *ttf_sr) struct ttf_startup_receipt *ttf_sr)
{ {
__prof;
(UNUSED)asset_cache_sr; (UNUSED)asset_cache_sr;
(UNUSED)ttf_sr; (UNUSED)ttf_sr;
G.params.arena = arena_alloc(GIBI(64)); G.params.arena = arena_alloc(GIBI(64));
return (struct font_startup_receipt) { 0 }; return (struct font_startup_receipt) { 0 };
} }

View File

@ -123,8 +123,14 @@ struct pipeline_scope {
struct pipeline_scope *next_free; struct pipeline_scope *next_free;
}; };
struct command_queue_desc {
enum D3D12_COMMAND_LIST_TYPE type;
enum D3D12_COMMAND_QUEUE_PRIORITY priority;
struct string dbg_name;
};
struct command_queue { struct command_queue {
D3D12_COMMAND_LIST_TYPE type; struct command_queue_desc desc;
ID3D12CommandQueue *cq; ID3D12CommandQueue *cq;
struct arena *arena; struct arena *arena;
@ -343,11 +349,16 @@ INTERNAL void dx12_init_device(void);
INTERNAL void dx12_init_objects(void); INTERNAL void dx12_init_objects(void);
INTERNAL void dx12_init_pipelines(void); INTERNAL void dx12_init_pipelines(void);
INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type); INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type);
INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority, struct string dbg_name);
INTERNAL void command_queue_release(struct command_queue *cq); INTERNAL void command_queue_release(struct command_queue *cq);
INTERNAL SYS_JOB_DEF(dx12_evictor_job, _); INTERNAL SYS_JOB_DEF(dx12_evictor_job, _);
INTERNAL void fenced_release(void *data, enum fenced_release_kind kind); INTERNAL void fenced_release(void *data, enum fenced_release_kind kind);
struct command_queue_alloc_job_sig { struct command_queue_desc *descs_in; struct command_queue **cqs_out; };
INTERNAL SYS_JOB_DEF(command_queue_alloc_job, job);
struct pipeline_alloc_job_sig { struct pipeline_desc *descs_in; struct pipeline **pipelines_out; };
INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job);
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name); INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name);
#endif #endif
@ -591,6 +602,8 @@ INTERNAL void dx12_init_device(void)
INTERNAL void dx12_init_objects(void) INTERNAL void dx12_init_objects(void)
{ {
__prof;
/* Initialize desc sizes */ /* Initialize desc sizes */
G.desc_sizes[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] = ID3D12Device_GetDescriptorHandleIncrementSize(G.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); G.desc_sizes[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] = ID3D12Device_GetDescriptorHandleIncrementSize(G.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
G.desc_sizes[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] = ID3D12Device_GetDescriptorHandleIncrementSize(G.device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); G.desc_sizes[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] = ID3D12Device_GetDescriptorHandleIncrementSize(G.device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
@ -606,16 +619,34 @@ INTERNAL void dx12_init_objects(void)
G.rtv_heap = cpu_descriptor_heap_alloc(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); G.rtv_heap = cpu_descriptor_heap_alloc(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
/* Create command queues */ /* Create command queues */
for (u32 i = 0; i < DX12_NUM_QUEUES; ++i) { {
if (i == DX12_QUEUE_DIRECT) { __profn("Allocate command queues");
G.command_queues[i] = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, LIT("Direct queue")); struct command_queue_desc params[] = {
} else if (i == DX12_QUEUE_COMPUTE) { { .type = D3D12_COMMAND_LIST_TYPE_DIRECT, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = LIT("Direct queue") },
G.command_queues[i] = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COMPUTE, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, LIT("Compute queue")); { .type = D3D12_COMMAND_LIST_TYPE_COMPUTE, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = LIT("Compute queue") },
} else if (i == DX12_QUEUE_COPY) { { .type = D3D12_COMMAND_LIST_TYPE_COPY, .priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH, .dbg_name = LIT("Copy queue") },
G.command_queues[i] = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COPY, D3D12_COMMAND_QUEUE_PRIORITY_HIGH, LIT("Copy queue")); { .type = D3D12_COMMAND_LIST_TYPE_COPY, .priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, .dbg_name = LIT("Background copy queue") }
} else if (i == DX12_QUEUE_COPY_BACKGROUND) { };
G.command_queues[i] = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COPY, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, LIT("Background copy queue")); struct command_queue_alloc_job_sig sig = ZI;
sig.descs_in = params;
sig.cqs_out = G.command_queues;
{
struct snc_counter counter = ZI;
sys_run(DX12_NUM_QUEUES, command_queue_alloc_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
snc_counter_wait(&counter);
} }
#if PROFILING
{
/* Initialize serially for consistent order in profiler */
__profn("Initialize command queue profiling contexts");
for (i32 i = 0; i < DX12_NUM_QUEUES; ++i) {
struct command_queue *cq = G.command_queues[i];
struct string dbg_name = params[i].dbg_name;
__prof_dx12_ctx_alloc(cq->prof, G.device, cq->cq, dbg_name.text, dbg_name.len);
(UNUSED)dbg_name;
}
}
#endif
} }
} }
@ -623,7 +654,6 @@ INTERNAL void dx12_init_objects(void)
* Dx12 pipeline initialization * Dx12 pipeline initialization
* ========================== */ * ========================== */
INTERNAL void pipeline_alloc(u64 num_pipelines, struct pipeline_desc *descs_in, struct pipeline **pipelines_out);
INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines); INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines);
INTERNAL void dx12_init_pipelines(void) INTERNAL void dx12_init_pipelines(void)
@ -676,7 +706,15 @@ INTERNAL void dx12_init_pipelines(void)
++num_pipelines; ++num_pipelines;
} }
struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines);
pipeline_alloc(num_pipelines, descs, pipelines); {
__profn("Allocate pipelines");
struct pipeline_alloc_job_sig sig = ZI;
sig.descs_in = descs;
sig.pipelines_out = pipelines;
struct snc_counter counter = ZI;
sys_run(num_pipelines, pipeline_alloc_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
snc_counter_wait(&counter);
}
for (u32 i = 0; i < num_pipelines; ++i) { for (u32 i = 0; i < num_pipelines; ++i) {
struct pipeline *pipeline = pipelines[i]; struct pipeline *pipeline = pipelines[i];
if (!pipeline->success) { if (!pipeline->success) {
@ -826,6 +864,7 @@ INTERNAL SYS_JOB_DEF(shader_compile_job, job)
/* Compile shader */ /* Compile shader */
{ {
__profn("Compile shader");
struct string shader_src = resource_get_data(shader_res); struct string shader_src = resource_get_data(shader_res);
logf_info("Compiling shader \"%F:%F\"", FMT_STR(shader_desc.file), FMT_STR(shader_desc.func)); logf_info("Compiling shader \"%F:%F\"", FMT_STR(shader_desc.file), FMT_STR(shader_desc.func));
/* Compile shader */ /* Compile shader */
@ -872,15 +911,10 @@ INTERNAL SYS_JOB_DEF(shader_compile_job, job)
* Pipeline * Pipeline
* ========================== */ * ========================== */
struct pipeline_init_job_sig { INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job)
struct pipeline_desc *descs_in;
struct pipeline **pipelines_out;
};
INTERNAL SYS_JOB_DEF(pipeline_init_job, job)
{ {
__prof; __prof;
struct pipeline_init_job_sig *sig = job.sig; struct pipeline_alloc_job_sig *sig = job.sig;
struct pipeline_desc *desc = &sig->descs_in[job.id]; struct pipeline_desc *desc = &sig->descs_in[job.id];
struct pipeline **pipelines_out = sig->pipelines_out; struct pipeline **pipelines_out = sig->pipelines_out;
@ -1131,15 +1165,6 @@ INTERNAL SYS_JOB_DEF(pipeline_init_job, job)
scratch_end(scratch); scratch_end(scratch);
} }
INTERNAL void pipeline_alloc(u64 num_pipelines, struct pipeline_desc *descs_in, struct pipeline **pipelines_out)
{
__prof;
struct pipeline_init_job_sig sig = { .descs_in = descs_in, .pipelines_out = pipelines_out };
struct snc_counter counter = ZI;
sys_run(num_pipelines, pipeline_init_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
snc_counter_wait(&counter);
}
INTERNAL void pipeline_release_now(struct pipeline *pipeline) INTERNAL void pipeline_release_now(struct pipeline *pipeline)
{ {
__prof; __prof;
@ -1279,8 +1304,16 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
/* Recompile dirty pipelines */ /* Recompile dirty pipelines */
if (num_pipelines > 0) { if (num_pipelines > 0) {
__profn("Compile dirty pipelines");
struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines);
pipeline_alloc(num_pipelines, pipeline_descs, pipelines); {
struct pipeline_alloc_job_sig sig = ZI;
sig.descs_in = pipeline_descs;
sig.pipelines_out = pipelines;
struct snc_counter counter = ZI;
sys_run(num_pipelines, pipeline_alloc_job, &sig, SYS_POOL_INHERIT, SYS_PRIORITY_INHERIT, &counter);
snc_counter_wait(&counter);
}
{ {
struct snc_lock lock = snc_lock_s(&G.pipelines_mutex); struct snc_lock lock = snc_lock_s(&G.pipelines_mutex);
for (u32 i = 0; i < num_pipelines; ++i) { for (u32 i = 0; i < num_pipelines; ++i) {
@ -1711,21 +1744,25 @@ void gp_resource_release(struct gp_resource *resource)
INTERNAL struct command_list_pool *command_list_pool_alloc(struct command_queue *cq); INTERNAL struct command_list_pool *command_list_pool_alloc(struct command_queue *cq);
INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority, struct string dbg_name) INTERNAL SYS_JOB_DEF(command_queue_alloc_job, job)
{ {
__prof; __prof;
struct command_queue_alloc_job_sig *sig = job.sig;
struct command_queue_desc *desc = &sig->descs_in[job.id];
{
struct command_queue *cq = 0; struct command_queue *cq = 0;
{ {
struct arena *arena = arena_alloc(GIBI(64)); struct arena *arena = arena_alloc(GIBI(64));
cq = arena_push(arena, struct command_queue); cq = arena_push(arena, struct command_queue);
cq->arena = arena; cq->arena = arena;
} }
cq->desc = *desc;
D3D12_COMMAND_QUEUE_DESC desc = ZI; D3D12_COMMAND_QUEUE_DESC dx12_desc = ZI;
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; dx12_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
desc.Type = type; dx12_desc.Type = desc->type;
desc.Priority = priority; dx12_desc.Priority = desc->priority;
HRESULT hr = ID3D12Device_CreateCommandQueue(G.device, &desc, &IID_ID3D12CommandQueue, (void **)&cq->cq); HRESULT hr = ID3D12Device_CreateCommandQueue(G.device, &dx12_desc, &IID_ID3D12CommandQueue, (void **)&cq->cq);
if (FAILED(hr)) { if (FAILED(hr)) {
sys_panic(LIT("Failed to create command queue")); sys_panic(LIT("Failed to create command queue"));
} }
@ -1735,12 +1772,10 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE
sys_panic(LIT("Failed to create command queue fence")); sys_panic(LIT("Failed to create command queue fence"));
} }
__prof_dx12_ctx_alloc(cq->prof, G.device, cq->cq, dbg_name.text, dbg_name.len);
(UNUSED)dbg_name;
cq->type = type;
cq->cl_pool = command_list_pool_alloc(cq); cq->cl_pool = command_list_pool_alloc(cq);
return cq;
sig->cqs_out[job.id] = cq;
}
} }
INTERNAL void command_queue_release(struct command_queue *cq) INTERNAL void command_queue_release(struct command_queue *cq)
@ -1816,12 +1851,12 @@ INTERNAL struct command_list *command_list_open(struct command_list_pool *pool)
cl->cl = old_cl; cl->cl = old_cl;
cl->ca = old_ca; cl->ca = old_ca;
} else { } else {
hr = ID3D12Device_CreateCommandAllocator(G.device, cq->type, &IID_ID3D12CommandAllocator, (void **)&cl->ca); hr = ID3D12Device_CreateCommandAllocator(G.device, cq->desc.type, &IID_ID3D12CommandAllocator, (void **)&cl->ca);
if (FAILED(hr)) { if (FAILED(hr)) {
sys_panic(LIT("Failed to create command allocator")); sys_panic(LIT("Failed to create command allocator"));
} }
hr = ID3D12Device_CreateCommandList(G.device, 0, cq->type, cl->ca, 0, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl); hr = ID3D12Device_CreateCommandList(G.device, 0, cq->desc.type, cl->ca, 0, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl);
if (FAILED(hr)) { if (FAILED(hr)) {
sys_panic(LIT("Failed to create command list")); sys_panic(LIT("Failed to create command list"));
} }

View File

@ -165,8 +165,8 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma);
struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr) struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr)
{ {
__prof;
(UNUSED)sock_sr; (UNUSED)sock_sr;
return (struct host_startup_receipt) { 0 }; return (struct host_startup_receipt) { 0 };
} }

View File

@ -64,6 +64,7 @@ GLOBAL READONLY struct log_level_settings g_log_level_settings[LOG_LEVEL_COUNT]
void log_startup(struct string logfile_path) void log_startup(struct string logfile_path)
{ {
__prof;
G.callbacks_arena = arena_alloc(MEBI(8)); G.callbacks_arena = arena_alloc(MEBI(8));
if (logfile_path.len > 0) { if (logfile_path.len > 0) {
/* Create / wipe log file */ /* Create / wipe log file */

View File

@ -72,10 +72,10 @@ GLOBAL struct {
struct mixer_startup_receipt mixer_startup(void) struct mixer_startup_receipt mixer_startup(void)
{ {
__prof;
G.track_arena = arena_alloc(GIBI(64)); G.track_arena = arena_alloc(GIBI(64));
G.listener_pos = V2(0, 0); G.listener_pos = V2(0, 0);
G.listener_dir = V2(0, -1); G.listener_dir = V2(0, -1);
return (struct mixer_startup_receipt) { 0 }; return (struct mixer_startup_receipt) { 0 };
} }

View File

@ -54,8 +54,8 @@ INTERNAL SYS_JOB_DEF(playback_job, _);
struct playback_startup_receipt playback_startup(struct mixer_startup_receipt *mixer_sr) struct playback_startup_receipt playback_startup(struct mixer_startup_receipt *mixer_sr)
{ {
__prof;
(UNUSED)mixer_sr; (UNUSED)mixer_sr;
wasapi_initialize(); wasapi_initialize();
/* Start playback job */ /* Start playback job */
sys_run(1, playback_job, 0, SYS_POOL_AUDIO, SYS_PRIORITY_HIGH, &G.playback_job_counter); sys_run(1, playback_job, 0, SYS_POOL_AUDIO, SYS_PRIORITY_HIGH, &G.playback_job_counter);

View File

@ -52,6 +52,7 @@ INTERNAL SYS_EXIT_FUNC(resource_shutdown);
struct resource_startup_receipt resource_startup(void) struct resource_startup_receipt resource_startup(void)
{ {
__prof;
G.arena = arena_alloc(GIBI(64)); G.arena = arena_alloc(GIBI(64));
#if RESOURCES_EMBEDDED #if RESOURCES_EMBEDDED

View File

@ -62,6 +62,7 @@ READONLY struct sim_ent **_g_sim_ent_nil = &G.nil_ent;
struct sim_startup_receipt sim_startup(void) struct sim_startup_receipt sim_startup(void)
{ {
__prof;
G.nil_arena = arena_alloc(GIBI(1)); G.nil_arena = arena_alloc(GIBI(1));
/* Nil client store */ /* Nil client store */

View File

@ -51,6 +51,7 @@ GLOBAL struct {
struct sock_startup_receipt sock_startup(void) struct sock_startup_receipt sock_startup(void)
{ {
__prof;
/* Startup winsock */ /* Startup winsock */
WSAStartup(MAKEWORD(2, 2), &G.wsa_data); WSAStartup(MAKEWORD(2, 2), &G.wsa_data);
G.win32_socks_arena = arena_alloc(GIBI(64)); G.win32_socks_arena = arena_alloc(GIBI(64));

View File

@ -35,10 +35,9 @@ GLOBAL struct {
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr) struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr)
{ {
__prof;
(UNUSED)asset_cache_sr; (UNUSED)asset_cache_sr;
G.params.arena = arena_alloc(GIBI(64)); G.params.arena = arena_alloc(GIBI(64));
return (struct sound_startup_receipt) { 0 }; return (struct sound_startup_receipt) { 0 };
} }

View File

@ -210,6 +210,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, info);
struct sprite_startup_receipt sprite_startup(void) struct sprite_startup_receipt sprite_startup(void)
{ {
__prof;
G.perm_arena = arena_alloc(MEBI(1)); G.perm_arena = arena_alloc(MEBI(1));
{ {
/* Init loading texture */ /* Init loading texture */

View File

@ -49,13 +49,6 @@ void sys_wake(void *addr, i32 count);
i16 sys_current_fiber_id(void); i16 sys_current_fiber_id(void);
/* When a job reaches a 'sys_wait' statement, by default the fiber will yield to the job pool and potentially resume on a different thread.
* Call this function to disable this behavior for the remainder of the job, and instead force a blocking wait on the current thread.
*
* For example, a job that processes audio and runs until the end of the program can set thread priority and then call this function to
* ensure it will never switch off of the worker thread that it set thread priority for. */
void sys_make_current_job_unyielding(void);
/* ========================== * /* ========================== *
* Job * Job
* ========================== */ * ========================== */

View File

@ -159,10 +159,9 @@ struct alignas(64) fiber {
/* ==================================================== */ /* ==================================================== */
char *name_cstr; /* 08 bytes */ char *name_cstr; /* 08 bytes */
/* ==================================================== */ /* ==================================================== */
struct atomic16 wake_lock; /* 02 bytes (4 byte alignment) */ struct atomic32 wake_lock; /* 04 bytes (4 byte alignment) */
i16 id; /* 02 bytes */ i16 id; /* 02 bytes */
i16 parent_id; /* 02 bytes */ i16 parent_id; /* 02 bytes */
i16 unyielding; /* 02 bytes */
/* ==================================================== */ /* ==================================================== */
u64 wait_addr; /* 08 bytes */ u64 wait_addr; /* 08 bytes */
/* ==================================================== */ /* ==================================================== */
@ -173,10 +172,10 @@ struct alignas(64) fiber {
i16 next_time_waiter; /* 02 bytes */ i16 next_time_waiter; /* 02 bytes */
i16 prev_time_waiter; /* 02 bytes */ i16 prev_time_waiter; /* 02 bytes */
/* ==================================================== */ /* ==================================================== */
u8 _pad0[8]; /* 08 bytes (padding) */
/* ==================================================== */
u8 _pad1[8]; /* 08 bytes (padding) */ u8 _pad1[8]; /* 08 bytes (padding) */
/* ==================================================== */ /* ==================================================== */
u8 _pad2[8]; /* 08 bytes (padding) */
/* ==================================================== */
/* ==================== Cache line ==================== */ /* ==================== Cache line ==================== */
/* ==================================================== */ /* ==================================================== */
struct sys_scratch_ctx scratch_ctx; /* 16 bytes */ struct sys_scratch_ctx scratch_ctx; /* 16 bytes */
@ -193,7 +192,7 @@ struct alignas(64) fiber {
/* ==================================================== */ /* ==================================================== */
struct yield_param *yield_param; /* 08 bytes */ struct yield_param *yield_param; /* 08 bytes */
/* ==================================================== */ /* ==================================================== */
u8 _pad2[8]; /* 08 bytes (padding) */ u8 _pad3[8]; /* 08 bytes (padding) */
}; };
STATIC_ASSERT(sizeof(struct fiber) == 128); /* Padding validation (increase if necessary) */ STATIC_ASSERT(sizeof(struct fiber) == 128); /* Padding validation (increase if necessary) */
@ -442,7 +441,7 @@ void sys_wait(void *addr, void *cmp, u32 size, i64 timeout_ns)
{ {
struct fiber *fiber = fiber_from_id(sys_current_fiber_id()); struct fiber *fiber = fiber_from_id(sys_current_fiber_id());
i16 parent_id = fiber->parent_id; i16 parent_id = fiber->parent_id;
if (parent_id != 0 && !fiber->unyielding) { if (parent_id != 0) {
*fiber->yield_param = (struct yield_param) { *fiber->yield_param = (struct yield_param) {
.kind = YIELD_KIND_WAIT, .kind = YIELD_KIND_WAIT,
.wait = { .wait = {
@ -575,6 +574,8 @@ INTERNAL void wake_fibers_locked(i32 num_fibers, struct fiber **fibers)
fiber->prev_time_waiter = 0; fiber->prev_time_waiter = 0;
fiber->next_time_waiter = 0; fiber->next_time_waiter = 0;
} }
/* Unlock fiber */
atomic32_fetch_set(&fiber->wake_lock, 0);
} }
/* Unlock wait bins */ /* Unlock wait bins */
if (wait_time_bin != 0) tm_unlock(&wait_time_bin->lock); if (wait_time_bin != 0) tm_unlock(&wait_time_bin->lock);
@ -612,7 +613,6 @@ INTERNAL void wake_fibers_locked(i32 num_fibers, struct fiber **fibers)
queue->first = info; queue->first = info;
} }
queue->last = info; queue->last = info;
atomic16_fetch_set(&fiber->wake_lock, 0);
} }
tm_unlock(&queue->lock); tm_unlock(&queue->lock);
} }
@ -659,7 +659,7 @@ INTERNAL void wake_address(void *addr, i32 count)
if (wait_addr_list) { if (wait_addr_list) {
fibers = arena_push_array_no_zero(scratch.arena, struct fiber *, wait_addr_list->num_waiters); fibers = arena_push_array_no_zero(scratch.arena, struct fiber *, wait_addr_list->num_waiters);
for (struct fiber *fiber = fiber_from_id(wait_addr_list->first_waiter); fiber && num_fibers < count; fiber = fiber_from_id(fiber->next_addr_waiter)) { for (struct fiber *fiber = fiber_from_id(wait_addr_list->first_waiter); fiber && num_fibers < count; fiber = fiber_from_id(fiber->next_addr_waiter)) {
if (atomic16_fetch_test_set(&fiber->wake_lock, 0, 1) == 0) { if (atomic32_fetch_test_set(&fiber->wake_lock, 0, 1) == 0) {
fibers[num_fibers] = fiber; fibers[num_fibers] = fiber;
++num_fibers; ++num_fibers;
} }
@ -710,7 +710,7 @@ INTERNAL void wake_time(u64 time)
/* Set waiter wake status & build fibers list */ /* Set waiter wake status & build fibers list */
fibers = arena_push_array_no_zero(scratch.arena, struct fiber *, wait_time_list->num_waiters); fibers = arena_push_array_no_zero(scratch.arena, struct fiber *, wait_time_list->num_waiters);
for (struct fiber *fiber = fiber_from_id(wait_time_list->first_waiter); fiber; fiber = fiber_from_id(fiber->next_time_waiter)) { for (struct fiber *fiber = fiber_from_id(wait_time_list->first_waiter); fiber; fiber = fiber_from_id(fiber->next_time_waiter)) {
if (atomic16_fetch_test_set(&fiber->wake_lock, 0, 1) == 0) { if (atomic32_fetch_test_set(&fiber->wake_lock, 0, 1) == 0) {
fibers[num_fibers] = fiber; fibers[num_fibers] = fiber;
++num_fibers; ++num_fibers;
} }
@ -812,7 +812,6 @@ INTERNAL struct fiber *fiber_alloc(struct job_pool *pool)
fiber->addr = ConvertThreadToFiber((void *)(i64)fiber_id); fiber->addr = ConvertThreadToFiber((void *)(i64)fiber_id);
} }
} }
MEMZERO_STRUCT(&fiber->wake_lock);
fiber->wait_addr = 0; fiber->wait_addr = 0;
fiber->wait_time = 0; fiber->wait_time = 0;
fiber->prev_addr_waiter = 0; fiber->prev_addr_waiter = 0;
@ -827,7 +826,6 @@ INTERNAL struct fiber *fiber_alloc(struct job_pool *pool)
fiber->job_counter = 0; fiber->job_counter = 0;
fiber->yield_param = 0; fiber->yield_param = 0;
fiber->parent_id = 0; fiber->parent_id = 0;
fiber->unyielding = 0;
return fiber; return fiber;
} }
@ -860,11 +858,6 @@ i16 sys_current_fiber_id(void)
return (i16)(i64)GetFiberData(); return (i16)(i64)GetFiberData();
} }
void sys_make_current_job_unyielding(void)
{
fiber_from_id(sys_current_fiber_id())->unyielding = 1;
}
void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_pool pool_kind, enum sys_priority priority, struct snc_counter *counter) void sys_run(i32 count, sys_job_func *func, void *sig, enum sys_pool pool_kind, enum sys_priority priority, struct snc_counter *counter)
{ {
if (count > 0) { if (count > 0) {
@ -926,7 +919,7 @@ INTERNAL void job_fiber_yield(struct fiber *fiber, struct fiber *parent_fiber)
MemoryBarrier(); MemoryBarrier();
SwitchToFiber(parent_fiber->addr); SwitchToFiber(parent_fiber->addr);
MemoryBarrier(); MemoryBarrier();
__prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - MEBI(fiber->job_pool) + fiber->id + 1); __prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - MEBI(fiber->job_pool) + KIBI(1) + fiber->id);
} }
} }
@ -945,7 +938,7 @@ INTERNAL void job_fiber_entry(void *id_ptr)
{ {
i16 id = (i32)(i64)id_ptr; i16 id = (i32)(i64)id_ptr;
struct fiber *fiber = fiber_from_id(id); struct fiber *fiber = fiber_from_id(id);
__prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - MEBI(fiber->job_pool) + fiber->id + 1); __prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - MEBI(fiber->job_pool) + KIBI(1) + fiber->id);
for (;;) { for (;;) {
/* Run job */ /* Run job */
{ {
@ -1086,12 +1079,10 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
} }
job_fiber_id = job_fiber->id; job_fiber_id = job_fiber->id;
{ {
//__profnc("Run fiber", RGB32_F(0.25, 0.75, 0));
__profnc("Run fiber", RGB32_F(1, 1, 1)); __profnc("Run fiber", RGB32_F(1, 1, 1));
__profvalue(job_fiber->id); __profvalue(job_fiber->id);
struct yield_param yield = ZI; struct yield_param yield = ZI;
job_fiber->parent_id = worker_fiber_id; job_fiber->parent_id = worker_fiber_id;
job_fiber->unyielding = 0;
job_fiber->job_func = job_func; job_fiber->job_func = job_func;
job_fiber->job_sig = job_sig; job_fiber->job_sig = job_sig;
job_fiber->job_id = job_id; job_fiber->job_id = job_id;
@ -1365,7 +1356,7 @@ INTERNAL SYS_THREAD_DEF(test_entry, _)
case SYS_POOL_SIM: case SYS_POOL_SIM:
{ {
name_fmt = LIT("Sim worker #%F"); name_fmt = LIT("Sim worker #%F");
pool->thread_affinity_mask = 0x000000000000000Full; //pool->thread_affinity_mask = 0x000000000000000Full;
pool->thread_priority = THREAD_PRIORITY_TIME_CRITICAL; pool->thread_priority = THREAD_PRIORITY_TIME_CRITICAL;
pool->num_worker_threads = 4; pool->num_worker_threads = 4;
} break; } break;
@ -1373,7 +1364,7 @@ INTERNAL SYS_THREAD_DEF(test_entry, _)
case SYS_POOL_USER: case SYS_POOL_USER:
{ {
name_fmt = LIT("User worker #%F"); name_fmt = LIT("User worker #%F");
pool->thread_affinity_mask = 0x00000000000000F0ull; //pool->thread_affinity_mask = 0x00000000000000F0ull;
pool->thread_priority = THREAD_PRIORITY_TIME_CRITICAL; pool->thread_priority = THREAD_PRIORITY_TIME_CRITICAL;
pool->num_worker_threads = 4; pool->num_worker_threads = 4;
} break; } break;
@ -1381,7 +1372,7 @@ INTERNAL SYS_THREAD_DEF(test_entry, _)
case SYS_POOL_AUDIO: case SYS_POOL_AUDIO:
{ {
name_fmt = LIT("Audio worker #%F"); name_fmt = LIT("Audio worker #%F");
pool->thread_affinity_mask = 0x0000000000000300ull; //pool->thread_affinity_mask = 0x0000000000000300ull;
pool->thread_priority = THREAD_PRIORITY_TIME_CRITICAL; pool->thread_priority = THREAD_PRIORITY_TIME_CRITICAL;
pool->thread_mm_characteristics = "Pro Audio"; pool->thread_mm_characteristics = "Pro Audio";
pool->num_worker_threads = 2; pool->num_worker_threads = 2;
@ -1390,14 +1381,14 @@ INTERNAL SYS_THREAD_DEF(test_entry, _)
case SYS_POOL_BACKGROUND: case SYS_POOL_BACKGROUND:
{ {
name_fmt = LIT("Background worker #%F"); name_fmt = LIT("Background worker #%F");
pool->thread_affinity_mask = 0x0000000000000C00ull; //pool->thread_affinity_mask = 0x0000000000000C00ull;
pool->num_worker_threads = 2; pool->num_worker_threads = 2;
} break; } break;
case SYS_POOL_FLOATING: case SYS_POOL_FLOATING:
{ {
name_fmt = LIT("Floating worker #%F"); name_fmt = LIT("Floating worker #%F");
pool->thread_affinity_mask = 0x0000000000000FFFull; //pool->thread_affinity_mask = 0x0000000000000FFFull;
pool->thread_priority = 0; pool->thread_priority = 0;
pool->num_worker_threads = 8; pool->num_worker_threads = 8;
} break; } break;

View File

@ -49,6 +49,7 @@ INTERNAL i32 round_up(f32 x)
/* Call this during font system startup */ /* Call this during font system startup */
struct ttf_startup_receipt ttf_startup(void) struct ttf_startup_receipt ttf_startup(void)
{ {
__prof;
ASSERT(!G.factory); ASSERT(!G.factory);
/* FIXME: I think IDWriteFactory5 only exists on later updates of windows /* FIXME: I think IDWriteFactory5 only exists on later updates of windows
* 10? Need to verify. Maybe should just use a custom loader. (We're only * 10? Need to verify. Maybe should just use a custom loader. (We're only

View File

@ -206,6 +206,7 @@ struct user_startup_receipt user_startup(struct font_startup_receipt *font_sr,
struct sim_startup_receipt *sim_sr, struct sim_startup_receipt *sim_sr,
struct string connect_address_str) struct string connect_address_str)
{ {
__prof;
(UNUSED)font_sr; (UNUSED)font_sr;
(UNUSED)sprite_sr; (UNUSED)sprite_sr;
(UNUSED)draw_sr; (UNUSED)draw_sr;