use compiler static assert when possible
This commit is contained in:
parent
05ce4f32a1
commit
fdf35c698d
@ -4,7 +4,7 @@
|
|||||||
#define SH_DECL(t, n) struct CAT(sh_, t) n
|
#define SH_DECL(t, n) struct CAT(sh_, t) n
|
||||||
#define SH_DECLS(t, n) SH_DECL(t, n)
|
#define SH_DECLS(t, n) SH_DECL(t, n)
|
||||||
#define SH_ENTRY(rootsig) static
|
#define SH_ENTRY(rootsig) static
|
||||||
#define SH_ASSERT_32BIT(s, n) CT_ASSERT((sizeof(s) / 4) == n)
|
#define SH_ASSERT_32BIT(s, n) STATIC_ASSERT((sizeof(s) / 4) == n)
|
||||||
|
|
||||||
struct sh_uint { u32 v; };
|
struct sh_uint { u32 v; };
|
||||||
INLINE struct sh_uint sh_uint_from_u32(u32 v)
|
INLINE struct sh_uint sh_uint_from_u32(u32 v)
|
||||||
@ -34,7 +34,7 @@ struct sh_float4x4 { f32 v[4][4]; };
|
|||||||
INLINE struct sh_float4x4 sh_float4x4_from_mat4x4(struct mat4x4 v)
|
INLINE struct sh_float4x4 sh_float4x4_from_mat4x4(struct mat4x4 v)
|
||||||
{
|
{
|
||||||
struct sh_float4x4 res;
|
struct sh_float4x4 res;
|
||||||
CT_ASSERT(sizeof(res) == sizeof(v));
|
STATIC_ASSERT(sizeof(res) == sizeof(v));
|
||||||
MEMCPY(&res, v.e, sizeof(res));
|
MEMCPY(&res, v.e, sizeof(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ struct sh_float2x3 { f32 v[2][3]; };
|
|||||||
INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v)
|
INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v)
|
||||||
{
|
{
|
||||||
struct sh_float2x3 res;
|
struct sh_float2x3 res;
|
||||||
CT_ASSERT(sizeof(res) == sizeof(v));
|
STATIC_ASSERT(sizeof(res) == sizeof(v));
|
||||||
MEMCPY(&res, &v, sizeof(res));
|
MEMCPY(&res, &v, sizeof(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -219,8 +219,8 @@ void sys_app_entry(struct string args_str)
|
|||||||
|
|
||||||
#if !RTC
|
#if !RTC
|
||||||
/* Verify test modes aren't left on by accident in release mode */
|
/* Verify test modes aren't left on by accident in release mode */
|
||||||
CT_ASSERT(BITBUFF_DEBUG == 0);
|
STATIC_ASSERT(BITBUFF_DEBUG == 0);
|
||||||
CT_ASSERT(BITBUFF_TEST == 0);
|
STATIC_ASSERT(BITBUFF_TEST == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BITBUFF_TEST
|
#if BITBUFF_TEST
|
||||||
|
|||||||
@ -33,8 +33,8 @@ struct arena *arena_alloc(u64 reserve)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
|
ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
|
||||||
CT_ASSERT(ARENA_HEADER_SIZE <= ARENA_BLOCK_SIZE); /* Header must fit in first block */
|
STATIC_ASSERT(ARENA_HEADER_SIZE <= ARENA_BLOCK_SIZE); /* Header must fit in first block */
|
||||||
CT_ASSERT(sizeof(struct arena) <= ARENA_HEADER_SIZE); /* Arena struct must fit in header */
|
STATIC_ASSERT(sizeof(struct arena) <= ARENA_HEADER_SIZE); /* Arena struct must fit in header */
|
||||||
|
|
||||||
__profalloc(base, ARENA_BLOCK_SIZE);
|
__profalloc(base, ARENA_BLOCK_SIZE);
|
||||||
ASAN_POISON(base + sizeof(struct arena), ARENA_BLOCK_SIZE - sizeof(struct arena));
|
ASAN_POISON(base + sizeof(struct arena), ARENA_BLOCK_SIZE - sizeof(struct arena));
|
||||||
|
|||||||
@ -141,7 +141,7 @@ INLINE void *_arena_push_dry(struct arena *arena, u64 align)
|
|||||||
INLINE struct arena_temp _scratch_begin(struct arena *potential_conflict)
|
INLINE struct arena_temp _scratch_begin(struct arena *potential_conflict)
|
||||||
{
|
{
|
||||||
/* This function is currently hard-coded to support 2 scratch arenas */
|
/* This function is currently hard-coded to support 2 scratch arenas */
|
||||||
CT_ASSERT(SYS_SCRATCH_ARENAS_PER_FIBER == 2);
|
STATIC_ASSERT(SYS_SCRATCH_ARENAS_PER_CTX == 2);
|
||||||
|
|
||||||
/* Use `scratch_begin_no_conflict` if no conflicts are present */
|
/* Use `scratch_begin_no_conflict` if no conflicts are present */
|
||||||
ASSERT(potential_conflict != NULL);
|
ASSERT(potential_conflict != NULL);
|
||||||
|
|||||||
@ -600,7 +600,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
/* Clip to determine final points */
|
/* Clip to determine final points */
|
||||||
if (colliding) {
|
if (colliding) {
|
||||||
/* Max vertices must be < 16 to fit in 4 bit ids */
|
/* Max vertices must be < 16 to fit in 4 bit ids */
|
||||||
CT_ASSERT(countof(shape0->points) <= 16);
|
STATIC_ASSERT(countof(shape0->points) <= 16);
|
||||||
|
|
||||||
struct collider_menkowski_feature f = epa_res.closest_feature;
|
struct collider_menkowski_feature f = epa_res.closest_feature;
|
||||||
|
|
||||||
|
|||||||
14
src/common.h
14
src/common.h
@ -119,9 +119,17 @@ extern "C" {
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Compile time assert */
|
/* Compile time assert */
|
||||||
#define CT_ASSERT3(cond, line) struct CT_ASSERT_____##line {int foo[(cond) ? 1 : -1];}
|
#if LANGUAGE_C && (__STDC_VERSION__ < 202311L)
|
||||||
#define CT_ASSERT2(cond, line) CT_ASSERT3(cond, line)
|
# if COMPILER_MSVC
|
||||||
#define CT_ASSERT(cond) CT_ASSERT2(cond, __LINE__)
|
# define STATIC_ASSERT3(cond, line) struct STATIC_ASSERT_____##line {int foo[(cond) ? 1 : -1];}
|
||||||
|
# define STATIC_ASSERT2(cond, line) STATIC_ASSERT3(cond, line)
|
||||||
|
# define STATIC_ASSERT(cond) STATIC_ASSERT2(cond, __LINE__)
|
||||||
|
# else
|
||||||
|
# define STATIC_ASSERT(cond) _Static_assert(cond, "")
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define STATIC_ASSERT(c) static_assert(c, "")
|
||||||
|
#endif
|
||||||
|
|
||||||
#if COMPILER_MSVC
|
#if COMPILER_MSVC
|
||||||
# if DEBINFO
|
# if DEBINFO
|
||||||
|
|||||||
@ -38,18 +38,11 @@ struct worker_job_queue {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(64) worker_ctx {
|
struct alignas(64) worker_ctx {
|
||||||
/* 4 bytes */
|
|
||||||
i32 worker_id; /* Will be -1 if thread is not a worker */
|
i32 worker_id; /* Will be -1 if thread is not a worker */
|
||||||
/* 4 bytes */
|
|
||||||
i32 pin_depth;
|
i32 pin_depth;
|
||||||
/* 4 bytes */
|
|
||||||
b32 initialized;
|
b32 initialized;
|
||||||
/* 52 bytes */
|
|
||||||
u8 padding[52];
|
|
||||||
};
|
};
|
||||||
/* One ctx per cache line (prevent false sharing) */
|
STATIC_ASSERT(alignof(struct worker_ctx) == 64); /* To avoid false sharing */
|
||||||
CT_ASSERT(alignof(struct worker_ctx) == 64);
|
|
||||||
CT_ASSERT(sizeof(struct worker_ctx) == 64);
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Global state
|
* Global state
|
||||||
|
|||||||
@ -92,8 +92,8 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
struct collider_collision_points_result collider_res = collider_collision_points(&e0_collider, &e1_collider, e0_xf, e1_xf);
|
struct collider_collision_points_result collider_res = collider_collision_points(&e0_collider, &e1_collider, e0_xf, e1_xf);
|
||||||
|
|
||||||
/* Parts of algorithm are hard-coded to support 2 contact points */
|
/* Parts of algorithm are hard-coded to support 2 contact points */
|
||||||
CT_ASSERT(countof(constraint_ent->contact_constraint_data.points) == 2);
|
STATIC_ASSERT(countof(constraint_ent->contact_constraint_data.points) == 2);
|
||||||
CT_ASSERT(countof(collider_res.points) == 2);
|
STATIC_ASSERT(countof(collider_res.points) == 2);
|
||||||
|
|
||||||
struct phys_contact_constraint *constraint = NULL;
|
struct phys_contact_constraint *constraint = NULL;
|
||||||
if (collider_res.num_points > 0) {
|
if (collider_res.num_points > 0) {
|
||||||
|
|||||||
@ -172,7 +172,7 @@ enum sim_tile_kind {
|
|||||||
|
|
||||||
NUM_SIM_TILE_KINDS
|
NUM_SIM_TILE_KINDS
|
||||||
};
|
};
|
||||||
CT_ASSERT(NUM_SIM_TILE_KINDS < 256); /* Tile kind must fit in 8 bits */
|
STATIC_ASSERT(NUM_SIM_TILE_KINDS < 256); /* Tile kind must fit in 8 bits */
|
||||||
|
|
||||||
struct sim_ent_bin;
|
struct sim_ent_bin;
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char
|
|||||||
res.valid = true;
|
res.valid = true;
|
||||||
res.family = SOCK_ADDRESS_FAMILY_IPV4;
|
res.family = SOCK_ADDRESS_FAMILY_IPV4;
|
||||||
res.portnb = sockaddr->sin_port;
|
res.portnb = sockaddr->sin_port;
|
||||||
CT_ASSERT(sizeof(sockaddr->sin_addr) == 4);
|
STATIC_ASSERT(sizeof(sockaddr->sin_addr) == 4);
|
||||||
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
|
MEMCPY(res.ipnb, (void *)&sockaddr->sin_addr, 4);
|
||||||
break;
|
break;
|
||||||
} else if (ai_res->ai_family == AF_INET6) {
|
} else if (ai_res->ai_family == AF_INET6) {
|
||||||
@ -89,7 +89,7 @@ INTERNAL struct sock_address sock_address_from_ip_port_cstr(char *ip_cstr, char
|
|||||||
res.valid = true;
|
res.valid = true;
|
||||||
res.family = SOCK_ADDRESS_FAMILY_IPV6;
|
res.family = SOCK_ADDRESS_FAMILY_IPV6;
|
||||||
res.portnb = sockaddr->sin6_port;
|
res.portnb = sockaddr->sin6_port;
|
||||||
CT_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
|
STATIC_ASSERT(sizeof(sockaddr->sin6_addr) == 16);
|
||||||
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
|
MEMCPY(res.ipnb, (void *)&sockaddr->sin6_addr, 16);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
* It will entries until the budget has shrunk < target. */
|
* It will entries until the budget has shrunk < target. */
|
||||||
#define CACHE_MEMORY_BUDGET_THRESHOLD (MEGABYTE(256))
|
#define CACHE_MEMORY_BUDGET_THRESHOLD (MEGABYTE(256))
|
||||||
#define CACHE_MEMORY_BUDGET_TARGET (MEGABYTE(128))
|
#define CACHE_MEMORY_BUDGET_TARGET (MEGABYTE(128))
|
||||||
CT_ASSERT(CACHE_MEMORY_BUDGET_THRESHOLD >= CACHE_MEMORY_BUDGET_TARGET);
|
STATIC_ASSERT(CACHE_MEMORY_BUDGET_THRESHOLD >= CACHE_MEMORY_BUDGET_TARGET);
|
||||||
|
|
||||||
#define CACHE_BINS_COUNT 1024
|
#define CACHE_BINS_COUNT 1024
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ struct cache_refcount {
|
|||||||
i32 count; /* Number of scopes currently holding a reference to this entry */
|
i32 count; /* Number of scopes currently holding a reference to this entry */
|
||||||
i32 last_ref_cycle; /* Last evictor cycle that the refcount was modified */
|
i32 last_ref_cycle; /* Last evictor cycle that the refcount was modified */
|
||||||
};
|
};
|
||||||
CT_ASSERT(sizeof(struct cache_refcount) == 8); /* Must fit into 64 bit atomic */
|
STATIC_ASSERT(sizeof(struct cache_refcount) == 8); /* Must fit into 64 bit atomic */
|
||||||
|
|
||||||
struct cache_entry_hash {
|
struct cache_entry_hash {
|
||||||
u64 v;
|
u64 v;
|
||||||
|
|||||||
@ -485,7 +485,7 @@ b32 sys_run_command(struct string cmd);
|
|||||||
* Fiber
|
* Fiber
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define SYS_MAX_FIBERS 65536
|
#define SYS_MAX_FIBERS 4096
|
||||||
|
|
||||||
i32 sys_current_fiber_id(void);
|
i32 sys_current_fiber_id(void);
|
||||||
|
|
||||||
@ -493,10 +493,10 @@ i32 sys_current_fiber_id(void);
|
|||||||
* Scratch
|
* Scratch
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define SYS_SCRATCH_ARENAS_PER_FIBER 2
|
#define SYS_SCRATCH_ARENAS_PER_CTX 2
|
||||||
|
|
||||||
struct sys_scratch_ctx {
|
struct sys_scratch_ctx {
|
||||||
struct arena *arenas[SYS_SCRATCH_ARENAS_PER_FIBER];
|
struct arena *arenas[SYS_SCRATCH_ARENAS_PER_CTX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 fiber_id);
|
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 fiber_id);
|
||||||
|
|||||||
@ -114,18 +114,14 @@ struct win32_window {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define FIBER_CTX_SLEEP_TIMER_INIT_MAGIC ((HANDLE)0x48e87857650169c8)
|
||||||
struct alignas(64) fiber_ctx {
|
struct alignas(64) fiber_ctx {
|
||||||
i32 id; /* 4 bytes */
|
|
||||||
u8 pad0[4]; /* 4 bytes */
|
|
||||||
HANDLE sleep_timer; /* 8 bytes */
|
HANDLE sleep_timer; /* 8 bytes */
|
||||||
struct sys_scratch_ctx scratch_ctx; /* 16 bytes */
|
struct sys_scratch_ctx scratch_ctx; /* 16 bytes */
|
||||||
u8 pad1[16]; /* 32 bytes */
|
u8 pad[40]; /* 40 bytes */
|
||||||
};
|
};
|
||||||
CT_ASSERT(sizeof(struct fiber_ctx) == 64);
|
STATIC_ASSERT(sizeof(struct fiber_ctx) == 64); /* Assume ctx fits in one cache line (increase if necessary) */
|
||||||
CT_ASSERT(alignof(struct fiber_ctx) == 64);
|
STATIC_ASSERT(alignof(struct fiber_ctx) == 64); /* To avoid false sharing */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +136,6 @@ GLOBAL struct {
|
|||||||
i64 qpc_per_second;
|
i64 qpc_per_second;
|
||||||
i64 ns_per_qpc;
|
i64 ns_per_qpc;
|
||||||
i32 scheduler_period_ms;
|
i32 scheduler_period_ms;
|
||||||
DWORD thread_tls_index;
|
|
||||||
u32 main_thread_id;
|
u32 main_thread_id;
|
||||||
|
|
||||||
wchar_t cmdline_args_wstr[8192];
|
wchar_t cmdline_args_wstr[8192];
|
||||||
@ -206,8 +201,7 @@ INTERNAL i32 fiber_ctx_init(void)
|
|||||||
}
|
}
|
||||||
struct fiber_ctx *ctx = &G.fiber_contexts[id];
|
struct fiber_ctx *ctx = &G.fiber_contexts[id];
|
||||||
{
|
{
|
||||||
ctx->id = id;
|
ctx->sleep_timer = FIBER_CTX_SLEEP_TIMER_INIT_MAGIC;
|
||||||
ctx->sleep_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -223,7 +217,7 @@ i32 sys_current_fiber_id(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Scratch
|
* Scratch ctx
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 id)
|
struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 id)
|
||||||
@ -231,7 +225,7 @@ struct sys_scratch_ctx *sys_scratch_ctx_from_fiber_id(i32 id)
|
|||||||
struct fiber_ctx *fiber_ctx = fiber_ctx_from_id(id);
|
struct fiber_ctx *fiber_ctx = fiber_ctx_from_id(id);
|
||||||
struct sys_scratch_ctx *scratch_ctx = &fiber_ctx->scratch_ctx;
|
struct sys_scratch_ctx *scratch_ctx = &fiber_ctx->scratch_ctx;
|
||||||
if (!scratch_ctx->arenas[0]) {
|
if (!scratch_ctx->arenas[0]) {
|
||||||
__profscope(Initialize scratch ctx);
|
__profscope(Initialize scratch context);
|
||||||
for (u32 i = 0; i < countof(scratch_ctx->arenas); ++i) {
|
for (u32 i = 0; i < countof(scratch_ctx->arenas); ++i) {
|
||||||
scratch_ctx->arenas[i] = arena_alloc(GIGABYTE(64));
|
scratch_ctx->arenas[i] = arena_alloc(GIGABYTE(64));
|
||||||
}
|
}
|
||||||
@ -2261,7 +2255,7 @@ void sys_panic(struct string msg)
|
|||||||
WRITE_BARRIER();
|
WRITE_BARRIER();
|
||||||
SetEvent(G.panic_event);
|
SetEvent(G.panic_event);
|
||||||
|
|
||||||
/* Wait for thread to be terminated */
|
/* Wait for process termination */
|
||||||
if (GetCurrentThreadId() != G.main_thread_id) {
|
if (GetCurrentThreadId() != G.main_thread_id) {
|
||||||
Sleep(INFINITE);
|
Sleep(INFINITE);
|
||||||
}
|
}
|
||||||
@ -2274,7 +2268,7 @@ void sys_panic(struct string msg)
|
|||||||
|
|
||||||
/* https://blog.bearcats.nl/perfect-sleep-function/ */
|
/* https://blog.bearcats.nl/perfect-sleep-function/ */
|
||||||
|
|
||||||
INTERNAL void win32_precise_sleep_timer(f64 seconds, HANDLE timer)
|
INTERNAL void win32_precise_sleep_timer(HANDLE timer, f64 seconds)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -2359,9 +2353,14 @@ void sys_sleep_precise(f64 seconds)
|
|||||||
__prof;
|
__prof;
|
||||||
struct fiber_ctx *ctx = fiber_ctx_from_id(sys_current_fiber_id());
|
struct fiber_ctx *ctx = fiber_ctx_from_id(sys_current_fiber_id());
|
||||||
HANDLE timer = ctx->sleep_timer;
|
HANDLE timer = ctx->sleep_timer;
|
||||||
|
if (timer == FIBER_CTX_SLEEP_TIMER_INIT_MAGIC) {
|
||||||
|
__profscope(Create high resolution timer);
|
||||||
|
timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
||||||
|
ctx->sleep_timer = timer;
|
||||||
|
}
|
||||||
if (timer) {
|
if (timer) {
|
||||||
/* Use newer sleeping method */
|
/* Use newer sleeping method */
|
||||||
win32_precise_sleep_timer(seconds, timer);
|
win32_precise_sleep_timer(timer, seconds);
|
||||||
} else {
|
} else {
|
||||||
/* Fall back to older sleep method if CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
/* Fall back to older sleep method if CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||||
* is not available due to older windows version */
|
* is not available due to older windows version */
|
||||||
@ -2476,14 +2475,6 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
G.windows_mutex = sys_mutex_alloc();
|
G.windows_mutex = sys_mutex_alloc();
|
||||||
G.windows_arena = arena_alloc(GIGABYTE(64));
|
G.windows_arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
/* Set up TLS index */
|
|
||||||
G.thread_tls_index = TlsAlloc();
|
|
||||||
if (G.thread_tls_index == TLS_OUT_OF_INDEXES) {
|
|
||||||
/* TODO: GetLastError */
|
|
||||||
error_msg = L"Platform initialization error: TLS_OUT_OF_INDEXES";
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize vk table */
|
/* Initialize vk table */
|
||||||
win32_init_vk_btn_table();
|
win32_init_vk_btn_table();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user