From a1ffe981a660829eecdafba2e11fedaf2985c522 Mon Sep 17 00:00:00 2001 From: tijani Date: Thu, 8 Aug 2024 06:40:00 -0500 Subject: [PATCH] threading context in place because we are a multi-threading system dammit! --- src/base/base_core.h | 48 ++++++++++++++++----- src/base/base_inc.c | 3 +- src/base/base_inc.h | 3 +- src/base/base_markup.c | 14 ++++++ src/base/base_markup.h | 10 +++++ src/base/base_threading_context.c | 71 +++++++++++++++++++++++++++++++ src/base/base_threading_context.h | 30 +++++++++++++ 7 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 src/base/base_markup.c create mode 100644 src/base/base_markup.h create mode 100644 src/base/base_threading_context.c create mode 100644 src/base/base_threading_context.h diff --git a/src/base/base_core.h b/src/base/base_core.h index 5ba53ec..4c2973d 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -16,18 +16,18 @@ typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; -typedef s8 b8; -typedef s16 b16; -typedef s32 b32; -typedef s64 b64; +typedef s8 b8; +typedef s16 b16; +typedef s32 b32; +typedef s64 b64; -typedef float f32; -typedef double f64; +typedef float f32; +typedef double f64; // Units #define KB(n) (((u64)(n)) << 10) @@ -38,8 +38,34 @@ typedef double f64; #define Million(n) ((n) * 1000000) #define Billion(n) ((n) * 1000000000) +// C++ linking shenanigans +#if LANG_CPP + #define C_LINK_BEGIN extern "C" { + #define C_LINK_END } + #define C_LINK extern "C" +#else + #define C_LINK_BEGIN + #define C_LINK_END + #define C_LINK + +#endif + +// Threads stuff +#if COMPILER_MSVC + #define thread_static __declspec(thread) +#else + #error "Thread local storage supported this platform." +#endif + +// Misc helpers +// NOTE(tijani): Divides total size of array by size of one element in the array gives +// the number of elements in the array. +#define ArrayCount(array_to_count) (sizeof(array_to_count) / sizeof((array_to_count)[0])) + // Memory operations -#define MemoryZero(dest, count) memset((dest), 0, (count)) +#define MemoryZero(dest, count) memset((dest), 0, (count)) +#define MemoryZeroStruct(count) MemoryZero((count), sizeof(*(count))) +#define MemoryCopy(dest, src, src_size) memmove((dest), (src), (src_size)) // Max, Min, Clamps #define Max(A, B) (((A) > (B)) ? (A) : (B)) diff --git a/src/base/base_inc.c b/src/base/base_inc.c index ebe70f2..baebe29 100644 --- a/src/base/base_inc.c +++ b/src/base/base_inc.c @@ -2,5 +2,6 @@ #include "base_arena.c" #include "base_strings.c" - +#include "base_markup.c" +#include "base_threading_context.c" // clang-format on diff --git a/src/base/base_inc.h b/src/base/base_inc.h index d5ec4dc..2a86773 100644 --- a/src/base/base_inc.h +++ b/src/base/base_inc.h @@ -8,7 +8,8 @@ #include "base_arena.h" #include "base_strings.h" - +#include "base_markup.h" +#include "base_thread_context.h" // clang-format on #endif // BASE_INC_H diff --git a/src/base/base_markup.c b/src/base/base_markup.c new file mode 100644 index 0000000..6075fb0 --- /dev/null +++ b/src/base/base_markup.c @@ -0,0 +1,14 @@ +internal void set_thread_name(String8 str) { + // ??(tijani): Profiling + os_set_thread_name(str); +} + +internal void set_thread_namef(char *fmt, ...) { + Temp scratch = temp_begin(0, 0); + va_list args; + va_start(args, fmt); + String8 string = push_str8fv(scratch.arena, fmt, args); + set_thread_name(string); + va_end(args); + scratch_end(scratch); +} diff --git a/src/base/base_markup.h b/src/base/base_markup.h new file mode 100644 index 0000000..5758cde --- /dev/null +++ b/src/base/base_markup.h @@ -0,0 +1,10 @@ +#ifndef BASE_MARKUP_H +#define BASE_MARKUP_H + +internal void set_thread_name(String8 string); +internal void set_thread_namef(char *fmt, ...); + +#define ThreadName(str) (set_thread_name(str)) +#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__)) + +#endif // BASE_MARKUP_H diff --git a/src/base/base_threading_context.c b/src/base/base_threading_context.c new file mode 100644 index 0000000..5d25e82 --- /dev/null +++ b/src/base/base_threading_context.c @@ -0,0 +1,71 @@ +// Thread related functions +C_LINK thread_static THCTX *thctx_thread_local; + +internal void thctx_init_and_equip(THCTX *thctx) { + MemoryZeroStruct(thctx); + Arena **arena_ptr = thctx->arenas; + for (u64 i = 0; i < ArrayCount(thctx->arenas); i += 1, arena_ptr += 1) { + *arena_ptr = arena_alloc(); + } + thctx_thread_local = thctx; +} + +internal void thctx_release(void) { + for (u64 i = 0; i < ArrayCount(thctx_thread_local->arenas); i += 1) { + arena_release(thctx_thread_local->arenas[i]); + } +} + +internal THCTX *thctx_get_equipped(void){return (thctx_thread_local)} + +// NOTE(tijani): This is used by a thread get temporary memory +// for use (scratch space). It makes sure their are no conflics +// in the memory block it's selecting before assigning it to the +// thread that needs it. +internal Arena *thctx_get_scratch(Arena **conflicts, u64 count) { + THCTX *thctx = thctx_get_equipped(); + Arena *memory = 0; + Arena **arena_ptr = thctx->arenas; + + for (u64 i = 0; i < ArrayCount(thctx->arenas); i += 1, arena_ptr += 1) { + Arena **conflicts_ptr = conflicts; + b32 has_conflict = 0; + + for (u64 j = 0; j < count; j += 1, conflicts_ptr += 1) { + if (*arena_ptr == *conflicts_ptr) { + has_conflicts = 1; + break; + } + } + if (!has_conflicts) { + memory = *arena_ptr; + break; + } + } + return (memory); +} + +internal void thctx_set_thread_name(String8 name) { + THCTX *thctx = thctx_get_equipped(); + u64 size = ClampTop(name.size, sizeof(thctx->thread_name)); + MemoryCopy(thctx->thread_name, name.str, size); + thctx->thread_name_size = size; +} + +internal String8 thctx_get_thread_name(void) { + THCTX *thctx = thctx_get_equipped(); + String8 name = str8(thctx->thread_name, thctx->thread_name_size); + return (name); +} + +internal void thctx_write_srcloc(char *file_name, u64 line_number) { + THCTX *thctx = thctx_get_equipped(); + thctx->file_name = file_name; + thctx->line_number = line_number; +} + +internal void thctx_read_srcloc(char **file_name, u64 *line_number) { + THCTX *thctx = thctx_get_equipped(); + *file_name = thctx->file_name; + *line_number = thctx->line_number; +} diff --git a/src/base/base_threading_context.h b/src/base/base_threading_context.h new file mode 100644 index 0000000..78e47b8 --- /dev/null +++ b/src/base/base_threading_context.h @@ -0,0 +1,30 @@ +#ifndef BASE_THREAD_CONTEXT_H +#define BASE_THREAD_CONTEXT_H + +typedef struct THCTX THCTX; +struct THCTX { + Arena *arenas[2]; + u8 thread_name[32]; + u64 thread_name_size; + + char *file_name; + u64 line_number; +}; + +// Thread related functions +internal void thctx_init_and_equip(THCTX *thctx); +internal void thctx_release(void); +internal THCTX *thctx_get_equipped(void); +internal Arena *thctx_get_scratch(Arena **conflicts, u64 count); +internal void thctx_set_thread_name(String8 name); +internal String8 thctx_get_thread_name(void); + +// NOTE(tijani): Debugging errors within a thread context. +internal void thctx_write_srcloc(char *file_name, u64 line_number); +internal void thctx_read_srcloc(char **file_name, u64 *line_number); +#define thctx_write_this_srcloc() thctx_write_srcloc(__FILE__, __LINE__); + +#define scratch_begin(conflicts, count) temp_begin(thctx_get_scratch((conflicts), (count))) +#define scratch_end(scratch) temp_end(scratch) + +#endif // BASE_THREAD_CONTEXT_H