separate fiber free lists by job pool
This commit is contained in:
parent
e13aca535a
commit
047f5c8359
@ -240,6 +240,9 @@ struct alignas(64) job_pool {
|
|||||||
/* Jobs */
|
/* Jobs */
|
||||||
struct job_queue job_queues[NUM_SYS_PRIORITIES];
|
struct job_queue job_queues[NUM_SYS_PRIORITIES];
|
||||||
|
|
||||||
|
struct ticket_mutex free_fibers_lock;
|
||||||
|
i16 first_free_fiber_id;
|
||||||
|
|
||||||
/* Workers */
|
/* Workers */
|
||||||
struct atomic32_padded workers_shutdown;
|
struct atomic32_padded workers_shutdown;
|
||||||
struct atomic64_padded num_jobs_in_queue;
|
struct atomic64_padded num_jobs_in_queue;
|
||||||
@ -304,10 +307,9 @@ GLOBAL struct {
|
|||||||
struct atomic64_padded current_scheduler_cycle_period_ns;
|
struct atomic64_padded current_scheduler_cycle_period_ns;
|
||||||
|
|
||||||
/* Fibers */
|
/* Fibers */
|
||||||
i16 num_fibers;
|
|
||||||
i16 first_free_fiber_id;
|
|
||||||
struct arena *fiber_names_arena;
|
|
||||||
struct ticket_mutex fibers_lock;
|
struct ticket_mutex fibers_lock;
|
||||||
|
i16 num_fibers;
|
||||||
|
struct arena *fiber_names_arena;
|
||||||
struct fiber fibers[SYS_MAX_FIBERS];
|
struct fiber fibers[SYS_MAX_FIBERS];
|
||||||
|
|
||||||
/* Wait lists */
|
/* Wait lists */
|
||||||
@ -608,7 +610,7 @@ INTERNAL void wake_address(void *addr, i32 count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock & build fibers array */
|
/* Lock fibers & build array */
|
||||||
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)) {
|
||||||
@ -622,7 +624,9 @@ INTERNAL void wake_address(void *addr, i32 count)
|
|||||||
tm_unlock(&wait_addr_bin->lock);
|
tm_unlock(&wait_addr_bin->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (num_fibers > 0) {
|
||||||
wake_fibers_locked(num_fibers, fibers);
|
wake_fibers_locked(num_fibers, fibers);
|
||||||
|
}
|
||||||
|
|
||||||
/* Wake win32 blocking thread waiters */
|
/* Wake win32 blocking thread waiters */
|
||||||
if (count >= WAKE_ALL_THRESHOLD) {
|
if (count >= WAKE_ALL_THRESHOLD) {
|
||||||
@ -686,26 +690,28 @@ void sys_wake(void *addr, i32 count)
|
|||||||
* Fibers
|
* Fibers
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
enum fiber_kind {
|
|
||||||
FIBER_KIND_CONVERTED_THREAD,
|
|
||||||
FIBER_KIND_JOB_WORKER
|
|
||||||
};
|
|
||||||
|
|
||||||
INTERNAL void job_fiber_entry(void *id_ptr);
|
INTERNAL void job_fiber_entry(void *id_ptr);
|
||||||
|
|
||||||
INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
/* If `pool` is 0, then the currently running thread will be converted into a fiber */
|
||||||
|
INTERNAL struct fiber *fiber_alloc(struct job_pool *pool)
|
||||||
{
|
{
|
||||||
i16 fiber_id = 0;
|
i16 fiber_id = 0;
|
||||||
struct fiber *fiber = 0;
|
struct fiber *fiber = 0;
|
||||||
char *new_name_cstr = 0;
|
char *new_name_cstr = 0;
|
||||||
{
|
{
|
||||||
|
if (pool != 0) {
|
||||||
|
tm_lock(&pool->free_fibers_lock);
|
||||||
|
if (pool->first_free_fiber_id) {
|
||||||
|
fiber_id = pool->first_free_fiber_id;
|
||||||
|
fiber = &G.fibers[fiber_id];
|
||||||
|
pool->first_free_fiber_id = fiber->parent_id;
|
||||||
|
}
|
||||||
|
tm_unlock(&pool->free_fibers_lock);
|
||||||
|
}
|
||||||
|
if (!fiber_id) {
|
||||||
tm_lock(&G.fibers_lock);
|
tm_lock(&G.fibers_lock);
|
||||||
{
|
{
|
||||||
fiber_id = G.first_free_fiber_id;
|
{
|
||||||
if (fiber_id && kind == FIBER_KIND_JOB_WORKER) {
|
|
||||||
fiber = &G.fibers[fiber_id];
|
|
||||||
G.first_free_fiber_id = fiber->parent_id;
|
|
||||||
} else {
|
|
||||||
fiber_id = G.num_fibers++;
|
fiber_id = G.num_fibers++;
|
||||||
if (fiber_id >= SYS_MAX_FIBERS) {
|
if (fiber_id >= SYS_MAX_FIBERS) {
|
||||||
sys_panic(LIT("Max fibers reached"));
|
sys_panic(LIT("Max fibers reached"));
|
||||||
@ -716,6 +722,8 @@ INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
|||||||
}
|
}
|
||||||
tm_unlock(&G.fibers_lock);
|
tm_unlock(&G.fibers_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if (new_name_cstr != 0) {
|
if (new_name_cstr != 0) {
|
||||||
fiber->id = fiber_id;
|
fiber->id = fiber_id;
|
||||||
|
|
||||||
@ -752,10 +760,11 @@ INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
|||||||
fiber->name_cstr = new_name_cstr;
|
fiber->name_cstr = new_name_cstr;
|
||||||
|
|
||||||
/* Init win32 fiber */
|
/* Init win32 fiber */
|
||||||
if (kind == FIBER_KIND_JOB_WORKER) {
|
if (pool != 0) {
|
||||||
fiber->addr = CreateFiber(FIBER_STACK_SIZE, job_fiber_entry, (void *)(i64)fiber_id);
|
fiber->addr = CreateFiber(FIBER_STACK_SIZE, job_fiber_entry, (void *)(i64)fiber_id);
|
||||||
fiber->can_yield = 1;
|
fiber->can_yield = 1;
|
||||||
} else {
|
} else {
|
||||||
|
/* Fiber is not a part of a job pool, convert thread to fiber */
|
||||||
fiber->addr = ConvertThreadToFiber((void *)(i64)fiber_id);
|
fiber->addr = ConvertThreadToFiber((void *)(i64)fiber_id);
|
||||||
fiber->can_yield = 0;
|
fiber->can_yield = 0;
|
||||||
}
|
}
|
||||||
@ -778,14 +787,14 @@ INTERNAL struct fiber *fiber_alloc(enum fiber_kind kind)
|
|||||||
return fiber;
|
return fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void fiber_release(struct fiber *fiber, i16 fiber_id)
|
INTERNAL void fiber_release(struct job_pool *pool, struct fiber *fiber, i16 fiber_id)
|
||||||
{
|
{
|
||||||
tm_lock(&G.fibers_lock);
|
tm_lock(&pool->free_fibers_lock);
|
||||||
{
|
{
|
||||||
fiber->parent_id = G.first_free_fiber_id;
|
fiber->parent_id = pool->first_free_fiber_id;
|
||||||
G.first_free_fiber_id = fiber_id;
|
pool->first_free_fiber_id = fiber_id;
|
||||||
}
|
}
|
||||||
tm_unlock(&G.fibers_lock);
|
tm_unlock(&pool->free_fibers_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE struct fiber *fiber_from_id(i16 id)
|
FORCE_INLINE struct fiber *fiber_from_id(i16 id)
|
||||||
@ -1007,7 +1016,7 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
|
|||||||
/* Use resumed fiber if present */
|
/* Use resumed fiber if present */
|
||||||
if (job_fiber_id > 0) {
|
if (job_fiber_id > 0) {
|
||||||
if (job_fiber) {
|
if (job_fiber) {
|
||||||
fiber_release(job_fiber, job_fiber->id);
|
fiber_release(pool, job_fiber, job_fiber->id);
|
||||||
}
|
}
|
||||||
job_fiber = fiber_from_id(job_fiber_id);
|
job_fiber = fiber_from_id(job_fiber_id);
|
||||||
}
|
}
|
||||||
@ -1015,7 +1024,7 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
|
|||||||
/* Run fiber */
|
/* Run fiber */
|
||||||
if (job_func) {
|
if (job_func) {
|
||||||
if (!job_fiber) {
|
if (!job_fiber) {
|
||||||
job_fiber = fiber_alloc(FIBER_KIND_JOB_WORKER);
|
job_fiber = fiber_alloc(pool);
|
||||||
}
|
}
|
||||||
job_fiber_id = job_fiber->id;
|
job_fiber_id = job_fiber->id;
|
||||||
{
|
{
|
||||||
@ -2881,7 +2890,7 @@ INTERNAL void win32_thread_release(struct win32_thread *t)
|
|||||||
|
|
||||||
INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
|
INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
|
||||||
{
|
{
|
||||||
fiber_alloc(FIBER_KIND_CONVERTED_THREAD);
|
fiber_alloc(0);
|
||||||
|
|
||||||
struct win32_thread *t = (struct win32_thread *)vt;
|
struct win32_thread *t = (struct win32_thread *)vt;
|
||||||
__profthread(t->thread_name_cstr, t->profiler_group);
|
__profthread(t->thread_name_cstr, t->profiler_group);
|
||||||
@ -3235,7 +3244,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
G.wait_lists_arena = arena_alloc(GIBI(64));
|
G.wait_lists_arena = arena_alloc(GIBI(64));
|
||||||
|
|
||||||
/* Convert main thread to fiber */
|
/* Convert main thread to fiber */
|
||||||
fiber_alloc(FIBER_KIND_CONVERTED_THREAD);
|
fiber_alloc(0);
|
||||||
|
|
||||||
/* Init job pools */
|
/* Init job pools */
|
||||||
for (enum sys_pool pool_kind = 0; pool_kind < (i32)countof(G.job_pools); ++pool_kind) {
|
for (enum sys_pool pool_kind = 0; pool_kind < (i32)countof(G.job_pools); ++pool_kind) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user