ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

base_win32.c (11425B)


      1 /* See LICENSE for license details. */
      2 
      3 /* NOTE(rnp): provides the platform layer for everything in this repo. */
      4 
      5 #define OS_SHARED_MEMORY_NAME "Local\\ogl_beamformer_parameters"
      6 
      7 #define OS_PATH_SEPARATOR_CHAR '\\'
      8 #define OS_PATH_SEPARATOR      "\\"
      9 
     10 #include "base_platform.h"
     11 
     12 #include "util.h"
     13 
     14 #define STD_INPUT_HANDLE  -10
     15 #define STD_OUTPUT_HANDLE -11
     16 #define STD_ERROR_HANDLE  -12
     17 
     18 #define PAGE_READONLY  0x02
     19 #define PAGE_READWRITE 0x04
     20 #define MEM_COMMIT     0x1000
     21 #define MEM_RESERVE    0x2000
     22 #define MEM_DECOMMIT   0x4000
     23 #define MEM_RELEASE    0x8000
     24 
     25 #define GENERIC_WRITE  0x40000000
     26 #define GENERIC_READ   0x80000000
     27 
     28 #define FILE_SHARE_READ            0x00000001
     29 #define FILE_MAP_ALL_ACCESS        0x000F001F
     30 #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
     31 #define FILE_FLAG_OVERLAPPED       0x40000000
     32 
     33 #define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
     34 
     35 #define FILE_ACTION_MODIFIED 0x00000003
     36 
     37 #define CREATE_ALWAYS  2
     38 #define OPEN_EXISTING  3
     39 
     40 #define THREAD_SET_LIMITED_INFORMATION 0x0400
     41 
     42 /* NOTE: this is packed because the w32 api designers are dumb and ordered the members
     43  * incorrectly. They worked around it be making the ft* members a struct {u32, u32} which
     44  * is aligned on a 4-byte boundary. Then in their documentation they explicitly tell you not
     45  * to cast to u64 because "it can cause alignment faults on 64-bit Windows" - go figure */
     46 typedef struct w32_file_info w32_file_info;
     47 pack_struct(struct w32_file_info {
     48 	u32 dwFileAttributes;
     49 	u64 ftCreationTime;
     50 	u64 ftLastAccessTime;
     51 	u64 ftLastWriteTime;
     52 	u32 dwVolumeSerialNumber;
     53 	u32 nFileSizeHigh;
     54 	u32 nFileSizeLow;
     55 	u32 nNumberOfLinks;
     56 	u32 nFileIndexHigh;
     57 	u32 nFileIndexLow;
     58 });
     59 
     60 typedef struct {
     61 	u32 next_entry_offset;
     62 	u32 action;
     63 	u32 filename_size;
     64 	u16 filename[];
     65 } w32_file_notify_info;
     66 
     67 typedef struct {
     68 	u16  architecture;
     69 	u16  _pad1;
     70 	u32  page_size;
     71 	i64  minimum_application_address;
     72 	i64  maximum_application_address;
     73 	u64  active_processor_mask;
     74 	u32  number_of_processors;
     75 	u32  processor_type;
     76 	u32  allocation_granularity;
     77 	u16  processor_level;
     78 	u16  processor_revision;
     79 } w32_system_info;
     80 
     81 typedef struct {
     82 	uptr internal, internal_high;
     83 	union {
     84 		struct {u32 off, off_high;};
     85 		iptr pointer;
     86 	};
     87 	iptr event_handle;
     88 } w32_overlapped;
     89 
     90 typedef struct {
     91 	u32 reserved1;
     92 	u32 reserved2;
     93 	u64 Reserved3[2];
     94 	u32 reserved4;
     95 	u32 reserved5;
     96 } w32_synchronization_barrier;
     97 
     98 typedef enum {
     99 	W32IOEvent_FileWatch,
    100 } W32IOEvent;
    101 
    102 typedef struct {
    103 	u64  tag;
    104 	iptr context;
    105 } w32_io_completion_event;
    106 
    107 #define W32(r) __declspec(dllimport) r __stdcall
    108 W32(b32)    CloseHandle(iptr);
    109 W32(b32)    CopyFileA(c8 *, c8 *, b32);
    110 W32(iptr)   CreateFileA(c8 *, u32, u32, void *, u32, u32, void *);
    111 W32(iptr)   CreateFileMappingA(iptr, void *, u32, u32, u32, c8 *);
    112 W32(iptr)   CreateIoCompletionPort(iptr, iptr, uptr, u32);
    113 W32(iptr)   CreateSemaphoreA(iptr, i32, i32, c8 *);
    114 W32(u64)    CreateThread(iptr, u64, iptr, iptr, u32, u32 *);
    115 W32(b32)    DeleteFileA(c8 *);
    116 W32(b32)    EnterSynchronizationBarrier(w32_synchronization_barrier *, u32);
    117 W32(void)   ExitProcess(i32);
    118 W32(i32)    GetFileAttributesA(c8 *);
    119 W32(b32)    GetFileInformationByHandle(iptr, void *);
    120 W32(i32)    GetLastError(void);
    121 W32(b32)    GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32);
    122 W32(iptr)   GetStdHandle(i32);
    123 W32(void)   GetSystemInfo(w32_system_info *);
    124 W32(b32)    InitializeSynchronizationBarrier(w32_synchronization_barrier *, i32, i32);
    125 W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64);
    126 W32(b32)    QueryPerformanceCounter(u64 *);
    127 W32(b32)    QueryPerformanceFrequency(u64 *);
    128 W32(b32)    ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *);
    129 W32(b32)    ReadFile(iptr, u8 *, i32, i32 *, void *);
    130 W32(b32)    ReleaseSemaphore(iptr, i32, i32 *);
    131 W32(i32)    SetThreadDescription(u64, u16 *);
    132 W32(u32)    WaitForSingleObject(iptr, u32);
    133 W32(b32)    WaitOnAddress(void *, void *, u64, u32);
    134 W32(i32)    WakeByAddressAll(void *);
    135 W32(b32)    WriteFile(iptr, u8 *, i32, i32 *, void *);
    136 W32(void *) VirtualAlloc(u8 *, i64, u32, u32);
    137 W32(b32)    VirtualFree(void *, u64, u32);
    138 W32(b32)    VirtualProtect(void *, u64, u32, u32 *);
    139 
    140 enum {OSW32_FileWatchDirectoryBufferSize = KB(4)};
    141 
    142 typedef struct OSW32Entity OSW32Entity;
    143 typedef struct {
    144 	void *handle;
    145 	OSW32Entity *prev, *next;
    146 } OSW32Window;
    147 
    148 typedef enum {
    149 	OSW32FileWatchKind_Platform,
    150 	OSW32FileWatchKind_User,
    151 } OSW32FileWatchKind;
    152 
    153 typedef struct OSW32FileWatchDirectory OSW32FileWatchDirectory;
    154 typedef struct OSW32FileWatch OSW32FileWatch;
    155 struct OSW32FileWatch {
    156 	OSW32FileWatchKind  kind;
    157 	u64                 hash;
    158 	u64                 update_time;
    159 	void               *user_context;
    160 
    161 	OSW32FileWatchDirectory *parent;
    162 	OSW32FileWatch *prev, *next;
    163 };
    164 
    165 struct OSW32FileWatchDirectory {
    166 	u64  hash;
    167 	i64  handle;
    168 	str8 name;
    169 
    170 	OSW32FileWatch *first_child;
    171 	OSW32FileWatch *last_child;
    172 	OSW32FileWatchDirectory *prev, *next;
    173 
    174 	w32_overlapped          overlapped;
    175   w32_io_completion_event event;
    176 
    177 	void *buffer;
    178 };
    179 
    180 typedef enum {
    181 	OSW32EntityKind_Window,
    182 	OSW32EntityKind_FileWatch,
    183 	OSW32EntityKind_FileWatchDirectory,
    184 } OSW32EntityKind;
    185 
    186 struct OSW32Entity {
    187 	OSW32EntityKind kind;
    188 	union {
    189 		OSW32FileWatch          file_watch;
    190 		OSW32FileWatchDirectory file_watch_directory;
    191 		OSW32Window             window;
    192 	} as;
    193 	OSW32Entity *next;
    194 };
    195 
    196 typedef struct {
    197 	OSSystemInfo  system_info;
    198 
    199 	Arena        *arena;
    200 	i32           arena_lock;
    201 	i64           error_handle;
    202 	i64           io_completion_handle;
    203 
    204 	struct {
    205 		OSW32FileWatchDirectory *first;
    206 		OSW32FileWatchDirectory *last;
    207 	} file_watch_directories;
    208 
    209 	struct {
    210 		OSW32Entity *first;
    211 		OSW32Entity *last;
    212 	} windows;
    213 
    214 	OSW32Entity *entity_freelist;
    215 } OSW32_Context;
    216 global OSW32_Context os_w32_context;
    217 
    218 function b32
    219 os_write_file(iptr file, void *data, i64 length)
    220 {
    221 	i32 wlen = 0;
    222 	if (length > 0 && length <= (i64)U32_MAX) WriteFile(file, data, (i32)length, &wlen, 0);
    223 	return length == wlen;
    224 }
    225 
    226 BASE_EXPORT no_return void
    227 os_exit(i32 code)
    228 {
    229 	ExitProcess(code);
    230 	unreachable();
    231 }
    232 
    233 function u64
    234 os_timer_frequency(void)
    235 {
    236 	u64 result;
    237 	QueryPerformanceFrequency(&result);
    238 	return result;
    239 }
    240 
    241 BASE_EXPORT u64
    242 os_timer_count(void)
    243 {
    244 	u64 result;
    245 	QueryPerformanceCounter(&result);
    246 	return result;
    247 }
    248 
    249 function void
    250 os_system_info_init(void)
    251 {
    252 	w32_system_info info = {0};
    253 	GetSystemInfo(&info);
    254 
    255 	os_w32_context.system_info.timer_frequency         = os_timer_frequency();
    256 	os_w32_context.system_info.logical_processor_count = info.number_of_processors;
    257 	os_w32_context.system_info.page_size               = info.page_size;
    258 	os_w32_context.system_info.path_separator_byte     = '\\';
    259 }
    260 
    261 BASE_EXPORT OSSystemInfo *
    262 os_system_info(void)
    263 {
    264 	#if BASE_PLATFORM_NO_MAIN
    265 	if unlikely(os_w32_context.system_info.path_separator_byte == 0)
    266 		os_system_info_init();
    267 	#endif
    268 	return &os_w32_context.system_info;
    269 }
    270 
    271 BASE_EXPORT void *
    272 os_memory_reserve(u64 size)
    273 {
    274 	void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
    275 	return result;
    276 }
    277 
    278 BASE_EXPORT void
    279 os_memory_release(void *base, u64 size)
    280 {
    281 	// NOTE(rnp): size must be 0 on w32, no partial releasing
    282 	VirtualFree(base, 0, MEM_RELEASE);
    283 }
    284 
    285 BASE_EXPORT b32
    286 os_memory_commit(void *base, u64 size)
    287 {
    288 	b32 result = VirtualAlloc(base, size, MEM_COMMIT, PAGE_READWRITE) != 0;
    289 	return result;
    290 }
    291 
    292 BASE_EXPORT void
    293 os_memory_uncommit(void *base, u64 size)
    294 {
    295 	VirtualFree(base, size, MEM_DECOMMIT);
    296 }
    297 
    298 BASE_EXPORT void
    299 os_memory_seal(void *base, u64 size)
    300 {
    301 	u32 w32_dummy;
    302 	VirtualProtect(base, size, PAGE_READONLY, &w32_dummy);
    303 }
    304 
    305 BASE_EXPORT OSW32Semaphore
    306 os_w32_create_semaphore(const char *name, i32 initial_count, i32 maximum_count)
    307 {
    308 	OSW32Semaphore result = {(u64)CreateSemaphoreA(0, initial_count, maximum_count, (c8 *)name)};
    309 	return result;
    310 }
    311 
    312 BASE_EXPORT u32
    313 os_w32_semaphore_wait(OSW32Semaphore handle, u32 timeout_ms)
    314 {
    315 	b32 result = !WaitForSingleObject(handle.value[0], timeout_ms);
    316 	return result;
    317 }
    318 
    319 BASE_EXPORT void
    320 os_w32_semaphore_release(OSW32Semaphore handle, i32 count)
    321 {
    322 	ReleaseSemaphore(handle.value[0], count, 0);
    323 }
    324 
    325 BASE_EXPORT str8
    326 os_read_entire_file(Arena *arena, const char *file)
    327 {
    328 	str8 result = {0};
    329 	w32_file_info fileinfo;
    330 	iptr h = CreateFileA((c8 *)file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
    331 	if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) {
    332 		i64 filesize  = (i64)fileinfo.nFileSizeHigh << 32;
    333 		filesize     |= (i64)fileinfo.nFileSizeLow;
    334 		result.data   = push_array(arena, u8, filesize);
    335 		result.length = filesize;
    336 		i32 rlen;
    337 		if (!ReadFile(h, result.data, (i32)filesize, &rlen, 0) || rlen != filesize) {
    338 			arena_pop(arena, filesize);
    339 			zero_struct(&result);
    340 		}
    341 	}
    342 	if (h >= 0) CloseHandle(h);
    343 
    344 	return result;
    345 }
    346 
    347 function b32
    348 os_write_new_file(char *fname, str8 raw)
    349 {
    350 	b32 result = 0;
    351 	iptr h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    352 	if (h >= 0) {
    353 		while (raw.length > 0) {
    354 			i64 length = Min(raw.length, (i64)GB(2));
    355 			result     = os_write_file(h, raw.data, length);
    356 			if (!result) break;
    357 			raw = str8_cut_head(raw, length);
    358 		}
    359 		CloseHandle(h);
    360 	}
    361 	return result;
    362 }
    363 
    364 function b32
    365 os_file_exists(char *path)
    366 {
    367 	b32 result = GetFileAttributesA(path) != -1;
    368 	return result;
    369 }
    370 
    371 function b32
    372 os_copy_file(char *name, char *new)
    373 {
    374 	return CopyFileA(name, new, 0);
    375 }
    376 
    377 function OSW32Entity *
    378 os_entity_allocate(OSW32EntityKind kind)
    379 {
    380 	OSW32Entity *result = 0;
    381 	DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
    382 	{
    383 		result = SLLPopFreelist(os_w32_context.entity_freelist);
    384 		if (!result) result = push_struct_no_zero(os_w32_context.arena, OSW32Entity);
    385 	}
    386 
    387 	zero_struct(result);
    388 	result->kind = kind;
    389 	return result;
    390 }
    391 
    392 BASE_EXPORT OSThread
    393 os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn)
    394 {
    395 	OSThread result = {(u64)CreateThread(0, 0, (iptr)fn, (iptr)user_context, 0, 0)};
    396 	if (result.value[0]) {
    397 		Temp scratch;
    398 		DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
    399 		DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
    400 		{
    401 			SetThreadDescription(result.value[0], str16_from_str8(scratch.arena, str8_from_c_str((c8 *)name)).data);
    402 		}
    403 	} else {
    404 		result.value[0] = OSInvalidHandleValue;
    405 	}
    406 	return result;
    407 }
    408 
    409 BASE_EXPORT OSBarrier
    410 os_barrier_alloc(u32 count)
    411 {
    412 	OSBarrier result = {0};
    413 	DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
    414 	{
    415 		w32_synchronization_barrier *barrier = push_struct(os_w32_context.arena, w32_synchronization_barrier);
    416 		InitializeSynchronizationBarrier(barrier, (i32)count, -1);
    417 		result.value[0] = (u64)barrier;
    418 	}
    419 	return result;
    420 }
    421 
    422 BASE_EXPORT void
    423 os_barrier_enter(OSBarrier barrier)
    424 {
    425 	w32_synchronization_barrier *b = (w32_synchronization_barrier *)barrier.value[0];
    426 	if (b) EnterSynchronizationBarrier(b, 0);
    427 }
    428 
    429 BASE_EXPORT b32
    430 os_wait_on_address(i32 *value, i32 current, u32 timeout_ms)
    431 {
    432 	return WaitOnAddress(value, &current, sizeof(*value), timeout_ms);
    433 }
    434 
    435 BASE_EXPORT void
    436 os_wake_all_waiters(i32 *sync)
    437 {
    438 	if (sync) {
    439 		atomic_store_u32(sync, 0);
    440 		WakeByAddressAll(sync);
    441 	}
    442 }
    443 
    444 #if !BASE_PLATFORM_NO_MAIN
    445 BASE_IMPORT void entry_point(i32 argc, char *argv[]);
    446 
    447 extern i32
    448 main(i32 argc, char *argv[])
    449 {
    450 	os_system_info_init();
    451 	os_w32_context.arena        = arena_create(.name = "Platform Arena");
    452 	os_w32_context.error_handle = GetStdHandle(STD_ERROR_HANDLE);
    453 
    454 	entry_point(argc, argv);
    455 
    456 	return 0;
    457 }
    458 #endif