commit 226bb5e88513b3e78d3a30b84b5368b69bca8d26 parent 0d9583a7aed34d8d1e55830a11ba636c80e831ea Author: Michael Savage <mikejsavage@gmail.com> Date: Wed Sep 2 22:30:51 +0200 Give each work queue thread a memory arena to play with Diffstat:
hm.cc | | | 4 | ++-- |
work_queue.cc | | | 34 | +++++++++++++++++++++++++++------- |
work_queue.h | | | 8 | ++++++-- |
diff --git a/hm.cc b/hm.cc @@ -92,7 +92,7 @@ glm::mat4 P( glm::perspective( glm::radians( 120.0f ), 640.0f / 480.0f, 0.1f, 10 static WORK_QUEUE_CALLBACK( testwq ) { u32 i = *( u32 * ) data; - printf( "the thread got called %u\n", i ); + printf( "work %u called with arena %p\n", i, arena->memory ); } extern "C" GAME_INIT( game_init ) { @@ -101,7 +101,7 @@ extern "C" GAME_INIT( game_init ) { terrain_init( &state->tm, "Srtm_ramp2.world.21600x10800.jpg.parts" ); terrain_teleport( &state->tm, state->pos ); - workqueue_init( &state->background_tasks, 2 ); + workqueue_init( &state->background_tasks, &mem->persistent_arena, 2 ); u32 nums[ 10 ]; for( u32 i = 0; i < 10; i++ ) { nums[ i ] = i; diff --git a/work_queue.cc b/work_queue.cc @@ -6,14 +6,19 @@ #include "platform_barrier.h" #include "platform_semaphore.h" -static bool workqueue_step( WorkQueue * const queue ) { +struct ThreadIDAndWorkQueue { + u32 thread_id; + WorkQueue * queue; +}; + +static bool workqueue_step( const u32 thread_id, WorkQueue * const queue ) { const u16 current_head = queue->head; const u16 new_head = ( current_head + 1 ) % array_count( queue->jobs ); if( current_head != queue->tail ) { if( __sync_bool_compare_and_swap( &queue->head, current_head, new_head ) ) { const Job & job = queue->jobs[ current_head ]; - job.callback( job.data ); + job.callback( job.data, &queue->arenas[ thread_id ] ); __sync_fetch_and_add( &queue->jobs_completed, 1 ); } @@ -25,10 +30,11 @@ static bool workqueue_step( WorkQueue * const queue ) { } static void * workqueue_worker( void * const data ) { - WorkQueue * const queue = ( WorkQueue * const ) data; + ThreadIDAndWorkQueue * const idq = ( ThreadIDAndWorkQueue * const ) data; + WorkQueue * const queue = idq->queue; for( ;; ) { - if( !workqueue_step( queue ) ) { + if( !workqueue_step( idq->thread_id, queue ) ) { semaphore_wait( &queue->sem ); } } @@ -36,14 +42,28 @@ static void * workqueue_worker( void * const data ) { return nullptr; } -void workqueue_init( WorkQueue * const queue, const u32 num_threads ) { +void workqueue_init( WorkQueue * const queue, MemoryArena * const arena, const u32 num_threads ) { *queue = { }; semaphore_init( &queue->sem ); + queue->num_threads = num_threads; + queue->arenas = memarena_push_many( arena, MemoryArena, num_threads + 1 ); + + for( u32 i = 0; i <= num_threads; i++ ) { + queue->arenas[ i ] = memarena_push_arena( arena, megabytes( 1 ) ); + } + + MemoryArenaCheckpoint cp = memarena_checkpoint( arena ); + ThreadIDAndWorkQueue * idqs = memarena_push_many( arena, ThreadIDAndWorkQueue, num_threads ); + for( u32 i = 0; i < num_threads; i++ ) { + idqs[ i ] = { i, queue }; + pthread_t thread; - pthread_create( &thread, nullptr, workqueue_worker, queue ); + pthread_create( &thread, nullptr, workqueue_worker, &idqs[ i ] ); } + + memarena_restore( arena, &cp ); } void workqueue_enqueue( WorkQueue * const queue, WorkQueueCallback * const callback, void * const data ) { @@ -62,7 +82,7 @@ void workqueue_enqueue( WorkQueue * const queue, WorkQueueCallback * const callb void workqueue_exhaust( WorkQueue * const queue ) { while( queue->jobs_completed < queue->jobs_queued ) { - workqueue_step( queue ); + workqueue_step( queue->num_threads, queue ); } queue->jobs_queued = 0; diff --git a/work_queue.h b/work_queue.h @@ -3,8 +3,9 @@ #include "intrinsics.h" #include "platform_semaphore.h" +#include "memory_arena.h" -#define WORK_QUEUE_CALLBACK( name ) void name( void * const data ) +#define WORK_QUEUE_CALLBACK( name ) void name( void * const data, MemoryArena * const arena ) typedef WORK_QUEUE_CALLBACK( WorkQueueCallback ); struct Job { @@ -23,9 +24,12 @@ struct WorkQueue { volatile u16 jobs_queued; volatile u16 jobs_completed; + + u32 num_threads; + MemoryArena * arenas; }; -void workqueue_init( WorkQueue * const queue, const u32 num_threads ); +void workqueue_init( WorkQueue * const queue, MemoryArena * const arena, const u32 num_threads ); void workqueue_enqueue( WorkQueue * const queue, WorkQueueCallback * const callback, void * const data ); void workqueue_exhaust( WorkQueue * const queue );