os_win32.c (6452B)
1 /* See LICENSE for license details. */ 2 3 #define OS_SHARED_MEMORY_NAME "Local\\ogl_beamformer_parameters" 4 5 #define OS_PATH_SEPARATOR_CHAR '\\' 6 #define OS_PATH_SEPARATOR "\\" 7 8 #include "util.h" 9 10 #define STD_INPUT_HANDLE -10 11 #define STD_OUTPUT_HANDLE -11 12 #define STD_ERROR_HANDLE -12 13 14 #define PAGE_READWRITE 0x04 15 #define MEM_COMMIT 0x1000 16 #define MEM_RESERVE 0x2000 17 18 #define GENERIC_WRITE 0x40000000 19 #define GENERIC_READ 0x80000000 20 21 #define FILE_SHARE_READ 0x00000001 22 #define FILE_MAP_ALL_ACCESS 0x000F001F 23 #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000 24 #define FILE_FLAG_OVERLAPPED 0x40000000 25 26 #define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 27 28 #define FILE_ACTION_MODIFIED 0x00000003 29 30 #define CREATE_ALWAYS 2 31 #define OPEN_EXISTING 3 32 33 #define THREAD_SET_LIMITED_INFORMATION 0x0400 34 35 /* NOTE: this is packed because the w32 api designers are dumb and ordered the members 36 * incorrectly. They worked around it be making the ft* members a struct {u32, u32} which 37 * is aligned on a 4-byte boundary. Then in their documentation they explicitly tell you not 38 * to cast to u64 because "it can cause alignment faults on 64-bit Windows" - go figure */ 39 typedef struct w32_file_info w32_file_info; 40 pack_struct(struct w32_file_info { 41 u32 dwFileAttributes; 42 u64 ftCreationTime; 43 u64 ftLastAccessTime; 44 u64 ftLastWriteTime; 45 u32 dwVolumeSerialNumber; 46 u32 nFileSizeHigh; 47 u32 nFileSizeLow; 48 u32 nNumberOfLinks; 49 u32 nFileIndexHigh; 50 u32 nFileIndexLow; 51 }); 52 53 typedef struct { 54 u32 next_entry_offset; 55 u32 action; 56 u32 filename_size; 57 u16 filename[]; 58 } w32_file_notify_info; 59 60 typedef struct { 61 u16 architecture; 62 u16 _pad1; 63 u32 page_size; 64 iz minimum_application_address; 65 iz maximum_application_address; 66 u64 active_processor_mask; 67 u32 number_of_processors; 68 u32 processor_type; 69 u32 allocation_granularity; 70 u16 processor_level; 71 u16 processor_revision; 72 } w32_system_info; 73 74 typedef struct { 75 uptr internal, internal_high; 76 union { 77 struct {u32 off, off_high;}; 78 iptr pointer; 79 }; 80 iptr event_handle; 81 } w32_overlapped; 82 83 typedef enum { 84 W32IOEvent_FileWatch, 85 } W32IOEvent; 86 87 typedef struct { 88 u64 tag; 89 iptr context; 90 } w32_io_completion_event; 91 92 typedef struct { 93 iptr *semaphores; 94 u32 reserved_count; 95 } w32_shared_memory_context; 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) CreateSemaphoreA(iptr, i32, i32, c8 *); 104 W32(b32) DeleteFileA(c8 *); 105 W32(void) ExitProcess(i32); 106 W32(i32) GetFileAttributesA(c8 *); 107 W32(b32) GetFileInformationByHandle(iptr, void *); 108 W32(i32) GetLastError(void); 109 W32(b32) GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32); 110 W32(iptr) GetStdHandle(i32); 111 W32(void) GetSystemInfo(w32_system_info *); 112 W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64); 113 W32(b32) QueryPerformanceCounter(u64 *); 114 W32(b32) QueryPerformanceFrequency(u64 *); 115 W32(b32) ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *); 116 W32(b32) ReadFile(iptr, u8 *, i32, i32 *, void *); 117 W32(b32) ReleaseSemaphore(iptr, i32, i32 *); 118 W32(u32) WaitForSingleObject(iptr, u32); 119 W32(b32) WaitOnAddress(void *, void *, uz, u32); 120 W32(i32) WakeByAddressAll(void *); 121 W32(b32) WriteFile(iptr, u8 *, i32, i32 *, void *); 122 W32(void *) VirtualAlloc(u8 *, iz, u32, u32); 123 124 function b32 125 os_write_file(iptr file, void *data, i64 length) 126 { 127 i32 wlen = 0; 128 if (length > 0 && length <= (i64)U32_MAX) WriteFile(file, data, (i32)length, &wlen, 0); 129 return length == wlen; 130 } 131 132 function no_return void 133 os_exit(i32 code) 134 { 135 ExitProcess(1); 136 unreachable(); 137 } 138 139 function u64 140 os_get_timer_frequency(void) 141 { 142 u64 result; 143 QueryPerformanceFrequency(&result); 144 return result; 145 } 146 147 function u64 148 os_get_timer_counter(void) 149 { 150 u64 result; 151 QueryPerformanceCounter(&result); 152 return result; 153 } 154 155 function u32 156 os_get_page_size(void) 157 { 158 w32_system_info info = {0}; 159 GetSystemInfo(&info); 160 u32 result = info.page_size; 161 return result; 162 } 163 164 function OS_ALLOC_ARENA_FN(os_alloc_arena) 165 { 166 Arena result = {0}; 167 capacity = round_up_to(capacity, os_get_page_size()); 168 result.beg = VirtualAlloc(0, capacity, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 169 if (result.beg) { 170 result.end = result.beg + capacity; 171 asan_poison_region(result.beg, result.end - result.beg); 172 } 173 return result; 174 } 175 176 BEAMFORMER_IMPORT OS_READ_ENTIRE_FILE_FN(os_read_entire_file) 177 { 178 i64 result = 0; 179 w32_file_info fileinfo; 180 iptr h = CreateFileA((c8 *)file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); 181 if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) { 182 iz filesize = (iz)fileinfo.nFileSizeHigh << 32; 183 filesize |= (iz)fileinfo.nFileSizeLow; 184 if (buffer_capacity >= filesize) { 185 result = filesize; 186 i32 rlen; 187 if (!ReadFile(h, buffer, (i32)filesize, &rlen, 0) || rlen != filesize) 188 result = 0; 189 } 190 } 191 if (h >= 0) CloseHandle(h); 192 193 return result; 194 } 195 196 function OS_WRITE_NEW_FILE_FN(os_write_new_file) 197 { 198 b32 result = 0; 199 iptr h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); 200 if (h >= 0) { 201 while (raw.len > 0) { 202 i64 length = MIN(raw.len, (iz)GB(2)); 203 result = os_write_file(h, raw.data, length); 204 if (!result) break; 205 raw = s8_cut_head(raw, length); 206 } 207 CloseHandle(h); 208 } 209 return result; 210 } 211 212 function b32 213 os_file_exists(char *path) 214 { 215 b32 result = GetFileAttributesA(path) != -1; 216 return result; 217 } 218 219 function b32 220 os_copy_file(char *name, char *new) 221 { 222 return CopyFileA(name, new, 0); 223 } 224 225 BEAMFORMER_IMPORT OS_WAIT_ON_ADDRESS_FN(os_wait_on_address) 226 { 227 return WaitOnAddress(value, ¤t, sizeof(*value), timeout_ms); 228 } 229 230 BEAMFORMER_IMPORT OS_WAKE_ALL_WAITERS_FN(os_wake_all_waiters) 231 { 232 if (sync) { 233 atomic_store_u32(sync, 0); 234 WakeByAddressAll(sync); 235 } 236 } 237 238 BEAMFORMER_IMPORT OSW32Semaphore 239 os_w32_create_semaphore(const char *name, i32 initial_count, i32 maximum_count) 240 { 241 OSW32Semaphore result = {(u64)CreateSemaphoreA(0, initial_count, maximum_count, (c8 *)name)}; 242 return result; 243 } 244 245 BEAMFORMER_IMPORT u32 246 os_w32_semaphore_wait(OSW32Semaphore handle, u32 timeout_ms) 247 { 248 b32 result = !WaitForSingleObject(handle.value[0], timeout_ms); 249 return result; 250 } 251 252 BEAMFORMER_IMPORT void 253 os_w32_semaphore_release(OSW32Semaphore handle, i32 count) 254 { 255 ReleaseSemaphore(handle.value[0], count, 0); 256 }