ogl_beamforming

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

os_win32.c (9419B)


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