more fleshed out atomics for i32, i64, u32, u64
This commit is contained in:
parent
edadca820a
commit
3b0cdfd1f4
@ -144,6 +144,7 @@ target_precompile_headers(powerplay_exe PRIVATE src/common.h)
|
|||||||
# Common flags
|
# Common flags
|
||||||
set(COMPILER_FLAGS "
|
set(COMPILER_FLAGS "
|
||||||
-fno-strict-aliasing \
|
-fno-strict-aliasing \
|
||||||
|
-fno-finite-loops \
|
||||||
-msse4.2 \
|
-msse4.2 \
|
||||||
")
|
")
|
||||||
|
|
||||||
|
|||||||
BIN
res/graphics/crosshair.ase
(Stored with Git LFS)
BIN
res/graphics/crosshair.ase
(Stored with Git LFS)
Binary file not shown.
@ -56,12 +56,14 @@ INTERNAL void refresh_dbg_table(void)
|
|||||||
{
|
{
|
||||||
#if RTC
|
#if RTC
|
||||||
sys_mutex_lock(&L.dbg_table_mutex);
|
sys_mutex_lock(&L.dbg_table_mutex);
|
||||||
MEMZERO_ARRAY(L.dbg_table);
|
{
|
||||||
L.dbg_table_count = 0;
|
MEMZERO_ARRAY(L.dbg_table);
|
||||||
for (u64 i = 0; i < ARRAY_COUNT(L.lookup); ++i) {
|
L.dbg_table_count = 0;
|
||||||
struct asset *asset = &L.lookup[i];
|
for (u64 i = 0; i < ARRAY_COUNT(L.lookup); ++i) {
|
||||||
if (asset->hash != 0) {
|
struct asset *asset = &L.lookup[i];
|
||||||
L.dbg_table[L.dbg_table_count++] = asset;
|
if (asset->hash != 0) {
|
||||||
|
L.dbg_table[L.dbg_table_count++] = asset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.dbg_table_mutex);
|
sys_mutex_unlock(&L.dbg_table_mutex);
|
||||||
|
|||||||
110
src/atomic.h
110
src/atomic.h
@ -3,13 +3,113 @@
|
|||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
|
||||||
/* winnt.h declarations */
|
/* atomic_i32 */
|
||||||
|
|
||||||
i64 _InterlockedIncrement64(i64 volatile *addend);
|
FORCE_INLINE i32 atomic_i32_eval(struct atomic_i32 *x)
|
||||||
i64 _InterlockedDecrement64(i64 volatile *addend);
|
{
|
||||||
|
return _InterlockedExchangeAdd((volatile long *)&x->_v, 0);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i32 atomic_i32_inc_eval(struct atomic_i32 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedIncrement((volatile long *)&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i32 atomic_i32_dec_eval(struct atomic_i32 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedDecrement((volatile long *)&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i32 atomic_i32_eval_add(struct atomic_i32 *x, i32 a)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd((volatile long *)&x->_v, a);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i32 atomic_i32_eval_exchange(struct atomic_i32 *x, i32 e)
|
||||||
|
{
|
||||||
|
return _InterlockedExchange((volatile long *)&x->_v, e);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i32 atomic_i32_eval_compare_exchange(struct atomic_i32 *x, i32 c, i32 e)
|
||||||
|
{
|
||||||
|
return _InterlockedCompareExchange((volatile long *)&x->_v, e, c);
|
||||||
|
}
|
||||||
|
|
||||||
#define atomic_inc_eval64(ptr) _InterlockedIncrement64(ptr)
|
/* atomic_u32 */
|
||||||
#define atomic_dec_eval64(ptr) _InterlockedDecrement64(ptr)
|
|
||||||
|
FORCE_INLINE u32 atomic_u32_eval(struct atomic_u32 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd((volatile long *)&x->_v, 0);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u32 atomic_u32_inc_eval(struct atomic_u32 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedIncrement((volatile long *)&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u32 atomic_u32_dec_eval(struct atomic_u32 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedDecrement((volatile long *)&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u32 atomic_u32_eval_add(struct atomic_u32 *x, u32 a)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd((volatile long *)&x->_v, a);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u32 atomic_u32_eval_exchange(struct atomic_u32 *x, u32 e)
|
||||||
|
{
|
||||||
|
return _InterlockedExchange((volatile long *)&x->_v, e);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u32 atomic_u32_eval_compare_exchange(struct atomic_u32 *x, u32 c, u32 e)
|
||||||
|
{
|
||||||
|
return _InterlockedCompareExchange((volatile long *)&x->_v, e, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* atomic_i64 */
|
||||||
|
|
||||||
|
FORCE_INLINE i64 atomic_i64_eval(struct atomic_i64 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd64(&x->_v, 0);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i64 atomic_i64_inc_eval(struct atomic_i64 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedIncrement64(&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i64 atomic_i64_dec_eval(struct atomic_i64 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedDecrement64(&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i64 atomic_i64_eval_add(struct atomic_i64 *x, i64 a)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd64(&x->_v, a);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i64 atomic_i64_eval_exchange(struct atomic_i64 *x, i64 e)
|
||||||
|
{
|
||||||
|
return _InterlockedExchange64(&x->_v, e);
|
||||||
|
}
|
||||||
|
FORCE_INLINE i64 atomic_i64_eval_compare_exchange(struct atomic_i64 *x, i64 c, i64 e)
|
||||||
|
{
|
||||||
|
return _InterlockedCompareExchange64(&x->_v, e, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* atomic_u64 */
|
||||||
|
|
||||||
|
FORCE_INLINE u64 atomic_u64_eval(struct atomic_u64 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd64((volatile i64 *)&x->_v, 0);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u64 atomic_u64_inc_eval(struct atomic_u64 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedIncrement64((volatile i64 *)&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u64 atomic_u64_dec_eval(struct atomic_u64 *x)
|
||||||
|
{
|
||||||
|
return _InterlockedDecrement64((volatile i64 *)&x->_v);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u64 atomic_u64_eval_add(struct atomic_u64 *x, u64 a)
|
||||||
|
{
|
||||||
|
return _InterlockedExchangeAdd64((volatile i64 *)&x->_v, a);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u64 atomic_u64_eval_exchange(struct atomic_u64 *x, u64 e)
|
||||||
|
{
|
||||||
|
return _InterlockedExchange64((volatile i64 *)&x->_v, e);
|
||||||
|
}
|
||||||
|
FORCE_INLINE u64 atomic_u64_eval_compare_exchange(struct atomic_u64 *x, u64 c, u64 e)
|
||||||
|
{
|
||||||
|
return _InterlockedCompareExchange64((volatile i64 *)&x->_v, e, c);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error "Atomics not implemented"
|
# error "Atomics not implemented"
|
||||||
|
|||||||
25
src/common.h
25
src/common.h
@ -28,6 +28,7 @@ extern "C" {
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <intrin.h>
|
||||||
#include <nmmintrin.h> /* SSE4.2 */
|
#include <nmmintrin.h> /* SSE4.2 */
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -153,9 +154,11 @@ extern "C" {
|
|||||||
# define INLINE static inline
|
# define INLINE static inline
|
||||||
#else
|
#else
|
||||||
/* TODO: benchmark benefits of forced inlining */
|
/* TODO: benchmark benefits of forced inlining */
|
||||||
# define INLINE __attribute((always_inline)) static inline
|
# define INLINE static inline __attribute((always_inline))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FORCE_INLINE static inline __attribute((always_inline))
|
||||||
|
|
||||||
/* Separate `static` usage into different keywords for easier grepping */
|
/* Separate `static` usage into different keywords for easier grepping */
|
||||||
#define LOCAL_PERSIST static
|
#define LOCAL_PERSIST static
|
||||||
#define INTERNAL static
|
#define INTERNAL static
|
||||||
@ -285,6 +288,26 @@ typedef u64 umm;
|
|||||||
#define PI ((f32)3.14159265358979323846)
|
#define PI ((f32)3.14159265358979323846)
|
||||||
#define TAU ((f32)6.28318530717958647693)
|
#define TAU ((f32)6.28318530717958647693)
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Atomics
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
struct atomic_i32 {
|
||||||
|
volatile i32 _v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct atomic_u32 {
|
||||||
|
volatile u32 _v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct atomic_i64 {
|
||||||
|
volatile i64 _v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct atomic_u64 {
|
||||||
|
volatile u64 _v;
|
||||||
|
};
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Common structs
|
* Common structs
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
10
src/font.c
10
src/font.c
@ -51,24 +51,26 @@ void font_startup(void)
|
|||||||
INTERNAL struct font_task_params *font_task_params_alloc(void)
|
INTERNAL struct font_task_params *font_task_params_alloc(void)
|
||||||
{
|
{
|
||||||
struct font_task_params *p = NULL;
|
struct font_task_params *p = NULL;
|
||||||
|
sys_mutex_lock(&L.params.mutex);
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
|
||||||
if (L.params.head_free) {
|
if (L.params.head_free) {
|
||||||
p = L.params.head_free;
|
p = L.params.head_free;
|
||||||
L.params.head_free = p->next_free;
|
L.params.head_free = p->next_free;
|
||||||
} else {
|
} else {
|
||||||
p = arena_push_zero(&L.params.arena, struct font_task_params);
|
p = arena_push_zero(&L.params.arena, struct font_task_params);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void font_task_params_release(struct font_task_params *p)
|
INTERNAL void font_task_params_release(struct font_task_params *p)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
sys_mutex_lock(&L.params.mutex);
|
||||||
p->next_free = L.params.head_free;
|
{
|
||||||
L.params.head_free = p;
|
p->next_free = L.params.head_free;
|
||||||
|
L.params.head_free = p;
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -64,7 +64,9 @@ INTERNAL void publish_game_tick(void)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&L.published_tick_mutex);
|
sys_mutex_lock(&L.published_tick_mutex);
|
||||||
world_copy_replace(&L.published_tick, &L.world);
|
{
|
||||||
|
world_copy_replace(&L.published_tick, &L.world);
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.published_tick_mutex);
|
sys_mutex_unlock(&L.published_tick_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,7 +569,9 @@ void game_shutdown(void)
|
|||||||
void game_get_latest_tick(struct world *dest)
|
void game_get_latest_tick(struct world *dest)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.published_tick_mutex);
|
sys_mutex_lock(&L.published_tick_mutex);
|
||||||
world_copy_replace(dest, &L.published_tick);
|
{
|
||||||
|
world_copy_replace(dest, &L.published_tick);
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.published_tick_mutex);
|
sys_mutex_unlock(&L.published_tick_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,10 @@ void log_startup(struct string logfile_path)
|
|||||||
void log_register_callback(log_event_callback_func *func)
|
void log_register_callback(log_event_callback_func *func)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
(UNUSED)func;
|
{
|
||||||
|
/* TODO */
|
||||||
|
(UNUSED)func;
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -569,20 +569,20 @@ INLINE struct mat4x4 mat4x4_from_xform(struct xform xf)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far)
|
INLINE struct mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z)
|
||||||
{
|
{
|
||||||
struct mat4x4 m = {0};
|
struct mat4x4 m = {0};
|
||||||
|
|
||||||
f32 rl = 1.0f / (right - left);
|
f32 rl = 1.0f / (right - left);
|
||||||
f32 tb = 1.0f / (top - bottom);
|
f32 tb = 1.0f / (top - bottom);
|
||||||
f32 fn = -1.0f / (far - near);
|
f32 fn = -1.0f / (far_z - near_z);
|
||||||
|
|
||||||
m.e[0][0] = 2.0f * rl;
|
m.e[0][0] = 2.0f * rl;
|
||||||
m.e[1][1] = 2.0f * tb;
|
m.e[1][1] = 2.0f * tb;
|
||||||
m.e[2][2] = 2.0f * fn;
|
m.e[2][2] = 2.0f * fn;
|
||||||
m.e[3][0] = -(right + left) * rl;
|
m.e[3][0] = -(right + left) * rl;
|
||||||
m.e[3][1] = -(top + bottom) * tb;
|
m.e[3][1] = -(top + bottom) * tb;
|
||||||
m.e[3][2] = (far + near) * fn;
|
m.e[3][2] = (far_z + near_z) * fn;
|
||||||
m.e[3][3] = 1.0f;
|
m.e[3][3] = 1.0f;
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|||||||
31
src/mixer.c
31
src/mixer.c
@ -5,7 +5,6 @@
|
|||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "playback.h"
|
#include "playback.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "atomic.h"
|
|
||||||
|
|
||||||
/* TODO: Cap max sounds playing. */
|
/* TODO: Cap max sounds playing. */
|
||||||
|
|
||||||
@ -188,8 +187,10 @@ struct mixer_track_handle mixer_play_ex(struct sound *sound, struct mixer_desc d
|
|||||||
struct track *track;
|
struct track *track;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
track = track_alloc_assume_locked(sound);
|
{
|
||||||
track->desc = desc;
|
track = track_alloc_assume_locked(sound);
|
||||||
|
track->desc = desc;
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
return track_to_handle(track);
|
return track_to_handle(track);
|
||||||
@ -204,13 +205,13 @@ struct mixer_desc mixer_track_get(struct mixer_track_handle handle)
|
|||||||
if (track) {
|
if (track) {
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
|
{
|
||||||
/* Confirm handle is still valid now that we're locked */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
track = track_from_handle(handle);
|
track = track_from_handle(handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
res = track->desc;
|
res = track->desc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,13 +225,13 @@ void mixer_track_set(struct mixer_track_handle handle, struct mixer_desc desc)
|
|||||||
if (track) {
|
if (track) {
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
|
{
|
||||||
/* Confirm handle is still valid now that we're locked */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
track = track_from_handle(handle);
|
track = track_from_handle(handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
track->desc = desc;
|
track->desc = desc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -195,22 +195,24 @@ INTERNAL struct renderer_handle handle_alloc(void *data)
|
|||||||
struct handle_slot *slot = NULL;
|
struct handle_slot *slot = NULL;
|
||||||
|
|
||||||
sys_mutex_lock(&store->mutex);
|
sys_mutex_lock(&store->mutex);
|
||||||
if (store->head_free) {
|
{
|
||||||
/* Take first from free list */
|
if (store->head_free) {
|
||||||
slot = store->head_free;
|
/* Take first from free list */
|
||||||
store->head_free = slot->next_free;
|
slot = store->head_free;
|
||||||
slot->next_free = NULL;
|
store->head_free = slot->next_free;
|
||||||
} else {
|
slot->next_free = NULL;
|
||||||
/* Or push onto arena */
|
} else {
|
||||||
if (store->count + 1 >= HANDLE_IDX_MAX) {
|
/* Or push onto arena */
|
||||||
sys_panic(STR("Maximum renderer handles exceeded"));
|
if (store->count + 1 >= HANDLE_IDX_MAX) {
|
||||||
|
sys_panic(STR("Maximum renderer handles exceeded"));
|
||||||
|
}
|
||||||
|
slot = arena_push_zero(&store->arena, struct handle_slot);
|
||||||
|
slot->idx = store->count;
|
||||||
|
slot->gen = 1;
|
||||||
|
++store->count;
|
||||||
}
|
}
|
||||||
slot = arena_push_zero(&store->arena, struct handle_slot);
|
slot->data = data;
|
||||||
slot->idx = store->count;
|
|
||||||
slot->gen = 1;
|
|
||||||
++store->count;
|
|
||||||
}
|
}
|
||||||
slot->data = data;
|
|
||||||
sys_mutex_unlock(&store->mutex);
|
sys_mutex_unlock(&store->mutex);
|
||||||
|
|
||||||
struct renderer_handle handle = HANDLE_CREATE(slot->idx, slot->gen);
|
struct renderer_handle handle = HANDLE_CREATE(slot->idx, slot->gen);
|
||||||
@ -226,27 +228,29 @@ INTERNAL void handle_release(struct renderer_handle handle)
|
|||||||
u32 gen = HANDLE_GEN(handle);
|
u32 gen = HANDLE_GEN(handle);
|
||||||
|
|
||||||
sys_mutex_lock(&store->mutex);
|
sys_mutex_lock(&store->mutex);
|
||||||
if (idx < store->count) {
|
{
|
||||||
struct handle_slot *slot = &store->array[idx];
|
if (idx < store->count) {
|
||||||
if (slot->gen == gen) {
|
struct handle_slot *slot = &store->array[idx];
|
||||||
/* Insert into free list */
|
if (slot->gen == gen) {
|
||||||
if (gen + 1 < HANDLE_GEN_MAX) {
|
/* Insert into free list */
|
||||||
slot->next_free = store->head_free;
|
if (gen + 1 < HANDLE_GEN_MAX) {
|
||||||
store->head_free = slot;
|
slot->next_free = store->head_free;
|
||||||
|
store->head_free = slot;
|
||||||
|
} else {
|
||||||
|
/* Maximum generations exceeded. Not a runtime error since it
|
||||||
|
* shouldn't cause issues in practice (just can't recycle this handle).
|
||||||
|
* Still probably means there's a problem in the code. */
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
++slot->gen;
|
||||||
} else {
|
} else {
|
||||||
/* Maximum generations exceeded. Not a runtime error since it
|
/* Tried to release handle not in store (non-matching generation) */
|
||||||
* shouldn't cause issues in practice (just can't recycle this handle).
|
|
||||||
* Still probably means there's a problem in the code. */
|
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
++slot->gen;
|
|
||||||
} else {
|
} else {
|
||||||
/* Tried to release handle not in store (non-matching generation) */
|
/* Tried to release out-of-bounds handle */
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* Tried to release out-of-bounds handle */
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&store->mutex);
|
sys_mutex_unlock(&store->mutex);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/sheet.c
10
src/sheet.c
@ -48,24 +48,26 @@ void sheet_startup(void)
|
|||||||
INTERNAL struct sheet_task_params *sheet_task_params_alloc(void)
|
INTERNAL struct sheet_task_params *sheet_task_params_alloc(void)
|
||||||
{
|
{
|
||||||
struct sheet_task_params *p = NULL;
|
struct sheet_task_params *p = NULL;
|
||||||
|
sys_mutex_lock(&L.params.mutex);
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
|
||||||
if (L.params.head_free) {
|
if (L.params.head_free) {
|
||||||
p = L.params.head_free;
|
p = L.params.head_free;
|
||||||
L.params.head_free = p->next_free;
|
L.params.head_free = p->next_free;
|
||||||
} else {
|
} else {
|
||||||
p = arena_push_zero(&L.params.arena, struct sheet_task_params);
|
p = arena_push_zero(&L.params.arena, struct sheet_task_params);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void sheet_task_params_release(struct sheet_task_params *p)
|
INTERNAL void sheet_task_params_release(struct sheet_task_params *p)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
sys_mutex_lock(&L.params.mutex);
|
||||||
p->next_free = L.params.head_free;
|
{
|
||||||
L.params.head_free = p;
|
p->next_free = L.params.head_free;
|
||||||
|
L.params.head_free = p;
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
src/sound.c
18
src/sound.c
@ -49,11 +49,13 @@ INTERNAL struct sound_task_params *sound_task_params_alloc(void)
|
|||||||
struct sound_task_params *p = NULL;
|
struct sound_task_params *p = NULL;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
sys_mutex_lock(&L.params.mutex);
|
||||||
if (L.params.head_free) {
|
{
|
||||||
p = L.params.head_free;
|
if (L.params.head_free) {
|
||||||
L.params.head_free = p->next_free;
|
p = L.params.head_free;
|
||||||
} else {
|
L.params.head_free = p->next_free;
|
||||||
p = arena_push_zero(&L.params.arena, struct sound_task_params);
|
} else {
|
||||||
|
p = arena_push_zero(&L.params.arena, struct sound_task_params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
}
|
}
|
||||||
@ -63,8 +65,10 @@ INTERNAL struct sound_task_params *sound_task_params_alloc(void)
|
|||||||
INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
INTERNAL void sound_task_params_release(struct sound_task_params *p)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
sys_mutex_lock(&L.params.mutex);
|
||||||
p->next_free = L.params.head_free;
|
{
|
||||||
L.params.head_free = p;
|
p->next_free = L.params.head_free;
|
||||||
|
L.params.head_free = p;
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -330,7 +330,7 @@ void sys_mutex_assert_locked(struct sys_mutex *mutex);
|
|||||||
struct sys_rw_mutex {
|
struct sys_rw_mutex {
|
||||||
u64 handle;
|
u64 handle;
|
||||||
#if RTC
|
#if RTC
|
||||||
i64 num_shared;
|
struct atomic_i64 num_shared;
|
||||||
u64 owner_tid;
|
u64 owner_tid;
|
||||||
# if _WIN32
|
# if _WIN32
|
||||||
wchar_t *owner_name;
|
wchar_t *owner_name;
|
||||||
@ -360,7 +360,7 @@ void sys_rw_mutex_assert_locked_exclusive(struct sys_rw_mutex *mutex);
|
|||||||
struct sys_condition_variable {
|
struct sys_condition_variable {
|
||||||
u64 handle;
|
u64 handle;
|
||||||
#if RTC
|
#if RTC
|
||||||
i64 num_sleepers;
|
struct atomic_i64 num_sleepers;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1205,7 +1205,7 @@ void sys_rw_mutex_release(struct sys_rw_mutex *mutex)
|
|||||||
(UNUSED)mutex;
|
(UNUSED)mutex;
|
||||||
/* Mutex must be unlocked */
|
/* Mutex must be unlocked */
|
||||||
ASSERT(mutex->owner_tid == 0);
|
ASSERT(mutex->owner_tid == 0);
|
||||||
ASSERT(mutex->num_shared == 0);
|
ASSERT(atomic_i64_eval(&mutex->num_shared) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_rw_mutex_lock_exclusive(struct sys_rw_mutex *mutex)
|
void sys_rw_mutex_lock_exclusive(struct sys_rw_mutex *mutex)
|
||||||
@ -1233,7 +1233,7 @@ void sys_rw_mutex_lock_shared(struct sys_rw_mutex *mutex)
|
|||||||
__prof;
|
__prof;
|
||||||
AcquireSRWLockShared((SRWLOCK *)&mutex->handle);
|
AcquireSRWLockShared((SRWLOCK *)&mutex->handle);
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_inc_eval64(&mutex->num_shared);
|
atomic_i64_inc_eval(&mutex->num_shared);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1241,7 +1241,7 @@ void sys_rw_mutex_unlock_shared(struct sys_rw_mutex *mutex)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_dec_eval64(&mutex->num_shared);
|
atomic_i64_dec_eval(&mutex->num_shared);
|
||||||
#endif
|
#endif
|
||||||
ReleaseSRWLockShared((SRWLOCK *)&mutex->handle);
|
ReleaseSRWLockShared((SRWLOCK *)&mutex->handle);
|
||||||
}
|
}
|
||||||
@ -1263,11 +1263,13 @@ INTERNAL struct win32_condition_variable *win32_condition_variable_alloc(void)
|
|||||||
struct win32_condition_variable *cv = NULL;
|
struct win32_condition_variable *cv = NULL;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.condition_variables_mutex);
|
sys_mutex_lock(&L.condition_variables_mutex);
|
||||||
if (L.first_free_condition_variable) {
|
{
|
||||||
cv = L.first_free_condition_variable;
|
if (L.first_free_condition_variable) {
|
||||||
L.first_free_condition_variable = cv->next_free;
|
cv = L.first_free_condition_variable;
|
||||||
} else {
|
L.first_free_condition_variable = cv->next_free;
|
||||||
cv = arena_push_zero(&L.condition_variables_arena, struct win32_condition_variable);
|
} else {
|
||||||
|
cv = arena_push_zero(&L.condition_variables_arena, struct win32_condition_variable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.condition_variables_mutex);
|
sys_mutex_unlock(&L.condition_variables_mutex);
|
||||||
}
|
}
|
||||||
@ -1303,7 +1305,7 @@ void sys_condition_variable_release(struct sys_condition_variable *cv)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
/* Condition variable must not have any sleepers (signal before releasing) */
|
/* Condition variable must not have any sleepers (signal before releasing) */
|
||||||
ASSERT(cv->num_sleepers == 0);
|
ASSERT(atomic_i64_eval(&cv->num_sleepers) == 0);
|
||||||
win32_condition_variable_release((struct win32_condition_variable *)cv->handle);
|
win32_condition_variable_release((struct win32_condition_variable *)cv->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1311,11 +1313,11 @@ void sys_condition_variable_wait(struct sys_condition_variable *cv, struct sys_m
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_inc_eval64(&cv->num_sleepers);
|
atomic_i64_inc_eval(&cv->num_sleepers);
|
||||||
#endif
|
#endif
|
||||||
SleepConditionVariableSRW((PCONDITION_VARIABLE)cv->handle, (SRWLOCK *)&mutex->handle, INFINITE, 0);
|
SleepConditionVariableSRW((PCONDITION_VARIABLE)cv->handle, (SRWLOCK *)&mutex->handle, INFINITE, 0);
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_dec_eval64(&cv->num_sleepers);
|
atomic_i64_dec_eval(&cv->num_sleepers);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1323,12 +1325,12 @@ void sys_condition_variable_wait_time(struct sys_condition_variable *cv, struct
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_inc_eval64(&cv->num_sleepers);
|
atomic_i64_inc_eval(&cv->num_sleepers);
|
||||||
#endif
|
#endif
|
||||||
u32 ms = (u32)math_round((f32)seconds * 1000.f);
|
u32 ms = (u32)math_round((f32)seconds * 1000.f);
|
||||||
SleepConditionVariableSRW((PCONDITION_VARIABLE)cv->handle, (SRWLOCK *)&mutex->handle, ms, 0);
|
SleepConditionVariableSRW((PCONDITION_VARIABLE)cv->handle, (SRWLOCK *)&mutex->handle, ms, 0);
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_dec_eval64(&cv->num_sleepers);
|
atomic_i64_dec_eval(&cv->num_sleepers);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,7 +1360,7 @@ void sys_semaphore_release(struct sys_semaphore *semaphore)
|
|||||||
CloseHandle((HANDLE)semaphore->handle);
|
CloseHandle((HANDLE)semaphore->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_semaphore_wait(struct sys_semaphore *semaphore)
|
void sys_semaphore_wait(struct sys_semaphore *semaphore)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
WaitForSingleObjectEx((HANDLE)semaphore->handle, INFINITE, FALSE);
|
WaitForSingleObjectEx((HANDLE)semaphore->handle, INFINITE, FALSE);
|
||||||
@ -1639,9 +1641,9 @@ u32 sys_rand_u32(void)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like sys_panic, but guaranteed to have no side-effects */
|
|
||||||
void sys_panic_raw(char *msg_cstr)
|
void sys_panic_raw(char *msg_cstr)
|
||||||
{
|
{
|
||||||
|
app_quit();
|
||||||
MessageBoxExA(NULL, msg_cstr, "Fatal error", MB_ICONSTOP, 0);
|
MessageBoxExA(NULL, msg_cstr, "Fatal error", MB_ICONSTOP, 0);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
sys_exit();
|
sys_exit();
|
||||||
|
|||||||
@ -54,11 +54,13 @@ INTERNAL struct texture_task_params *texture_task_params_alloc(void)
|
|||||||
struct texture_task_params *p = NULL;
|
struct texture_task_params *p = NULL;
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
sys_mutex_lock(&L.params.mutex);
|
||||||
if (L.params.head_free) {
|
{
|
||||||
p = L.params.head_free;
|
if (L.params.head_free) {
|
||||||
L.params.head_free = p->next_free;
|
p = L.params.head_free;
|
||||||
} else {
|
L.params.head_free = p->next_free;
|
||||||
p = arena_push_zero(&L.params.arena, struct texture_task_params);
|
} else {
|
||||||
|
p = arena_push_zero(&L.params.arena, struct texture_task_params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
}
|
}
|
||||||
@ -68,8 +70,10 @@ INTERNAL struct texture_task_params *texture_task_params_alloc(void)
|
|||||||
INTERNAL void texture_task_params_release(struct texture_task_params *p)
|
INTERNAL void texture_task_params_release(struct texture_task_params *p)
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.params.mutex);
|
sys_mutex_lock(&L.params.mutex);
|
||||||
p->next_free = L.params.head_free;
|
{
|
||||||
L.params.head_free = p;
|
p->next_free = L.params.head_free;
|
||||||
|
L.params.head_free = p;
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.params.mutex);
|
sys_mutex_unlock(&L.params.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
src/user.c
34
src/user.c
@ -63,7 +63,6 @@ GLOBAL struct {
|
|||||||
struct v2 screen_center;
|
struct v2 screen_center;
|
||||||
struct v2 screen_cursor;
|
struct v2 screen_cursor;
|
||||||
struct v2 world_cursor;
|
struct v2 world_cursor;
|
||||||
struct v2 mouse_delta;
|
|
||||||
} L = { 0 }, DEBUG_LVAR(L_user);
|
} L = { 0 }, DEBUG_LVAR(L_user);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -95,18 +94,16 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
|||||||
INTERNAL struct sys_event_array pop_sys_events(struct arena *arena)
|
INTERNAL struct sys_event_array pop_sys_events(struct arena *arena)
|
||||||
{
|
{
|
||||||
struct sys_event_array array = { 0 };
|
struct sys_event_array array = { 0 };
|
||||||
if (L.sys_events_arena.pos > 0) {
|
sys_mutex_lock(&L.sys_events_mutex);
|
||||||
sys_mutex_lock(&L.sys_events_mutex);
|
{
|
||||||
{
|
struct buffer events_buff = arena_to_buffer(&L.sys_events_arena);
|
||||||
struct buffer events_buff = arena_to_buffer(&L.sys_events_arena);
|
arena_align(arena, ALIGNOF(struct sys_event));
|
||||||
arena_align(arena, ALIGNOF(struct sys_event));
|
array.events = (struct sys_event *)arena_push_array(arena, u8, events_buff.size);
|
||||||
array.events = (struct sys_event *)arena_push_array(arena, u8, events_buff.size);
|
array.count = events_buff.size / sizeof(struct sys_event);
|
||||||
array.count = events_buff.size / sizeof(struct sys_event);
|
MEMCPY(array.events, events_buff.data, events_buff.size);
|
||||||
MEMCPY(array.events, events_buff.data, events_buff.size);
|
arena_reset(&L.sys_events_arena);
|
||||||
arena_reset(&L.sys_events_arena);
|
|
||||||
}
|
|
||||||
sys_mutex_unlock(&L.sys_events_mutex);
|
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&L.sys_events_mutex);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,8 +445,6 @@ INTERNAL void user_update(void)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
L.mouse_delta = V2(0, 0);
|
|
||||||
|
|
||||||
for (u64 entity_index = 0; entity_index < events.count; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < events.count; ++entity_index) {
|
||||||
struct sys_event *event = &events.events[entity_index];
|
struct sys_event *event = &events.events[entity_index];
|
||||||
|
|
||||||
@ -476,11 +471,6 @@ INTERNAL void user_update(void)
|
|||||||
L.screen_cursor = event->cursor_position;
|
L.screen_cursor = event->cursor_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update mouse delta */
|
|
||||||
if (event->kind == SYS_EVENT_KIND_MOUSE_MOVE) {
|
|
||||||
L.mouse_delta = v2_add(L.mouse_delta, event->mouse_delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update bind states */
|
/* Update bind states */
|
||||||
if ((event->kind == SYS_EVENT_KIND_BUTTON_DOWN || event->kind == SYS_EVENT_KIND_BUTTON_UP) && !event->is_repeat) {
|
if ((event->kind == SYS_EVENT_KIND_BUTTON_DOWN || event->kind == SYS_EVENT_KIND_BUTTON_UP) && !event->is_repeat) {
|
||||||
enum sys_btn button = event->button;
|
enum sys_btn button = event->button;
|
||||||
@ -779,16 +769,16 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw crosshair or enable cursor */
|
/* Draw crosshair or show cursor */
|
||||||
if (!L.debug_camera) {
|
if (!L.debug_camera) {
|
||||||
struct v2 crosshair_pos = L.screen_cursor;
|
struct v2 crosshair_pos = L.screen_cursor;
|
||||||
u32 tint = RGBA_F(1, 1, 1, 0.5);
|
u32 tint = RGBA_F(1, 1, 1, 1 );
|
||||||
|
|
||||||
struct v2 size = V2(0, 0);
|
struct v2 size = V2(0, 0);
|
||||||
struct texture *t = texture_load_async(STR("res/graphics/crosshair.ase"));
|
struct texture *t = texture_load_async(STR("res/graphics/crosshair.ase"));
|
||||||
if (t) {
|
if (t) {
|
||||||
size = t->size;
|
size = t->size;
|
||||||
struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = t->size);
|
struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = size);
|
||||||
struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xf);
|
struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xf);
|
||||||
draw_texture_quad(L.screen_canvas, DRAW_TEXTURE_PARAMS(.texture = t, .tint = tint), quad);
|
draw_texture_quad(L.screen_canvas, DRAW_TEXTURE_PARAMS(.texture = t, .tint = tint), quad);
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/util.h
20
src/util.h
@ -5,6 +5,7 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
/* Utility functions and stuff that don't have a home :( */
|
/* Utility functions and stuff that don't have a home :( */
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ struct sync_flag {
|
|||||||
/* TODO: Make this a rw mutex? */
|
/* TODO: Make this a rw mutex? */
|
||||||
struct sys_mutex mutex;
|
struct sys_mutex mutex;
|
||||||
struct sys_condition_variable cv;
|
struct sys_condition_variable cv;
|
||||||
b32 flag;
|
struct atomic_i32 flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE struct sync_flag sync_flag_alloc(void)
|
INLINE struct sync_flag sync_flag_alloc(void)
|
||||||
@ -153,11 +154,12 @@ INLINE void sync_flag_release(struct sync_flag *sf)
|
|||||||
INLINE void sync_flag_set(struct sync_flag *sf)
|
INLINE void sync_flag_set(struct sync_flag *sf)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
WRITE_BARRIER();
|
if (atomic_i32_eval_compare_exchange(&sf->flag, 0, 1) == 0) {
|
||||||
if (!sf->flag) {
|
|
||||||
sys_mutex_lock(&sf->mutex);
|
sys_mutex_lock(&sf->mutex);
|
||||||
sf->flag = true;
|
{
|
||||||
sys_condition_variable_signal(&sf->cv);
|
atomic_i32_eval_exchange(&sf->flag, 1);
|
||||||
|
sys_condition_variable_signal(&sf->cv);
|
||||||
|
}
|
||||||
sys_mutex_unlock(&sf->mutex);
|
sys_mutex_unlock(&sf->mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,13 +167,9 @@ INLINE void sync_flag_set(struct sync_flag *sf)
|
|||||||
INLINE void sync_flag_wait(struct sync_flag *sf)
|
INLINE void sync_flag_wait(struct sync_flag *sf)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
READ_BARRIER();
|
while (atomic_i32_eval(&sf->flag) == 0) {
|
||||||
if (!sf->flag) {
|
|
||||||
sys_mutex_lock(&sf->mutex);
|
sys_mutex_lock(&sf->mutex);
|
||||||
while (!sf->flag) {
|
sys_condition_variable_wait(&sf->cv, &sf->mutex);
|
||||||
sys_condition_variable_wait(&sf->cv, &sf->mutex);
|
|
||||||
}
|
|
||||||
sys_mutex_unlock(&sf->mutex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
100
src/work.c
100
src/work.c
@ -110,20 +110,22 @@ void work_startup(u32 num_worker_threads)
|
|||||||
/* Initialize threads */
|
/* Initialize threads */
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
struct worker *prev = NULL;
|
{
|
||||||
for (u32 i = 0; i < num_worker_threads; ++i) {
|
struct worker *prev = NULL;
|
||||||
struct string thread_name = string_format(scratch.arena,
|
for (u32 i = 0; i < num_worker_threads; ++i) {
|
||||||
STR("[P0] Worker %F"),
|
struct string thread_name = string_format(scratch.arena,
|
||||||
FMT_UINT(i));
|
STR("[P0] Worker %F"),
|
||||||
|
FMT_UINT(i));
|
||||||
|
|
||||||
struct worker *worker = arena_push_zero(&L.arena, struct worker);
|
struct worker *worker = arena_push_zero(&L.arena, struct worker);
|
||||||
worker->thread = sys_thread_init(&worker_thread_entry_point, NULL, thread_name);
|
worker->thread = sys_thread_init(&worker_thread_entry_point, NULL, thread_name);
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = worker;
|
prev->next = worker;
|
||||||
} else {
|
} else {
|
||||||
L.worker_head = worker;
|
L.worker_head = worker;
|
||||||
|
}
|
||||||
|
prev = worker;
|
||||||
}
|
}
|
||||||
prev = worker;
|
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
@ -320,12 +322,12 @@ INTERNAL b32 work_exec_single_task_maybe_release_assume_locked(struct work *work
|
|||||||
work->status = WORK_STATUS_IN_PROGRESS;
|
work->status = WORK_STATUS_IN_PROGRESS;
|
||||||
|
|
||||||
++work->workers;
|
++work->workers;
|
||||||
|
/* Do task (temporarily unlock) */
|
||||||
|
sys_mutex_unlock(&L.mutex);
|
||||||
{
|
{
|
||||||
/* Do task (temporarily unlock) */
|
|
||||||
sys_mutex_unlock(&L.mutex);
|
|
||||||
task->func(task->data);
|
task->func(task->data);
|
||||||
sys_mutex_lock(&L.mutex);
|
|
||||||
}
|
}
|
||||||
|
sys_mutex_lock(&L.mutex);
|
||||||
--work->workers;
|
--work->workers;
|
||||||
--work->tasks_incomplete;
|
--work->tasks_incomplete;
|
||||||
task_release_assume_locked(task);
|
task_release_assume_locked(task);
|
||||||
@ -378,12 +380,14 @@ INTERNAL void worker_thread_entry_point(void *thread_data)
|
|||||||
while (L.scheduled_work_head) {
|
while (L.scheduled_work_head) {
|
||||||
/* Do work from top */
|
/* Do work from top */
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
struct work *work = L.scheduled_work_head;
|
{
|
||||||
if (work) {
|
struct work *work = L.scheduled_work_head;
|
||||||
__profscope(work_pool_task);
|
if (work) {
|
||||||
--L.idle_worker_count;
|
__profscope(work_pool_task);
|
||||||
work_exec_single_task_maybe_release_assume_locked((struct work *)work);
|
--L.idle_worker_count;
|
||||||
++L.idle_worker_count;
|
work_exec_single_task_maybe_release_assume_locked((struct work *)work);
|
||||||
|
++L.idle_worker_count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
@ -442,19 +446,20 @@ INTERNAL struct work_handle work_push_from_slate_assume_locked(struct work_slate
|
|||||||
|
|
||||||
INTERNAL struct work_handle work_push_task_internal(work_task_func *func, void *data, b32 help, enum work_priority priority)
|
INTERNAL struct work_handle work_push_task_internal(work_task_func *func, void *data, b32 help, enum work_priority priority)
|
||||||
{
|
{
|
||||||
|
struct work_handle handle;
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
|
{
|
||||||
|
struct work_task *task = task_alloc_assume_locked();
|
||||||
|
task->data = data;
|
||||||
|
task->func = func;
|
||||||
|
|
||||||
struct work_task *task = task_alloc_assume_locked();
|
struct work_slate ws = {
|
||||||
task->data = data;
|
.task_head = task,
|
||||||
task->func = func;
|
.task_tail = task,
|
||||||
|
.num_tasks = 1
|
||||||
struct work_slate ws = {
|
};
|
||||||
.task_head = task,
|
handle = work_push_from_slate_assume_locked(&ws, help, priority);
|
||||||
.task_tail = task,
|
}
|
||||||
.num_tasks = 1
|
|
||||||
};
|
|
||||||
struct work_handle handle = work_push_from_slate_assume_locked(&ws, help, priority);
|
|
||||||
|
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
@ -487,11 +492,11 @@ void work_slate_push_task(struct work_slate *ws, work_task_func *func, void *dat
|
|||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct work_task *task = NULL;
|
struct work_task *task = NULL;
|
||||||
|
sys_mutex_lock(&L.mutex);
|
||||||
{
|
{
|
||||||
sys_mutex_lock(&L.mutex);
|
|
||||||
task = task_alloc_assume_locked();
|
task = task_alloc_assume_locked();
|
||||||
sys_mutex_unlock(&L.mutex);
|
|
||||||
}
|
}
|
||||||
|
sys_mutex_unlock(&L.mutex);
|
||||||
|
|
||||||
task->data = data;
|
task->data = data;
|
||||||
task->func = func;
|
task->func = func;
|
||||||
@ -511,8 +516,11 @@ struct work_handle work_slate_end(struct work_slate *ws, enum work_priority prio
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
|
struct work_handle handle;
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
struct work_handle handle = work_push_from_slate_assume_locked(ws, false, priority);
|
{
|
||||||
|
handle = work_push_from_slate_assume_locked(ws, false, priority);
|
||||||
|
}
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
@ -550,21 +558,21 @@ void work_wait(struct work_handle handle)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
sys_mutex_lock(&L.mutex);
|
sys_mutex_lock(&L.mutex);
|
||||||
|
{
|
||||||
struct work *work = work_from_handle_assume_locked(handle);
|
struct work *work = work_from_handle_assume_locked(handle);
|
||||||
if (work) {
|
|
||||||
/* Help with tasks */
|
|
||||||
work_exec_remaining_tasks_maybe_release_assume_locked(work);
|
|
||||||
|
|
||||||
/* Wait for work completion */
|
|
||||||
work = work_from_handle_assume_locked(handle); /* Re-checking work is sitll valid here in case work_do caused work to release */
|
|
||||||
if (work) {
|
if (work) {
|
||||||
while (work->status != WORK_STATUS_DONE) {
|
/* Help with tasks */
|
||||||
sys_condition_variable_wait(&work->condition_variable_finished, &L.mutex);
|
work_exec_remaining_tasks_maybe_release_assume_locked(work);
|
||||||
|
|
||||||
|
/* Wait for work completion */
|
||||||
|
work = work_from_handle_assume_locked(handle); /* Re-checking work is sitll valid here in case work_do caused work to release */
|
||||||
|
if (work) {
|
||||||
|
while (work->status != WORK_STATUS_DONE) {
|
||||||
|
sys_condition_variable_wait(&work->condition_variable_finished, &L.mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_mutex_unlock(&L.mutex);
|
sys_mutex_unlock(&L.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user