diff --git a/src/base/base.h b/src/base/base.h index de65fc8b..1af18dbe 100644 --- a/src/base/base.h +++ b/src/base/base.h @@ -713,7 +713,11 @@ Struct(ComputeShader) { Resource resource; }; //////////////////////////////// //~ Fibers -#define VirtualFibersEnabled 0 +/* If virtual fibers are enabled, each fiber will get its own OS thread, + * and fiber suspend/resume will be emulated using OS thread primitives. + * This is slow but allows for easier debugging in tricky cases + * since the debugger won't be confused by fiber context switching. */ +#define VirtualFibersEnabled 1 # define MaxFibers 4096 StaticAssert(MaxFibers < I16Max); /* MaxFibers should fit in FiberId */ diff --git a/src/base/base_job.h b/src/base/base_job.h index 8029e717..e0bf72f8 100644 --- a/src/base/base_job.h +++ b/src/base/base_job.h @@ -71,7 +71,7 @@ void InitJobSystem(void); //~ @hookdecl Fiber suspend/resume operations void SuspendFiber(void); -void ResumeFibers(i16 fiber_ids_count, i16 *fiber_ids); +void ResumeFibers(i16 fiber_ids_count, i16 *fiber_ids); /* NOTE: Must only be called on fibers suspended via SuspendFiber */ //////////////////////////////// //~ @hookdecl Job declaration operations @@ -102,17 +102,35 @@ void ResumeFibers(i16 fiber_ids_count, i16 *fiber_ids); * } * */ -#define RunJob(name, ...) \ +#define RunJob(job_func, ...) \ do { \ - name##_Desc __desc = { .count = 1, .pool = JobPool_Inherit, .func = name, __VA_ARGS__ }; \ + job_func##_Desc __desc = { .count = 1, .pool = JobPool_Inherit, .func = job_func, __VA_ARGS__ }; \ Job *__job = OpenJob(__desc.func, __desc.pool); \ __job->count = __desc.count; \ __job->counter = __desc.counter; \ - __job->sig = PushStructNoZero(__job->arena, name##_Sig); \ + __job->sig = PushStructNoZero(__job->arena, job_func##_Sig); \ CopyBytes(__job->sig, &__desc.sig, sizeof(__desc.sig)); \ CloseJob(__job); \ } while (0) Job *OpenJob(JobFunc *func, JobPool pool_kind); void CloseJob(Job *job); + #define YieldOnJobs(counter) (YieldOnFence(&(counter)->num_jobs_completed_fence, Atomic64Fetch(&(counter)->num_jobs_dispatched.v))) + +//////////////////////////////// +//~ @hookdecl Dedicated job operations + +/* A dedicated job is a heavy weight job that will not operate inside of any + * job pool. As such, it receives its own dedicated thread, and never yields to + * other fibers. Instead of yielding when the fiber suspends, it performs a blocking + * wait that puts the OS thread to sleep. This is mainly useful for + * implementing long-running blocking dispatcher-like jobs tasks for subsystems. + * + * For example, Win32 window message processing is required by the OS to occur + * on the same thread that initially created the window, which means it + * actually must run in a dedicated to prevent message processing from yielding + * & resuming on another thread. + */ + +void RunDedicatedJob(JobFunc job_func); diff --git a/src/base/base_win32/base_win32_job.c b/src/base/base_win32/base_win32_job.c index 04eabf35..9b8d135e 100644 --- a/src/base/base_win32/base_win32_job.c +++ b/src/base/base_win32/base_win32_job.c @@ -569,6 +569,7 @@ void SuspendFiber(void) __prof_fiber_enter(fiber->name_cstr, PROF_THREAD_GROUP_FIBERS - Mebi(fiber->pool) + Kibi(1) + fiber->id); } +/* NOTE: Must only be called on fibers suspended via SuspendFiber */ void ResumeFibers(i16 fiber_ids_count, i16 *fiber_ids) { __prof; @@ -785,3 +786,12 @@ void CloseJob(Job *job) EndScratch(scratch); } + +//////////////////////////////// +//~ @hookdef Dedicated job operations + +void RunDedicatedJob(JobFunc job_func) +{ + /* TODO: Implement */ + Assert(0); +}