medfall

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 5a169f4740c2cb981408124747df74b9124c7344
parent fbe948572d1759ec18a88f65e452f8ba390f7dda
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sat Sep 19 21:28:18 +0100

Add platform_atomic and platform_thread

Diffstat:
game.h | 3+++
platform_atomic.h | 8++++++++
platform_thread.h | 8++++++++
unix_atomic.cc | 37+++++++++++++++++++++++++++++++++++++
unix_thread.cc | 13+++++++++++++
work_queue.cc | 18+++++++-----------
6 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/game.h b/game.h @@ -8,6 +8,9 @@ // bounded arithmetic classes? - easy/medium // would be used in terrain manager // +// platform +// platform specific mutexes - easy +// // rendering // textures - easy/medium // unify the renderers - hard diff --git a/platform_atomic.h b/platform_atomic.h @@ -0,0 +1,8 @@ +#ifndef _PLATFORM_ATOMIC_H_ +#define _PLATFORM_ATOMIC_H_ + +#if defined(__linux__) || defined(__APPLE__) +#include "unix_atomic.cc" +#endif + +#endif // _PLATFORM_ATOMIC_H_ diff --git a/platform_thread.h b/platform_thread.h @@ -0,0 +1,8 @@ +#ifndef _PLATFORM_THREAD_H_ +#define _PLATFORM_THREAD_H_ + +#if defined(__linux__) || defined(__APPLE__) +#include "unix_thread.cc" +#endif + +#endif // _PLATFORM_THREAD_H_ diff --git a/unix_atomic.cc b/unix_atomic.cc @@ -0,0 +1,37 @@ +#include "intrinsics.h" + +inline u8 atomic_add_u8( volatile u8 * dest, u8 i ) { + return __sync_add_and_fetch( dest, i ); +} + +inline u16 atomic_add_u16( volatile u16 * dest, u16 i ) { + return __sync_add_and_fetch( dest, i ); +} + +inline u32 atomic_add_u32( volatile u32 * dest, u32 i ) { + return __sync_add_and_fetch( dest, i ); +} + +inline u64 atomic_add_u64( volatile u64 * dest, u64 i ) { + return __sync_add_and_fetch( dest, i ); +} + +inline bool atomic_cas_u8( volatile u8 * dest, u8 oldval, u8 newval ) { + return __sync_bool_compare_and_swap( dest, oldval, newval ); +} + +inline bool atomic_cas_u16( volatile u16 * dest, u16 oldval, u16 newval ) { + return __sync_bool_compare_and_swap( dest, oldval, newval ); +} + +inline bool atomic_cas_u32( volatile u32 * dest, u32 oldval, u32 newval ) { + return __sync_bool_compare_and_swap( dest, oldval, newval ); +} + +inline bool atomic_cas_u64( volatile u64 * dest, u64 oldval, u64 newval ) { + return __sync_bool_compare_and_swap( dest, oldval, newval ); +} + +inline bool atomic_cas_pointer( volatile void ** dest, void * oldval, void * newval ) { + return __sync_bool_compare_and_swap( dest, oldval, newval ); +} diff --git a/unix_thread.cc b/unix_thread.cc @@ -0,0 +1,13 @@ +#include <err.h> +#include <pthread.h> + +struct Thread { + pthread_t pthread; +}; + +inline void thread_init( Thread * thread, void * callback( void * ), void * data ) { + const int ok = pthread_create( &thread->pthread, nullptr, callback, data ); + if( ok == -1 ) { + err( 1, "pthread_create failed" ); + } +} diff --git a/work_queue.cc b/work_queue.cc @@ -1,9 +1,8 @@ -#include <err.h> -#include <pthread.h> - #include "intrinsics.h" #include "work_queue.h" #include "platform_barrier.h" +#include "platform_thread.h" +#include "platform_atomic.h" #include "platform_semaphore.h" struct ThreadInfo { @@ -17,11 +16,11 @@ static bool workqueue_step( const u32 thread_id, WorkQueue * const queue ) { 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 ) ) { + if( atomic_cas_u16( &queue->head, current_head, new_head ) ) { const Job & job = queue->jobs[ current_head ]; job.callback( job.data, &queue->arenas[ thread_id ] ); - __sync_fetch_and_add( &queue->jobs_completed, 1 ); + atomic_add_u16( &queue->jobs_completed, 1 ); } return true; @@ -37,7 +36,7 @@ static void * workqueue_worker( void * const data ) { const u32 thread_id = info->thread_id; write_barrier(); - __sync_fetch_and_add( info->started_threads, 1 ); + atomic_add_u32( info->started_threads, 1 ); for( ;; ) { if( !workqueue_step( thread_id, queue ) ) { @@ -66,11 +65,8 @@ void workqueue_init( WorkQueue * const queue, MemoryArena * const arena, const u for( u32 i = 0; i < num_threads; i++ ) { infos[ i ] = { i, queue, &started_threads }; - pthread_t thread; - const int ok = pthread_create( &thread, nullptr, workqueue_worker, &infos[ i ] ); - if( ok == -1 ) { - err( 1, "pthread_create" ); - } + Thread thread; + thread_init( &thread, workqueue_worker, &infos[ i ] ); } // wait until all threads have a local copy of ThreadInfo