base_win32.c (7796B)
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 enum { 91 W32IOEvent_FileWatch, 92 } W32IOEvent; 93 94 typedef struct { 95 u64 tag; 96 iptr context; 97 } w32_io_completion_event; 98 99 typedef struct { 100 iptr *semaphores; 101 u32 reserved_count; 102 } w32_shared_memory_context; 103 104 #define W32(r) __declspec(dllimport) r __stdcall 105 W32(b32) CloseHandle(iptr); 106 W32(b32) CopyFileA(c8 *, c8 *, b32); 107 W32(iptr) CreateFileA(c8 *, u32, u32, void *, u32, u32, void *); 108 W32(iptr) CreateFileMappingA(iptr, void *, u32, u32, u32, c8 *); 109 W32(iptr) CreateIoCompletionPort(iptr, iptr, uptr, u32); 110 W32(iptr) CreateSemaphoreA(iptr, i32, i32, c8 *); 111 W32(b32) DeleteFileA(c8 *); 112 W32(void) ExitProcess(i32); 113 W32(i32) GetFileAttributesA(c8 *); 114 W32(b32) GetFileInformationByHandle(iptr, void *); 115 W32(i32) GetLastError(void); 116 W32(b32) GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32); 117 W32(iptr) GetStdHandle(i32); 118 W32(void) GetSystemInfo(w32_system_info *); 119 W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64); 120 W32(b32) QueryPerformanceCounter(u64 *); 121 W32(b32) QueryPerformanceFrequency(u64 *); 122 W32(b32) ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *); 123 W32(b32) ReadFile(iptr, u8 *, i32, i32 *, void *); 124 W32(b32) ReleaseSemaphore(iptr, i32, i32 *); 125 W32(u32) WaitForSingleObject(iptr, u32); 126 W32(b32) WaitOnAddress(void *, void *, u64, u32); 127 W32(i32) WakeByAddressAll(void *); 128 W32(b32) WriteFile(iptr, u8 *, i32, i32 *, void *); 129 W32(void *) VirtualAlloc(u8 *, i64, u32, u32); 130 W32(b32) VirtualFree(void *, u64, u32); 131 W32(b32) VirtualProtect(void *, u64, u32, u32 *); 132 133 global OSSystemInfo win32_system_info; 134 135 function b32 136 os_write_file(iptr file, void *data, i64 length) 137 { 138 i32 wlen = 0; 139 if (length > 0 && length <= (i64)U32_MAX) WriteFile(file, data, (i32)length, &wlen, 0); 140 return length == wlen; 141 } 142 143 BASE_EXPORT no_return void 144 os_exit(i32 code) 145 { 146 ExitProcess(code); 147 unreachable(); 148 } 149 150 function u64 151 os_timer_frequency(void) 152 { 153 u64 result; 154 QueryPerformanceFrequency(&result); 155 return result; 156 } 157 158 BASE_EXPORT u64 159 os_timer_count(void) 160 { 161 u64 result; 162 QueryPerformanceCounter(&result); 163 return result; 164 } 165 166 function void 167 os_system_info_init(void) 168 { 169 w32_system_info info = {0}; 170 GetSystemInfo(&info); 171 172 win32_system_info.timer_frequency = os_timer_frequency(); 173 win32_system_info.logical_processor_count = info.number_of_processors; 174 win32_system_info.page_size = info.page_size; 175 win32_system_info.path_separator_byte = '\\'; 176 } 177 178 BASE_EXPORT OSSystemInfo * 179 os_system_info(void) 180 { 181 #if BASE_PLATFORM_NO_MAIN 182 if unlikely(win32_system_info.path_separator_byte == 0) 183 os_system_info_init(); 184 #endif 185 return &win32_system_info; 186 } 187 188 BASE_EXPORT void * 189 os_memory_reserve(u64 size) 190 { 191 void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); 192 return result; 193 } 194 195 BASE_EXPORT void 196 os_memory_release(void *base, u64 size) 197 { 198 // NOTE(rnp): size must be 0 on w32, no partial releasing 199 VirtualFree(base, 0, MEM_RELEASE); 200 } 201 202 BASE_EXPORT b32 203 os_memory_commit(void *base, u64 size) 204 { 205 b32 result = VirtualAlloc(base, size, MEM_COMMIT, PAGE_READWRITE) != 0; 206 return result; 207 } 208 209 BASE_EXPORT void 210 os_memory_uncommit(void *base, u64 size) 211 { 212 VirtualFree(base, size, MEM_DECOMMIT); 213 } 214 215 BASE_EXPORT void 216 os_memory_seal(void *base, u64 size) 217 { 218 u32 w32_dummy; 219 VirtualProtect(base, size, PAGE_READONLY, &w32_dummy); 220 } 221 222 BASE_EXPORT OSW32Semaphore 223 os_w32_create_semaphore(const char *name, i32 initial_count, i32 maximum_count) 224 { 225 OSW32Semaphore result = {(u64)CreateSemaphoreA(0, initial_count, maximum_count, (c8 *)name)}; 226 return result; 227 } 228 229 BASE_EXPORT u32 230 os_w32_semaphore_wait(OSW32Semaphore handle, u32 timeout_ms) 231 { 232 b32 result = !WaitForSingleObject(handle.value[0], timeout_ms); 233 return result; 234 } 235 236 BASE_EXPORT void 237 os_w32_semaphore_release(OSW32Semaphore handle, i32 count) 238 { 239 ReleaseSemaphore(handle.value[0], count, 0); 240 } 241 242 BASE_EXPORT str8 243 os_read_entire_file(Arena *arena, const char *file) 244 { 245 str8 result = {0}; 246 w32_file_info fileinfo; 247 iptr h = CreateFileA((c8 *)file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); 248 if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) { 249 i64 filesize = (i64)fileinfo.nFileSizeHigh << 32; 250 filesize |= (i64)fileinfo.nFileSizeLow; 251 result.data = push_array(arena, u8, filesize); 252 result.length = filesize; 253 i32 rlen; 254 if (!ReadFile(h, result.data, (i32)filesize, &rlen, 0) || rlen != filesize) { 255 arena_pop(arena, filesize); 256 zero_struct(&result); 257 } 258 } 259 if (h >= 0) CloseHandle(h); 260 261 return result; 262 } 263 264 function b32 265 os_write_new_file(char *fname, str8 raw) 266 { 267 b32 result = 0; 268 iptr h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); 269 if (h >= 0) { 270 while (raw.length > 0) { 271 i64 length = Min(raw.length, (i64)GB(2)); 272 result = os_write_file(h, raw.data, length); 273 if (!result) break; 274 raw = str8_cut_head(raw, length); 275 } 276 CloseHandle(h); 277 } 278 return result; 279 } 280 281 function b32 282 os_file_exists(char *path) 283 { 284 b32 result = GetFileAttributesA(path) != -1; 285 return result; 286 } 287 288 function b32 289 os_copy_file(char *name, char *new) 290 { 291 return CopyFileA(name, new, 0); 292 } 293 294 BASE_EXPORT b32 295 os_wait_on_address(i32 *value, i32 current, u32 timeout_ms) 296 { 297 return WaitOnAddress(value, ¤t, sizeof(*value), timeout_ms); 298 } 299 300 BASE_EXPORT void 301 os_wake_all_waiters(i32 *sync) 302 { 303 if (sync) { 304 atomic_store_u32(sync, 0); 305 WakeByAddressAll(sync); 306 } 307 } 308 309 #if !BASE_PLATFORM_NO_MAIN 310 BASE_IMPORT void entry_point(i32 argc, char *argv[]); 311 312 extern i32 313 main(i32 argc, char *argv[]) 314 { 315 os_system_info_init(); 316 317 entry_point(argc, argv); 318 319 return 0; 320 } 321 #endif