power_play/src/base/base_job.h
2025-08-05 13:48:49 -05:00

99 lines
2.9 KiB
C

////////////////////////////////
//~ Job queue types
/* Work pools contain their own worker threads with their own thread priority
* affinity based on the intended context of the pool. */
typedef i32 JobPool; enum
{
JobPool_Inherit = -1,
/* The floating pool contains a large number of lower priority worker
* threads that have affinity over the entire CPU. Other pools should push
* jobs that only block and do no work here so that they can yield on the
* blocking job rather than blocking themselves. */
JobPool_Floating = 0,
JobPool_Background = 1,
JobPool_Audio = 2,
JobPool_User = 3,
JobPool_Sim = 4,
JobPool_Count
};
/* Job execution order within a pool is based on priority. */
typedef i32 JobPriority; enum
{
JobPriority_Inherit = -1,
JobPriority_High = 0,
JobPriority_Normal = 1,
JobPriority_Low = 2,
JobPriority_Count
};
////////////////////////////////
//~ @hookdecl Startup
void StartupBaseJobs(void);
////////////////////////////////
//~ @hookdecl Futex
/* Futex-like wait & wake */
void FutexWait(volatile void *addr, void *cmp, u32 size, i64 timeout_ns);
void FutexWake(void *addr, i32 count);
////////////////////////////////
//~ @hookdecl Job helpers
#define EmptySig { i32 _; }
typedef void GenericJobFunc(void *, i32);
Struct(GenericJobDesc)
{
Arena *arena;
void *sig;
GenericJobFunc *func;
i32 count;
JobPool pool;
JobPriority priority;
Counter *counter;
};
Struct(JobDescParams)
{
i32 count;
JobPool pool;
JobPriority priority;
Counter *counter;
};
#define JobDecl(job, sigdef) \
typedef struct job##_Sig sigdef job##_Sig; \
Struct(job##_Desc) { Arena *arena; job##_Sig *sig; GenericJobFunc *func; i32 count; JobPool pool; JobPriority priority; Counter *counter; }; \
void job(job##_Sig *, i32); \
inline void job##_Generic(void *sig, i32 id) { job((job##_Sig *)sig, id); } \
StaticAssert(1)
#define PushJobDesc(job, ...) (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), job##_Generic, (JobDescParams) { .count = 1, .pool = JobPool_Inherit, .priority = JobPriority_Inherit, .counter = 0, __VA_ARGS__ })
GenericJobDesc *PushJobDesc_(u64 sig_size, u64 sig_align, GenericJobFunc *func, JobDescParams params);
#define JobDef(job, sig_arg, id_arg) void job(job##_Sig *sig_arg, i32 id_arg)
#define RunJob(_count, job, _pool, _priority, _counter, ...) do { \
job##_Desc *__job_desc = (job##_Desc *)PushJobDesc_(sizeof(job##_Sig), alignof(job##_Sig), job##_Generic, (JobDescParams) { .count = _count, .pool = _pool, .priority = _priority, .counter = _counter,}); \
*__job_desc->sig = (job##_Sig) { __VA_ARGS__ }; \
RunJobEx((GenericJobDesc *)__job_desc); \
} while (0)
void RunJobEx(GenericJobDesc *desc);
////////////////////////////////
//~ @hookdecl Helpers
i64 TimeNs(void);
u32 ThreadId(void);
u32 GetLogicalProcessorCount(void);
i64 GetCurrentSchedulerPeriodNs(void);