Commit: f08977594719b224db2710dd3f575bcda35bafeb
Parent: 2236c1d733d7fca11793307b2680239c8084a080
Author: Randy Palamar
Date: Tue, 1 Sep 2026 19:42:40 -0700
base_platform: move thread/barrier functions into platform layer
This way they can be used from tests/other code.
Diffstat:
11 files changed, 374 insertions(+), 368 deletions(-)
diff --git a/base_linux.c b/base_linux.c
@@ -24,7 +24,76 @@
#include <sys/sysinfo.h>
#include <unistd.h>
-global OSSystemInfo linux_system_info;
+typedef struct OSLinuxEntity OSLinuxEntity;
+typedef struct {
+ void *handle;
+ OSLinuxEntity *prev, *next;
+} OSLinuxWindow;
+
+typedef enum {
+ OSLinuxFileWatchKind_Platform,
+ OSLinuxFileWatchKind_User,
+} OSLinuxFileWatchKind;
+
+typedef struct OSLinuxFileWatchDirectory OSLinuxFileWatchDirectory;
+typedef struct OSLinuxFileWatch OSLinuxFileWatch;
+struct OSLinuxFileWatch {
+ OSLinuxFileWatchKind kind;
+ u64 hash;
+ u64 update_time;
+ void *user_context;
+
+ OSLinuxFileWatchDirectory *parent;
+ OSLinuxFileWatch *prev, *next;
+};
+
+struct OSLinuxFileWatchDirectory {
+ u64 hash;
+ i64 handle;
+ str8 name;
+
+ OSLinuxFileWatch *first_child;
+ OSLinuxFileWatch *last_child;
+ OSLinuxFileWatchDirectory *prev, *next;
+};
+
+typedef enum {
+ OSLinuxEntityKind_Window,
+ OSLinuxEntityKind_FileWatch,
+ OSLinuxEntityKind_FileWatchDirectory,
+} OSLinuxEntityKind;
+
+struct OSLinuxEntity {
+ OSLinuxEntityKind kind;
+ union {
+ OSLinuxFileWatch file_watch;
+ OSLinuxFileWatchDirectory file_watch_directory;
+ OSLinuxWindow window;
+ } as;
+ OSLinuxEntity *next;
+};
+
+typedef struct {
+ OSSystemInfo system_info;
+
+ Arena *arena;
+ i32 arena_lock;
+
+ i32 inotify_handle;
+
+ struct {
+ OSLinuxFileWatchDirectory *first;
+ OSLinuxFileWatchDirectory *last;
+ } file_watch_directories;
+
+ struct {
+ OSLinuxEntity *first;
+ OSLinuxEntity *last;
+ } windows;
+
+ OSLinuxEntity *entity_freelist;
+} OSLinux_Context;
+global OSLinux_Context os_linux_context;
function b32
os_write_file(i32 file, void *data, i64 length)
@@ -75,20 +144,20 @@ os_number_of_processors(void)
function void
os_system_info_init(void)
{
- linux_system_info.timer_frequency = os_timer_frequency();
- linux_system_info.logical_processor_count = os_number_of_processors();
- linux_system_info.page_size = ARCH_X64? KB(4) : getauxval(AT_PAGESZ);
- linux_system_info.path_separator_byte = '/';
+ os_linux_context.system_info.timer_frequency = os_timer_frequency();
+ os_linux_context.system_info.logical_processor_count = os_number_of_processors();
+ os_linux_context.system_info.page_size = ARCH_X64? KB(4) : getauxval(AT_PAGESZ);
+ os_linux_context.system_info.path_separator_byte = '/';
}
BASE_EXPORT OSSystemInfo *
os_system_info(void)
{
#if BASE_PLATFORM_NO_MAIN
- if unlikely(linux_system_info.path_separator_byte == 0)
+ if unlikely(os_linux_context.system_info.path_separator_byte == 0)
os_system_info_init();
#endif
- return &linux_system_info;
+ return &os_linux_context.system_info;
}
BASE_EXPORT void *
@@ -195,6 +264,60 @@ os_copy_file(char *name, char *new)
return result;
}
+function OSLinuxEntity *
+os_entity_allocate(OSLinuxEntityKind kind)
+{
+ OSLinuxEntity *result = 0;
+ DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
+ {
+ result = SLLPopFreelist(os_linux_context.entity_freelist);
+ if (!result) result = push_struct_no_zero(os_linux_context.arena, OSLinuxEntity);
+ }
+
+ zero_struct(result);
+ result->kind = kind;
+ return result;
+}
+
+BASE_EXPORT OSThread
+os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn)
+{
+ pthread_t thread;
+ pthread_create(&thread, 0, (void *)fn, (void *)user_context);
+
+ if (name) {
+ char buffer[16];
+ str8 name_str = str8_from_c_str((char *)name);
+ u64 length = (u64)Clamp(name_str.length, 0, countof(buffer) - 1);
+ memory_copy(buffer, (char *)name, length);
+ buffer[length] = 0;
+ pthread_setname_np(thread, buffer);
+ }
+
+ OSThread result = {(u64)thread};
+ return result;
+}
+
+BASE_EXPORT OSBarrier
+os_barrier_alloc(u32 count)
+{
+ OSBarrier result = {0};
+ DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
+ {
+ pthread_barrier_t *barrier = push_struct(os_linux_context.arena, pthread_barrier_t);
+ pthread_barrier_init(barrier, 0, count);
+ result.value[0] = (u64)barrier;
+ }
+ return result;
+}
+
+BASE_EXPORT void
+os_barrier_enter(OSBarrier barrier)
+{
+ pthread_barrier_t *b = (pthread_barrier_t *)barrier.value[0];
+ if (b) pthread_barrier_wait(b);
+}
+
BASE_EXPORT b32
os_wait_on_address(i32 *value, i32 current, u32 timeout_ms)
{
@@ -223,6 +346,7 @@ extern i32
main(i32 argc, char *argv[])
{
os_system_info_init();
+ os_linux_context.arena = arena_create(.name = "Platform Arena");
entry_point(argc, argv);
diff --git a/base_platform.h b/base_platform.h
@@ -2,6 +2,21 @@
#ifndef BASE_PLATFORM_H
#define BASE_PLATFORM_H
+/*
+ * CONFIGURATION
+ *
+ * BASE_EXPORT
+ * the attributes for functions defined by the platfom layer. for example
+ * `#define BASE_EXPORT static` in a single translation unit build
+ *
+ * BASE_IMPORT
+ * the attributes to apply on the entry_point() called from main()
+ *
+ * BASE_PLATFORM_NO_MAIN:
+ * define if you do not want a main() function (useful for library code)
+ *
+ */
+
#ifndef BASE_EXPORT
#define BASE_EXPORT
#endif
@@ -12,6 +27,9 @@
#ifndef BASE_PLATFORM_NO_MAIN
#define BASE_PLATFORM_NO_MAIN 0
+#else
+#undef BASE_PLATFORM_NO_MAIN
+#define BASE_PLATFORM_NO_MAIN 1
#endif
#include "base_types.h"
@@ -50,12 +68,15 @@ BASE_EXPORT u64 os_timer_count(void);
BASE_EXPORT str8 os_read_entire_file(Arena *arena, const char *file);
+BASE_EXPORT OSThread os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn);
+BASE_EXPORT OSBarrier os_barrier_alloc(u32 thread_count);
+BASE_EXPORT void os_barrier_enter(OSBarrier);
+
/* NOTE(rnp): memory watch timed waiting functions. (-1) is an infinite timeout.
* Used with the intention of yielding the thread back to the OS. */
BASE_EXPORT u32 os_wait_on_address(i32 *lock, i32 current, u32 timeout_ms);
BASE_EXPORT void os_wake_all_waiters(i32 *lock);
-
/* NOTE(rnp): this functionality is only needed on win32 to provide cross process
* synchronization. While posix has equivalent functionality there is no reason to
* use it over a value located in shared memory. */
diff --git a/base_win32.c b/base_win32.c
@@ -87,6 +87,14 @@ typedef struct {
iptr event_handle;
} w32_overlapped;
+typedef struct {
+ u32 reserved1;
+ u32 reserved2;
+ u64 Reserved3[2];
+ u32 reserved4;
+ u32 reserved5;
+} w32_synchronization_barrier;
+
typedef enum {
W32IOEvent_FileWatch,
} W32IOEvent;
@@ -96,11 +104,6 @@ typedef struct {
iptr context;
} w32_io_completion_event;
-typedef struct {
- iptr *semaphores;
- u32 reserved_count;
-} w32_shared_memory_context;
-
#define W32(r) __declspec(dllimport) r __stdcall
W32(b32) CloseHandle(iptr);
W32(b32) CopyFileA(c8 *, c8 *, b32);
@@ -108,7 +111,9 @@ W32(iptr) CreateFileA(c8 *, u32, u32, void *, u32, u32, void *);
W32(iptr) CreateFileMappingA(iptr, void *, u32, u32, u32, c8 *);
W32(iptr) CreateIoCompletionPort(iptr, iptr, uptr, u32);
W32(iptr) CreateSemaphoreA(iptr, i32, i32, c8 *);
+W32(u64) CreateThread(iptr, u64, iptr, iptr, u32, u32 *);
W32(b32) DeleteFileA(c8 *);
+W32(b32) EnterSynchronizationBarrier(w32_synchronization_barrier *, u32);
W32(void) ExitProcess(i32);
W32(i32) GetFileAttributesA(c8 *);
W32(b32) GetFileInformationByHandle(iptr, void *);
@@ -116,12 +121,14 @@ W32(i32) GetLastError(void);
W32(b32) GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32);
W32(iptr) GetStdHandle(i32);
W32(void) GetSystemInfo(w32_system_info *);
+W32(b32) InitializeSynchronizationBarrier(w32_synchronization_barrier *, i32, i32);
W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64);
W32(b32) QueryPerformanceCounter(u64 *);
W32(b32) QueryPerformanceFrequency(u64 *);
W32(b32) ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *);
W32(b32) ReadFile(iptr, u8 *, i32, i32 *, void *);
W32(b32) ReleaseSemaphore(iptr, i32, i32 *);
+W32(i32) SetThreadDescription(u64, u16 *);
W32(u32) WaitForSingleObject(iptr, u32);
W32(b32) WaitOnAddress(void *, void *, u64, u32);
W32(i32) WakeByAddressAll(void *);
@@ -130,7 +137,83 @@ W32(void *) VirtualAlloc(u8 *, i64, u32, u32);
W32(b32) VirtualFree(void *, u64, u32);
W32(b32) VirtualProtect(void *, u64, u32, u32 *);
-global OSSystemInfo win32_system_info;
+enum {OSW32_FileWatchDirectoryBufferSize = KB(4)};
+
+typedef struct OSW32Entity OSW32Entity;
+typedef struct {
+ void *handle;
+ OSW32Entity *prev, *next;
+} OSW32Window;
+
+typedef enum {
+ OSW32FileWatchKind_Platform,
+ OSW32FileWatchKind_User,
+} OSW32FileWatchKind;
+
+typedef struct OSW32FileWatchDirectory OSW32FileWatchDirectory;
+typedef struct OSW32FileWatch OSW32FileWatch;
+struct OSW32FileWatch {
+ OSW32FileWatchKind kind;
+ u64 hash;
+ u64 update_time;
+ void *user_context;
+
+ OSW32FileWatchDirectory *parent;
+ OSW32FileWatch *prev, *next;
+};
+
+struct OSW32FileWatchDirectory {
+ u64 hash;
+ i64 handle;
+ str8 name;
+
+ OSW32FileWatch *first_child;
+ OSW32FileWatch *last_child;
+ OSW32FileWatchDirectory *prev, *next;
+
+ w32_overlapped overlapped;
+ w32_io_completion_event event;
+
+ void *buffer;
+};
+
+typedef enum {
+ OSW32EntityKind_Window,
+ OSW32EntityKind_FileWatch,
+ OSW32EntityKind_FileWatchDirectory,
+} OSW32EntityKind;
+
+struct OSW32Entity {
+ OSW32EntityKind kind;
+ union {
+ OSW32FileWatch file_watch;
+ OSW32FileWatchDirectory file_watch_directory;
+ OSW32Window window;
+ } as;
+ OSW32Entity *next;
+};
+
+typedef struct {
+ OSSystemInfo system_info;
+
+ Arena *arena;
+ i32 arena_lock;
+ i64 error_handle;
+ i64 io_completion_handle;
+
+ struct {
+ OSW32FileWatchDirectory *first;
+ OSW32FileWatchDirectory *last;
+ } file_watch_directories;
+
+ struct {
+ OSW32Entity *first;
+ OSW32Entity *last;
+ } windows;
+
+ OSW32Entity *entity_freelist;
+} OSW32_Context;
+global OSW32_Context os_w32_context;
function b32
os_write_file(iptr file, void *data, i64 length)
@@ -169,20 +252,20 @@ os_system_info_init(void)
w32_system_info info = {0};
GetSystemInfo(&info);
- win32_system_info.timer_frequency = os_timer_frequency();
- win32_system_info.logical_processor_count = info.number_of_processors;
- win32_system_info.page_size = info.page_size;
- win32_system_info.path_separator_byte = '\\';
+ os_w32_context.system_info.timer_frequency = os_timer_frequency();
+ os_w32_context.system_info.logical_processor_count = info.number_of_processors;
+ os_w32_context.system_info.page_size = info.page_size;
+ os_w32_context.system_info.path_separator_byte = '\\';
}
BASE_EXPORT OSSystemInfo *
os_system_info(void)
{
#if BASE_PLATFORM_NO_MAIN
- if unlikely(win32_system_info.path_separator_byte == 0)
+ if unlikely(os_w32_context.system_info.path_separator_byte == 0)
os_system_info_init();
#endif
- return &win32_system_info;
+ return &os_w32_context.system_info;
}
BASE_EXPORT void *
@@ -291,6 +374,58 @@ os_copy_file(char *name, char *new)
return CopyFileA(name, new, 0);
}
+function OSW32Entity *
+os_entity_allocate(OSW32EntityKind kind)
+{
+ OSW32Entity *result = 0;
+ DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ {
+ result = SLLPopFreelist(os_w32_context.entity_freelist);
+ if (!result) result = push_struct_no_zero(os_w32_context.arena, OSW32Entity);
+ }
+
+ zero_struct(result);
+ result->kind = kind;
+ return result;
+}
+
+BASE_EXPORT OSThread
+os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn)
+{
+ OSThread result = {(u64)CreateThread(0, 0, (iptr)fn, (iptr)user_context, 0, 0)};
+ if (result.value[0]) {
+ Temp scratch;
+ DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
+ {
+ SetThreadDescription(result.value[0], str16_from_str8(scratch.arena, str8_from_c_str((c8 *)name)).data);
+ }
+ } else {
+ result.value[0] = OSInvalidHandleValue;
+ }
+ return result;
+}
+
+BASE_EXPORT OSBarrier
+os_barrier_alloc(u32 count)
+{
+ OSBarrier result = {0};
+ DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
+ {
+ w32_synchronization_barrier *barrier = push_struct(os_w32_context.arena, w32_synchronization_barrier);
+ InitializeSynchronizationBarrier(barrier, (i32)count, -1);
+ result.value[0] = (u64)barrier;
+ }
+ return result;
+}
+
+BASE_EXPORT void
+os_barrier_enter(OSBarrier barrier)
+{
+ w32_synchronization_barrier *b = (w32_synchronization_barrier *)barrier.value[0];
+ if (b) EnterSynchronizationBarrier(b, 0);
+}
+
BASE_EXPORT b32
os_wait_on_address(i32 *value, i32 current, u32 timeout_ms)
{
@@ -313,6 +448,8 @@ extern i32
main(i32 argc, char *argv[])
{
os_system_info_init();
+ os_w32_context.arena = arena_create(.name = "Platform Arena");
+ os_w32_context.error_handle = GetStdHandle(STD_ERROR_HANDLE);
entry_point(argc, argv);
diff --git a/beamformer.h b/beamformer.h
@@ -72,10 +72,6 @@ BEAMFORMER_IMPORT void os_add_file_watch(const char *path, int64_t pat
BEAMFORMER_IMPORT void * os_lookup_symbol(OSLibrary library, const char *symbol);
-BEAMFORMER_IMPORT OSThread os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn);
-BEAMFORMER_IMPORT OSBarrier os_barrier_alloc(u32 thread_count);
-BEAMFORMER_IMPORT void os_barrier_enter(OSBarrier);
-
// NOTE(rnp): currently beamformer will only create one window.
// once raylib is removed it may request multiple
BEAMFORMER_IMPORT OSWindow os_window_create(uint8_t *title, int64_t title_length, int32_t width, int32_t height);
diff --git a/beamformer_internal.h b/beamformer_internal.h
@@ -131,7 +131,6 @@ typedef struct {
} RenderModel;
#include "threads.c"
-#include "util_os_ui.c"
///////////////////////////
// NOTE: vulkan layer API
@@ -223,7 +222,7 @@ DEBUG_IMPORT renderdoc_end_frame_capture_fn *end_frame_capture;
#define renderdoc_attached(...) (0)
#endif
-#include "util_os.c"
+#include "util_os_ui.c"
///////////////////////////////
// NOTE: CUDA Library Bindings
diff --git a/lib/ogl_beamformer_lib.c b/lib/ogl_beamformer_lib.c
@@ -22,7 +22,6 @@ W32(iptr) OpenFileMappingA(u32, b32, c8 *);
#error Unsupported Platform
#endif
-#include "../util_os.c"
#include "../beamformer_compute_stats.c"
#include "../beamformer_shared_memory.c"
diff --git a/main_linux.c b/main_linux.c
@@ -32,130 +32,7 @@
#include <dlfcn.h>
-typedef struct OSLinuxEntity OSLinuxEntity;
-typedef struct {
- void *handle;
- OSLinuxEntity *prev, *next;
-} OSLinuxWindow;
-
-typedef enum {
- OSLinuxFileWatchKind_Platform,
- OSLinuxFileWatchKind_User,
-} OSLinuxFileWatchKind;
-
-typedef struct OSLinuxFileWatchDirectory OSLinuxFileWatchDirectory;
-typedef struct OSLinuxFileWatch OSLinuxFileWatch;
-struct OSLinuxFileWatch {
- OSLinuxFileWatchKind kind;
- u64 hash;
- u64 update_time;
- void *user_context;
-
- OSLinuxFileWatchDirectory *parent;
- OSLinuxFileWatch *prev, *next;
-};
-
-struct OSLinuxFileWatchDirectory {
- u64 hash;
- i64 handle;
- str8 name;
-
- OSLinuxFileWatch *first_child;
- OSLinuxFileWatch *last_child;
- OSLinuxFileWatchDirectory *prev, *next;
-};
-
-typedef enum {
- OSLinuxEntityKind_Window,
- OSLinuxEntityKind_FileWatch,
- OSLinuxEntityKind_FileWatchDirectory,
-} OSLinuxEntityKind;
-
-struct OSLinuxEntity {
- OSLinuxEntityKind kind;
- union {
- OSLinuxFileWatch file_watch;
- OSLinuxFileWatchDirectory file_watch_directory;
- OSLinuxWindow window;
- } as;
- OSLinuxEntity *next;
-};
-
-typedef struct {
- Arena *arena;
- i32 arena_lock;
-
- i32 inotify_handle;
-
- BeamformerInput *input;
-
- struct {
- OSLinuxFileWatchDirectory *first;
- OSLinuxFileWatchDirectory *last;
- } file_watch_directories;
-
- struct {
- OSLinuxEntity *first;
- OSLinuxEntity *last;
- } windows;
-
- OSLinuxEntity *entity_freelist;
-} OSLinux_Context;
-global OSLinux_Context os_linux_context;
-
-function OSLinuxEntity *
-os_entity_allocate(OSLinuxEntityKind kind)
-{
- OSLinuxEntity *result = 0;
- DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
- {
- result = SLLPopFreelist(os_linux_context.entity_freelist);
- if (!result) result = push_struct_no_zero(os_linux_context.arena, OSLinuxEntity);
- }
-
- zero_struct(result);
- result->kind = kind;
- return result;
-}
-
-BEAMFORMER_IMPORT OSThread
-os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn)
-{
- pthread_t thread;
- pthread_create(&thread, 0, (void *)fn, (void *)user_context);
-
- if (name) {
- char buffer[16];
- str8 name_str = str8_from_c_str((char *)name);
- u64 length = (u64)Clamp(name_str.length, 0, countof(buffer) - 1);
- memory_copy(buffer, (char *)name, length);
- buffer[length] = 0;
- pthread_setname_np(thread, buffer);
- }
-
- OSThread result = {(u64)thread};
- return result;
-}
-
-BEAMFORMER_IMPORT OSBarrier
-os_barrier_alloc(u32 count)
-{
- OSBarrier result = {0};
- DeferLoop(take_lock(&os_linux_context.arena_lock, -1), release_lock(&os_linux_context.arena_lock))
- {
- pthread_barrier_t *barrier = push_struct(os_linux_context.arena, pthread_barrier_t);
- pthread_barrier_init(barrier, 0, count);
- result.value[0] = (u64)barrier;
- }
- return result;
-}
-
-BEAMFORMER_IMPORT void
-os_barrier_enter(OSBarrier barrier)
-{
- pthread_barrier_t *b = (pthread_barrier_t *)barrier.value[0];
- if (b) pthread_barrier_wait(b);
-}
+global BeamformerInput beamformer_input_main;
BEAMFORMER_IMPORT void
os_console_log(u8 *data, i64 length)
@@ -189,7 +66,7 @@ os_lookup_symbol(OSLibrary library, const char *symbol)
function void *
allocate_shared_memory(char *name, i64 requested_capacity, u64 *capacity)
{
- u64 rounded_capacity = round_up_to(requested_capacity, ARCH_X64? KB(4) : linux_system_info.page_size);
+ u64 rounded_capacity = round_up_to(requested_capacity, ARCH_X64? KB(4) : os_linux_context.system_info.page_size);
void *result = 0;
i32 fd = shm_open(name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (fd > 0 && ftruncate(fd, rounded_capacity) != -1) {
@@ -295,7 +172,7 @@ os_window_create(u8 *title, i64 title_length, i32 width, i32 height)
}
we->as.window.handle = GetPlatformWindowHandle();
- os_window_equip_common(os_linux_context.input, we->as.window.handle);
+ os_window_equip_common(&beamformer_input_main, we->as.window.handle);
raylib_window_resize = glfwSetWindowSizeCallback(we->as.window.handle, os_window_resize_callback);
/* NOTE: do this after initing so that the window starts out floating in tiling wm */
@@ -341,12 +218,12 @@ load_library(char *name, char *temp_name, u32 flags)
#if BEAMFORMER_DEBUG
function void
-debug_library_reload(void *beamformer, BeamformerInput *input)
+debug_library_reload(void *beamformer)
{
local_persist OSLibrary beamformer_library_handle = {OSInvalidHandleValue};
if ValidHandle(beamformer_library_handle) {
- beamformer_debug_hot_release(beamformer, input);
+ beamformer_debug_hot_release(beamformer, &beamformer_input_main);
dlclose((void *)beamformer_library_handle.value[0]);
beamformer_library_handle = (OSLibrary){OSInvalidHandleValue};
}
@@ -361,18 +238,19 @@ debug_library_reload(void *beamformer, BeamformerInput *input)
}
}
#else
-#define debug_library_reload(a, b) (void)(a), (void)(b)
+#define debug_library_reload(a) (void)(a)
#endif /* BEAMFORMER_DEBUG */
function void
-load_platform_libraries(BeamformerInput *input)
+load_platform_libraries(void)
{
#if BEAMFORMER_DEBUG
- debug_library_reload(0, input);
+ debug_library_reload(0);
os_linux_add_file_watch(str8(OS_DEBUG_LIB_NAME), (void *)BeamformerInputEventKind_ExecutableReload,
OSLinuxFileWatchKind_Platform);
#endif
+ BeamformerInput *input = &beamformer_input_main;
input->vulkan_library_handle = (OSLibrary){OSInvalidHandleValue};
#define X(name) \
if InvalidHandle(input->vulkan_library_handle) \
@@ -393,7 +271,7 @@ load_platform_libraries(BeamformerInput *input)
}
function void
-dispatch_file_watch_events(void *beamformer, BeamformerInput *input)
+dispatch_file_watch_events(void *beamformer)
{
local_persist alignas(16) u8 mem[KB(4)];
struct inotify_event *event;
@@ -417,13 +295,13 @@ dispatch_file_watch_events(void *beamformer, BeamformerInput *input)
if (fw->kind == OSLinuxFileWatchKind_Platform) {
assert((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload);
if ((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload)
- debug_library_reload(beamformer, input);
+ debug_library_reload(beamformer);
input_event.kind = (u64)fw->user_context;
} else {
input_event.kind = BeamformerInputEventKind_FileEvent;
input_event.file_watch_user_context = fw->user_context;
}
- os_push_input_event(input, input_event);
+ os_push_input_event(&beamformer_input_main, input_event);
}
fw->update_time = current_time;
break;
@@ -436,11 +314,9 @@ dispatch_file_watch_events(void *beamformer, BeamformerInput *input)
BASE_IMPORT void
entry_point(i32 argc, char *argv[])
{
- os_linux_context.arena = arena_create(.name = "Platform Arena");
os_linux_context.inotify_handle = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
- BeamformerInput *input = push_struct(os_linux_context.arena, BeamformerInput);
- os_linux_context.input = input;
+ BeamformerInput *input = &beamformer_input_main;
input->shared_memory = allocate_shared_memory(OS_SHARED_MEMORY_NAME, OS_SHARED_MEMORY_SIZE,
&input->shared_memory_size);
if (input->shared_memory) {
@@ -452,7 +328,7 @@ entry_point(i32 argc, char *argv[])
.kind = BeamformerInputEventKind_ExecutableReload,
});
- load_platform_libraries(input);
+ load_platform_libraries();
void *beamformer = beamformer_init(input);
@@ -465,7 +341,7 @@ entry_point(i32 argc, char *argv[])
poll(fds, countof(fds), 0);
if (fds[0].revents & POLLIN)
- dispatch_file_watch_events(beamformer, input);
+ dispatch_file_watch_events(beamformer);
beamformer_frame_step(beamformer, input);
diff --git a/main_w32.c b/main_w32.c
@@ -32,22 +32,10 @@
#include "beamformer.c"
#include "base_win32.c"
-typedef struct {
- u32 reserved1;
- u32 reserved2;
- u64 Reserved3[2];
- u32 reserved4;
- u32 reserved5;
-} w32_synchronization_barrier;
-
-W32(u64) CreateThread(iptr, u64, iptr, iptr, u32, u32 *);
-W32(b32) EnterSynchronizationBarrier(w32_synchronization_barrier *, u32);
W32(b32) FreeLibrary(u64);
W32(void *) GetModuleHandleA(const c8 *);
W32(void *) GetProcAddress(u64, const c8 *);
-W32(b32) InitializeSynchronizationBarrier(w32_synchronization_barrier *, i32, i32);
W32(void *) LoadLibraryA(const c8 *);
-W32(i32) SetThreadDescription(u64, u16 *);
#define OS_SHARED_MEMORY_SIZE GB(2)
@@ -62,135 +50,7 @@ W32(i32) SetThreadDescription(u64, u16 *);
#define OS_VULKAN_SONAME_LIST \
X("vulkan-1.dll") \
-enum {OSW32_FileWatchDirectoryBufferSize = KB(4)};
-
-typedef struct OSW32Entity OSW32Entity;
-typedef struct {
- void *handle;
- OSW32Entity *prev, *next;
-} OSW32Window;
-
-typedef enum {
- OSW32FileWatchKind_Platform,
- OSW32FileWatchKind_User,
-} OSW32FileWatchKind;
-
-typedef struct OSW32FileWatchDirectory OSW32FileWatchDirectory;
-typedef struct OSW32FileWatch OSW32FileWatch;
-struct OSW32FileWatch {
- OSW32FileWatchKind kind;
- u64 hash;
- u64 update_time;
- void *user_context;
-
- OSW32FileWatchDirectory *parent;
- OSW32FileWatch *prev, *next;
-};
-
-struct OSW32FileWatchDirectory {
- u64 hash;
- i64 handle;
- str8 name;
-
- OSW32FileWatch *first_child;
- OSW32FileWatch *last_child;
- OSW32FileWatchDirectory *prev, *next;
-
- w32_overlapped overlapped;
- w32_io_completion_event event;
-
- void *buffer;
-};
-
-typedef enum {
- OSW32EntityKind_Window,
- OSW32EntityKind_FileWatch,
- OSW32EntityKind_FileWatchDirectory,
-} OSW32EntityKind;
-
-struct OSW32Entity {
- OSW32EntityKind kind;
- union {
- OSW32FileWatch file_watch;
- OSW32FileWatchDirectory file_watch_directory;
- OSW32Window window;
- } as;
- OSW32Entity *next;
-};
-
-typedef struct {
- Arena *arena;
- i32 arena_lock;
- i64 error_handle;
- i64 io_completion_handle;
-
- BeamformerInput *input;
-
- struct {
- OSW32FileWatchDirectory *first;
- OSW32FileWatchDirectory *last;
- } file_watch_directories;
-
- struct {
- OSW32Entity *first;
- OSW32Entity *last;
- } windows;
-
- OSW32Entity *entity_freelist;
-} OSW32_Context;
-global OSW32_Context os_w32_context;
-
-function OSW32Entity *
-os_entity_allocate(OSW32EntityKind kind)
-{
- OSW32Entity *result = 0;
- DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
- {
- result = SLLPopFreelist(os_w32_context.entity_freelist);
- if (!result) result = push_struct_no_zero(os_w32_context.arena, OSW32Entity);
- }
-
- zero_struct(result);
- result->kind = kind;
- return result;
-}
-
-BEAMFORMER_IMPORT OSThread
-os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn)
-{
- OSThread result = {(u64)CreateThread(0, 0, (iptr)fn, (iptr)user_context, 0, 0)};
- if (result.value[0]) {
- Temp scratch;
- DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
- DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
- {
- SetThreadDescription(result.value[0], str16_from_str8(scratch.arena, str8_from_c_str((c8 *)name)).data);
- }
- } else {
- result.value[0] = OSInvalidHandleValue;
- }
- return result;
-}
-
-BEAMFORMER_IMPORT OSBarrier
-os_barrier_alloc(u32 count)
-{
- OSBarrier result = {0};
- DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
- {
- w32_synchronization_barrier *barrier = push_struct(os_w32_context.arena, w32_synchronization_barrier);
- InitializeSynchronizationBarrier(barrier, (i32)count, -1);
- result.value[0] = (u64)barrier;
- }
- return result;
-}
-
-BEAMFORMER_IMPORT void
-os_barrier_enter(OSBarrier barrier)
-{
- w32_synchronization_barrier *b = (w32_synchronization_barrier *)barrier.value[0];
- if (b) EnterSynchronizationBarrier(b, 0);
-}
+global BeamformerInput beamformer_input_main;
BEAMFORMER_IMPORT void
os_console_log(u8 *data, i64 length)
@@ -224,7 +84,7 @@ os_lookup_symbol(OSLibrary library, const char *symbol)
function void *
allocate_shared_memory(char *name, i64 requested_capacity, u64 *capacity)
{
- u64 rounded_capacity = round_up_to(requested_capacity, win32_system_info.page_size);
+ u64 rounded_capacity = round_up_to(requested_capacity, os_w32_context.system_info.page_size);
void *result = 0;
iptr h = CreateFileMappingA(-1, 0, PAGE_READWRITE, (rounded_capacity >> 32u),
(rounded_capacity & 0xFFFFFFFFul), name);
@@ -337,7 +197,7 @@ os_window_create(u8 *title, i64 title_length, i32 width, i32 height)
}
we->as.window.handle = GetPlatformWindowHandle();
- os_window_equip_common(os_w32_context.input, we->as.window.handle);
+ os_window_equip_common(&beamformer_input_main, we->as.window.handle);
raylib_window_resize = glfwSetWindowSizeCallback(we->as.window.handle, os_window_resize_callback);
/* NOTE: do this after initing so that the window starts out floating in tiling wm */
@@ -393,12 +253,12 @@ load_library(char *name, char *temp_name)
#if BEAMFORMER_DEBUG
function void
-debug_library_reload(void *beamformer, BeamformerInput *input)
+debug_library_reload(void *beamformer)
{
local_persist OSLibrary beamformer_library_handle = {OSInvalidHandleValue};
if ValidHandle(beamformer_library_handle) {
- beamformer_debug_hot_release(beamformer, input);
+ beamformer_debug_hot_release(beamformer, &beamformer_input_main);
FreeLibrary(beamformer_library_handle.value[0]);
beamformer_library_handle = (OSLibrary){OSInvalidHandleValue};
}
@@ -413,18 +273,19 @@ debug_library_reload(void *beamformer, BeamformerInput *input)
}
}
#else
-#define debug_library_reload(a, b) (void)(a), (void)(b)
+#define debug_library_reload(a) (void)(a)
#endif /* BEAMFORMER_DEBUG */
function void
-load_platform_libraries(BeamformerInput *input)
+load_platform_libraries(void)
{
#if BEAMFORMER_DEBUG
- debug_library_reload(0, input);
+ debug_library_reload(0);
os_w32_add_file_watch(str8(OS_DEBUG_LIB_NAME), (void *)BeamformerInputEventKind_ExecutableReload,
OSW32FileWatchKind_Platform);
#endif
+ BeamformerInput *input = &beamformer_input_main;
input->vulkan_library_handle = (OSLibrary){OSInvalidHandleValue};
#define X(name) \
if InvalidHandle(input->vulkan_library_handle) \
@@ -445,7 +306,7 @@ load_platform_libraries(BeamformerInput *input)
}
function void
-dispatch_file_watch(void *beamformer, BeamformerInput *input, u64 current_time, OSW32FileWatchDirectory *fw_dir, Arena *scratch)
+dispatch_file_watch(void *beamformer, u64 current_time, OSW32FileWatchDirectory *fw_dir, Arena *scratch)
{
i64 offset = 0;
w32_file_notify_info *fni = (w32_file_notify_info *)fw_dir->buffer;
@@ -468,13 +329,13 @@ dispatch_file_watch(void *beamformer, BeamformerInput *input, u64 current_time,
if (fw->kind == OSW32FileWatchKind_Platform) {
assert((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload);
if ((u64)fw->user_context == BeamformerInputEventKind_ExecutableReload)
- debug_library_reload(beamformer, input);
+ debug_library_reload(beamformer);
input_event.kind = (u64)fw->user_context;
} else {
input_event.kind = BeamformerInputEventKind_FileEvent;
input_event.file_watch_user_context = fw->user_context;
}
- os_push_input_event(input, input_event);
+ os_push_input_event(&beamformer_input_main, input_event);
}
fw->update_time = current_time;
break;
@@ -486,7 +347,7 @@ dispatch_file_watch(void *beamformer, BeamformerInput *input, u64 current_time,
}
function void
-clear_io_queue(void *beamformer, BeamformerInput *input, Arena *scratch)
+clear_io_queue(void *beamformer, Arena *scratch)
{
iptr handle = os_w32_context.io_completion_handle;
w32_overlapped *overlapped;
@@ -500,7 +361,7 @@ clear_io_queue(void *beamformer, BeamformerInput *input, Arena *scratch)
switch (event->tag) {
case W32IOEvent_FileWatch:{
OSW32FileWatchDirectory *dir = (OSW32FileWatchDirectory *)event->context;
- dispatch_file_watch(beamformer, input, current_time, dir, scratch);
+ dispatch_file_watch(beamformer, current_time, dir, scratch);
zero_struct(&dir->overlapped);
ReadDirectoryChangesW(dir->handle, dir->buffer, OSW32_FileWatchDirectoryBufferSize, 0,
FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &dir->overlapped, 0);
@@ -512,12 +373,9 @@ clear_io_queue(void *beamformer, BeamformerInput *input, Arena *scratch)
BASE_IMPORT void
entry_point(i32 argc, char *argv[])
{
- os_w32_context.arena = arena_create(.name = "Platform Arena");
- os_w32_context.error_handle = GetStdHandle(STD_ERROR_HANDLE);
os_w32_context.io_completion_handle = CreateIoCompletionPort(INVALID_FILE, 0, 0, 0);
- BeamformerInput *input = push_struct(os_w32_context.arena, BeamformerInput);
- os_w32_context.input = input;
+ BeamformerInput *input = &beamformer_input_main;
input->shared_memory = allocate_shared_memory(OS_SHARED_MEMORY_NAME, OS_SHARED_MEMORY_SIZE,
&input->shared_memory_size);
if (input->shared_memory) {
@@ -529,7 +387,7 @@ entry_point(i32 argc, char *argv[])
.kind = BeamformerInputEventKind_ExecutableReload,
});
- load_platform_libraries(input);
+ load_platform_libraries();
void *beamformer = beamformer_init(input);
@@ -540,7 +398,7 @@ entry_point(i32 argc, char *argv[])
DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
{
- clear_io_queue(beamformer, input, scratch.arena);
+ clear_io_queue(beamformer, scratch.arena);
}
beamformer_frame_step(beamformer, input);
diff --git a/util.c b/util.c
@@ -1092,3 +1092,25 @@ number_from_str8(str8 s)
}
return result;
}
+
+function b32
+take_lock(i32 *lock, i32 timeout_ms)
+{
+ b32 result = 0;
+ for (;;) {
+ i32 current = 0;
+ if (atomic_cas_u32(lock, ¤t, 1))
+ result = 1;
+ if (result || !timeout_ms || (!os_wait_on_address(lock, current, (u32)timeout_ms) && timeout_ms != -1))
+ break;
+ }
+ return result;
+}
+
+function void
+release_lock(i32 *lock)
+{
+ assert(atomic_load_u32(lock));
+ atomic_store_u32(lock, 0);
+ os_wake_all_waiters(lock);
+}
diff --git a/util_os.c b/util_os.c
@@ -1,43 +0,0 @@
-/* See LICENSE for license details. */
-
-// NOTE(rnp): functions which require platform layer support but
-// otherwise share implementation
-
-function b32
-take_lock(i32 *lock, i32 timeout_ms)
-{
- b32 result = 0;
- for (;;) {
- i32 current = 0;
- if (atomic_cas_u32(lock, ¤t, 1))
- result = 1;
- if (result || !timeout_ms || (!os_wait_on_address(lock, current, (u32)timeout_ms) && timeout_ms != -1))
- break;
- }
- return result;
-}
-
-function void
-release_lock(i32 *lock)
-{
- assert(atomic_load_u32(lock));
- atomic_store_u32(lock, 0);
- os_wake_all_waiters(lock);
-}
-
-#if BEAMFORMER_RENDERDOC_HOOKS
-function void
-load_renderdoc_functions(BeamformerInput *input, OSLibrary rdoc)
-{
- if ValidHandle(rdoc) {
- renderdoc_get_api_fn *get_api = os_lookup_symbol(rdoc, "RENDERDOC_GetAPI");
- if (get_api) {
- RenderDocAPI *api = 0;
- if (get_api(10600, (void **)&api)) {
- input->renderdoc_start_frame_capture = RENDERDOC_START_FRAME_CAPTURE(api);
- input->renderdoc_end_frame_capture = RENDERDOC_END_FRAME_CAPTURE(api);
- }
- }
- }
-}
-#endif
diff --git a/util_os_ui.c b/util_os_ui.c
@@ -227,3 +227,20 @@ os_build_frame_input(BeamformerInput *input)
input->mouse_x = new_mouse.x;
input->mouse_y = new_mouse.y;
}
+
+#if BEAMFORMER_RENDERDOC_HOOKS
+function void
+load_renderdoc_functions(BeamformerInput *input, OSLibrary rdoc)
+{
+ if ValidHandle(rdoc) {
+ renderdoc_get_api_fn *get_api = os_lookup_symbol(rdoc, "RENDERDOC_GetAPI");
+ if (get_api) {
+ RenderDocAPI *api = 0;
+ if (get_api(10600, (void **)&api)) {
+ input->renderdoc_start_frame_capture = RENDERDOC_START_FRAME_CAPTURE(api);
+ input->renderdoc_end_frame_capture = RENDERDOC_END_FRAME_CAPTURE(api);
+ }
+ }
+ }
+}
+#endif