ogl_beamforming

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

os_win32.c (9504B)


      1 /* See LICENSE for license details. */
      2 
      3 #define OS_SHARED_MEMORY_NAME "Local\\ogl_beamformer_parameters"
      4 #define OS_EXPORT_PIPE_NAME   "\\\\.\\pipe\\beamformer_output_pipe"
      5 
      6 #define OS_PATH_SEPARATOR_CHAR '\\'
      7 #define OS_PATH_SEPARATOR      "\\"
      8 
      9 #include "util.h"
     10 
     11 #define STD_INPUT_HANDLE  -10
     12 #define STD_OUTPUT_HANDLE -11
     13 #define STD_ERROR_HANDLE  -12
     14 
     15 #define PAGE_READWRITE 0x04
     16 #define MEM_COMMIT     0x1000
     17 #define MEM_RESERVE    0x2000
     18 #define MEM_RELEASE    0x8000
     19 
     20 #define GENERIC_WRITE  0x40000000
     21 #define GENERIC_READ   0x80000000
     22 
     23 #define FILE_SHARE_READ            0x00000001
     24 #define FILE_MAP_ALL_ACCESS        0x000F001F
     25 #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
     26 #define FILE_FLAG_OVERLAPPED       0x40000000
     27 
     28 #define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
     29 
     30 #define FILE_ACTION_MODIFIED 0x00000003
     31 
     32 #define CREATE_ALWAYS  2
     33 #define OPEN_EXISTING  3
     34 
     35 #define THREAD_SET_LIMITED_INFORMATION 0x0400
     36 
     37 /* NOTE: this is packed because the w32 api designers are dumb and ordered the members
     38  * incorrectly. They worked around it be making the ft* members a struct {u32, u32} which
     39  * is aligned on a 4-byte boundary. Then in their documentation they explicitly tell you not
     40  * to cast to u64 because "it can cause alignment faults on 64-bit Windows" - go figure */
     41 typedef struct w32_file_info w32_file_info;
     42 pack_struct(struct w32_file_info {
     43 	u32 dwFileAttributes;
     44 	u64 ftCreationTime;
     45 	u64 ftLastAccessTime;
     46 	u64 ftLastWriteTime;
     47 	u32 dwVolumeSerialNumber;
     48 	u32 nFileSizeHigh;
     49 	u32 nFileSizeLow;
     50 	u32 nNumberOfLinks;
     51 	u32 nFileIndexHigh;
     52 	u32 nFileIndexLow;
     53 });
     54 
     55 typedef struct {
     56 	u32 next_entry_offset;
     57 	u32 action;
     58 	u32 filename_size;
     59 	u16 filename[];
     60 } w32_file_notify_info;
     61 
     62 typedef struct {
     63 	uptr internal, internal_high;
     64 	union {
     65 		struct {u32 off, off_high;};
     66 		iptr pointer;
     67 	};
     68 	iptr event_handle;
     69 } w32_overlapped;
     70 
     71 typedef struct {
     72 	iptr io_completion_handle;
     73 	u64  timer_start_time;
     74 	u64  timer_frequency;
     75 } w32_context;
     76 
     77 typedef enum {
     78 	W32_IO_FILE_WATCH,
     79 	W32_IO_PIPE,
     80 } W32_IO_Event;
     81 
     82 typedef struct {
     83 	u64  tag;
     84 	iptr context;
     85 } w32_io_completion_event;
     86 
     87 #define W32(r) __declspec(dllimport) r __stdcall
     88 W32(b32)    CloseHandle(iptr);
     89 W32(b32)    CopyFileA(c8 *, c8 *, b32);
     90 W32(iptr)   CreateFileA(c8 *, u32, u32, void *, u32, u32, void *);
     91 W32(iptr)   CreateFileMappingA(iptr, void *, u32, u32, u32, c8 *);
     92 W32(iptr)   CreateIoCompletionPort(iptr, iptr, uptr, u32);
     93 W32(iptr)   CreateThread(iptr, uz, iptr, iptr, u32, u32 *);
     94 W32(b32)    DeleteFileA(c8 *);
     95 W32(void)   ExitProcess(i32);
     96 W32(b32)    FreeLibrary(void *);
     97 W32(i32)    GetFileAttributesA(c8 *);
     98 W32(b32)    GetFileInformationByHandle(iptr, void *);
     99 W32(i32)    GetLastError(void);
    100 W32(void *) GetModuleHandleA(c8 *);
    101 W32(void *) GetProcAddress(void *, c8 *);
    102 W32(b32)    GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32);
    103 W32(iptr)   GetStdHandle(i32);
    104 W32(void)   GetSystemInfo(void *);
    105 W32(void *) LoadLibraryA(c8 *);
    106 W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64);
    107 W32(b32)    ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *);
    108 W32(b32)    ReadFile(iptr, u8 *, i32, i32 *, void *);
    109 W32(b32)    ReleaseSemaphore(iptr, i64, i64 *);
    110 W32(i32)    SetThreadDescription(iptr, u16 *);
    111 W32(b32)    WaitOnAddress(void *, void *, uz, u32);
    112 W32(i32)    WakeByAddressAll(void *);
    113 W32(b32)    WriteFile(iptr, u8 *, i32, i32 *, void *);
    114 W32(void *) VirtualAlloc(u8 *, iz, u32, u32);
    115 W32(b32)    VirtualFree(u8 *, iz, u32);
    116 
    117 #ifdef _DEBUG
    118 function void *
    119 os_get_module(char *name, Stream *e)
    120 {
    121 	void *result = GetModuleHandleA(name);
    122 	if (!result && e) {
    123 		stream_append_s8s(e, s8("os_get_module(\""), c_str_to_s8(name), s8("\"): "));
    124 		stream_append_i64(e, GetLastError());
    125 		stream_append_byte(e, '\n');
    126 	}
    127 	return result;
    128 }
    129 #endif
    130 
    131 function OS_WRITE_FILE_FN(os_write_file)
    132 {
    133 	i32 wlen = 0;
    134 	if (raw.len > 0 && raw.len <= U32_MAX) WriteFile(file, raw.data, raw.len, &wlen, 0);
    135 	return raw.len == wlen;
    136 }
    137 
    138 function no_return void
    139 os_exit(i32 code)
    140 {
    141 	ExitProcess(1);
    142 	unreachable();
    143 }
    144 
    145 function no_return void
    146 os_fatal(s8 msg)
    147 {
    148 	os_write_file(GetStdHandle(STD_ERROR_HANDLE), msg);
    149 	os_exit(1);
    150 	unreachable();
    151 }
    152 
    153 function OS_ALLOC_ARENA_FN(os_alloc_arena)
    154 {
    155 	Arena result = old;
    156 
    157 	struct {
    158 		u16  architecture;
    159 		u16  _pad1;
    160 		u32  page_size;
    161 		iz   minimum_application_address;
    162 		iz   maximum_application_address;
    163 		u64  active_processor_mask;
    164 		u32  number_of_processors;
    165 		u32  processor_type;
    166 		u32  allocation_granularity;
    167 		u16  processor_level;
    168 		u16  processor_revision;
    169 	} info;
    170 
    171 	GetSystemInfo(&info);
    172 
    173 	if (capacity % info.page_size != 0)
    174 		capacity += (info.page_size - capacity % info.page_size);
    175 
    176 	iz old_size = old.end - old.beg;
    177 	if (old_size < capacity) {
    178 		if (old.beg)
    179 			VirtualFree(old.beg, old_size, MEM_RELEASE);
    180 
    181 		result.beg = VirtualAlloc(0, capacity, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    182 		if (!result.beg)
    183 			os_fatal(s8("os_alloc_arena: couldn't allocate memory\n"));
    184 		result.end = result.beg + capacity;
    185 	}
    186 	return result;
    187 }
    188 
    189 function OS_CLOSE_FN(os_close)
    190 {
    191 	CloseHandle(file);
    192 }
    193 
    194 function OS_OPEN_FOR_WRITE_FN(os_open_for_write)
    195 {
    196 	iptr result = CreateFileA(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    197 	return result;
    198 }
    199 
    200 function OS_READ_WHOLE_FILE_FN(os_read_whole_file)
    201 {
    202 	s8 result = s8("");
    203 
    204 	w32_file_info fileinfo;
    205 	iptr h = CreateFileA(file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
    206 	if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) {
    207 		iz filesize  = (iz)fileinfo.nFileSizeHigh << 32;
    208 		filesize    |= (iz)fileinfo.nFileSizeLow;
    209 		result       = s8_alloc(arena, filesize);
    210 
    211 		ASSERT(filesize <= (iz)U32_MAX);
    212 
    213 		i32 rlen;
    214 		if (!ReadFile(h, result.data, result.len, &rlen, 0) || rlen != result.len)
    215 			result = s8("");
    216 	}
    217 	if (h >= 0) CloseHandle(h);
    218 
    219 	return result;
    220 }
    221 
    222 function OS_READ_FILE_FN(os_read_file)
    223 {
    224 	i32 total_read = 0;
    225 	ReadFile(file, buf, size, &total_read, 0);
    226 	return total_read;
    227 }
    228 
    229 function OS_WRITE_NEW_FILE_FN(os_write_new_file)
    230 {
    231 	enum { CHUNK_SIZE = GB(2) };
    232 
    233 	b32 result = 0;
    234 	iptr h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    235 	if (h >= 0) {
    236 		while (raw.len > 0) {
    237 			s8 chunk  = raw;
    238 			chunk.len = MIN(chunk.len, CHUNK_SIZE);
    239 			result    = os_write_file(h, chunk);
    240 			if (!result) break;
    241 			raw = s8_cut_head(raw, chunk.len);
    242 		}
    243 		CloseHandle(h);
    244 	}
    245 	return result;
    246 }
    247 
    248 function b32
    249 os_file_exists(char *path)
    250 {
    251 	b32 result = GetFileAttributesA(path) != -1;
    252 	return result;
    253 }
    254 
    255 function void *
    256 os_create_shared_memory_area(char *name, iz cap)
    257 {
    258 	void *result = 0;
    259 	iptr h = CreateFileMappingA(-1, 0, PAGE_READWRITE, 0, cap, name);
    260 	if (h != INVALID_FILE)
    261 		result = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, cap);
    262 	return result;
    263 }
    264 
    265 function b32
    266 os_copy_file(char *name, char *new)
    267 {
    268 	return CopyFileA(name, new, 0);
    269 }
    270 
    271 function void *
    272 os_load_library(char *name, char *temp_name, Stream *e)
    273 {
    274 	if (temp_name && os_copy_file(name, temp_name))
    275 		name = temp_name;
    276 
    277 	void *result = LoadLibraryA(name);
    278 	if (!result && e) {
    279 		stream_append_s8s(e, s8("os_load_library(\""), c_str_to_s8(name), s8("\"): "));
    280 		stream_append_i64(e, GetLastError());
    281 		stream_append_byte(e, '\n');
    282 	}
    283 
    284 	if (temp_name)
    285 		DeleteFileA(temp_name);
    286 
    287 	return result;
    288 }
    289 
    290 function void *
    291 os_lookup_dynamic_symbol(void *h, char *name, Stream *e)
    292 {
    293 	void *result = 0;
    294 	if (h) {
    295 		result = GetProcAddress(h, name);
    296 		if (!result && e) {
    297 			stream_append_s8s(e, s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name),
    298 			                  s8("\"): "));
    299 			stream_append_i64(e, GetLastError());
    300 			stream_append_byte(e, '\n');
    301 		}
    302 	}
    303 	return result;
    304 }
    305 
    306 function void
    307 os_unload_library(void *h)
    308 {
    309 	FreeLibrary(h);
    310 }
    311 
    312 function OS_ADD_FILE_WATCH_FN(os_add_file_watch)
    313 {
    314 	s8 directory  = path;
    315 	directory.len = s8_scan_backwards(path, '\\');
    316 	ASSERT(directory.len > 0);
    317 
    318 	u64 hash = s8_hash(directory);
    319 	FileWatchContext *fwctx = &os->file_watch_context;
    320 	FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash);
    321 	if (!dir) {
    322 		ASSERT(path.data[directory.len] == '\\');
    323 
    324 		dir = da_push(a, fwctx);
    325 		dir->hash   = hash;
    326 		dir->name   = push_s8_zero(a, directory);
    327 		dir->handle = CreateFileA((c8 *)dir->name.data, GENERIC_READ, FILE_SHARE_READ, 0,
    328 		                          OPEN_EXISTING,
    329 		                          FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 0);
    330 
    331 		w32_context *ctx = (w32_context *)os->context;
    332 		w32_io_completion_event *event = push_struct(a, typeof(*event));
    333 		event->tag     = W32_IO_FILE_WATCH;
    334 		event->context = (iptr)dir;
    335 		CreateIoCompletionPort(dir->handle, ctx->io_completion_handle, (uptr)event, 0);
    336 
    337 		dir->buffer = sub_arena(a, 4096 + sizeof(w32_overlapped), 64);
    338 		w32_overlapped *overlapped = (w32_overlapped *)(dir->buffer.beg + 4096);
    339 		zero_struct(overlapped);
    340 
    341 		ReadDirectoryChangesW(dir->handle, dir->buffer.beg, 4096, 0,
    342 		                      FILE_NOTIFY_CHANGE_LAST_WRITE, 0, overlapped, 0);
    343 	}
    344 
    345 	FileWatch *fw = da_push(a, dir);
    346 	fw->user_data = user_data;
    347 	fw->callback  = callback;
    348 	fw->hash      = s8_hash(s8_cut_head(path, dir->name.len + 1));
    349 }
    350 
    351 function iptr
    352 os_create_thread(Arena arena, iptr user_context, s8 name, os_thread_entry_point_fn *fn)
    353 {
    354 	iptr result = CreateThread(0, 0, (iptr)fn, user_context, 0, 0);
    355 	SetThreadDescription(result, s8_to_s16(&arena, name).data);
    356 	return result;
    357 }
    358 
    359 function OS_WAIT_ON_VALUE_FN(os_wait_on_value)
    360 {
    361 	return WaitOnAddress(value, &current, sizeof(*value), timeout_ms);
    362 }
    363 
    364 function OS_WAKE_WAITERS_FN(os_wake_waiters)
    365 {
    366 	if (sync) {
    367 		atomic_inc_u32(sync, 1);
    368 		WakeByAddressAll(sync);
    369 	}
    370 }