blob: dc4ac1091f29ff74a6c61538339e127584e94ac0 [file] [log] [blame]
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001/*
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07002 *
Jon Ashburn23d36b12016-02-02 17:47:28 -07003 * Copyright (c) 2015-2016 The Khronos Group Inc.
4 * Copyright (c) 2015-2016 Valve Corporation
5 * Copyright (c) 2015-2016 LunarG, Inc.
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07006 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06007 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070010 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011 * http://www.apache.org/licenses/LICENSE-2.0
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070012 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060013 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jon Ashburn23d36b12016-02-02 17:47:28 -070018 *
19 * Author: Ian Elliot <ian@lunarg.com>
20 * Author: Jon Ashburn <jon@lunarg.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021 *
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070022 */
Jon Ashburn3f8c3002015-10-15 13:47:58 -060023#pragma once
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070024
Mark Lobodzinski450e4632015-11-24 12:04:15 -070025#if defined(_WIN32)
26// WinSock2.h must be included *BEFORE* windows.h
Mark Lobodzinski450e4632015-11-24 12:04:15 -070027#include <WinSock2.h>
28#endif // _WIN32
29
David Pinedo9316d3b2015-11-06 12:54:48 -070030#include "vulkan/vk_platform.h"
31#include "vulkan/vk_sdk_platform.h"
Cody Northrop33fa0412015-07-08 16:48:37 -060032
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070033#if defined(__linux__)
34/* Linux-specific common code: */
35
36// Headers:
37//#define _GNU_SOURCE 1
38// TBD: Are the contents of the following file used?
39#include <unistd.h>
40// Note: The following file is for dynamic loading:
41#include <dlfcn.h>
42#include <pthread.h>
43#include <assert.h>
Jon Ashburnfc1031e2015-11-17 15:31:02 -070044#include <string.h>
Jon Ashburn2077e382015-06-29 11:25:34 -060045#include <stdbool.h>
Michael Lentine695f2c22015-09-09 12:39:13 -070046#include <stdlib.h>
Jon Ashburn15315172015-07-07 15:06:25 -060047#include <libgen.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070048
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060049// VK Library Filenames, Paths, etc.:
Frank Henigman57173102016-11-24 22:15:20 -050050#define PATH_SEPARATOR ':'
Jon Ashburn2077e382015-06-29 11:25:34 -060051#define DIRECTORY_SYMBOL '/'
52
John Drinkwater9ac3f4f2016-08-01 17:00:00 +010053#define VULKAN_DIR "/vulkan/"
54#define VULKAN_ICDCONF_DIR "icd.d"
55#define VULKAN_ICD_DIR "icd"
56#define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
57#define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
58#define VULKAN_LAYER_DIR "layer"
James Jonesc28b0a12015-07-23 17:39:37 -070059
Dor Askayoa120bb32016-10-22 22:20:29 +030060#if defined(EXTRASYSCONFDIR)
61#define EXTRA_DRIVERS_SYSCONFDIR_INFO ":" \
62 EXTRASYSCONFDIR VULKAN_DIR VULKAN_ICDCONF_DIR
63#define EXTRA_ELAYERS_SYSCONFDIR_INFO ":" \
64 EXTRASYSCONFDIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
65#define EXTRA_ILAYERS_SYSCONFDIR_INFO ":" \
66 EXTRASYSCONFDIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
James Jonesc28b0a12015-07-23 17:39:37 -070067#else
Dor Askayoa120bb32016-10-22 22:20:29 +030068#define EXTRA_DRIVERS_SYSCONFDIR_INFO
69#define EXTRA_ELAYERS_SYSCONFDIR_INFO
70#define EXTRA_ILAYERS_SYSCONFDIR_INFO
71#endif
72
73#if defined(EXTRADATADIR)
74#define EXTRA_DRIVERS_DATADIR_INFO ":" \
75 EXTRADATADIR VULKAN_DIR VULKAN_ICDCONF_DIR
76#define EXTRA_ELAYERS_DATADIR_INFO ":" \
77 EXTRADATADIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
78#define EXTRA_ILAYERS_DATADIR_INFO ":" \
79 EXTRADATADIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
80#else
81#define EXTRA_DRIVERS_DATADIR_INFO
82#define EXTRA_ELAYERS_DATADIR_INFO
83#define EXTRA_ILAYERS_DATADIR_INFO
James Jonesc28b0a12015-07-23 17:39:37 -070084#endif
85
Jon Ashburn23d36b12016-02-02 17:47:28 -070086#define DEFAULT_VK_DRIVERS_INFO \
Dor Askayoa120bb32016-10-22 22:20:29 +030087 SYSCONFDIR VULKAN_DIR VULKAN_ICDCONF_DIR ":" \
88 DATADIR VULKAN_DIR VULKAN_ICDCONF_DIR \
89 EXTRA_DRIVERS_SYSCONFDIR_INFO \
90 EXTRA_DRIVERS_DATADIR_INFO
Jon Ashburn23d36b12016-02-02 17:47:28 -070091#define DEFAULT_VK_ELAYERS_INFO \
Dor Askayoa120bb32016-10-22 22:20:29 +030092 SYSCONFDIR VULKAN_DIR VULKAN_ELAYERCONF_DIR ":" \
93 DATADIR VULKAN_DIR VULKAN_ELAYERCONF_DIR \
94 EXTRA_ELAYERS_SYSCONFDIR_INFO \
95 EXTRA_ELAYERS_DATADIR_INFO
Jon Ashburn23d36b12016-02-02 17:47:28 -070096#define DEFAULT_VK_ILAYERS_INFO \
Dor Askayoa120bb32016-10-22 22:20:29 +030097 SYSCONFDIR VULKAN_DIR VULKAN_ILAYERCONF_DIR ":" \
98 DATADIR VULKAN_DIR VULKAN_ILAYERCONF_DIR \
99 EXTRA_ILAYERS_SYSCONFDIR_INFO \
100 EXTRA_ILAYERS_DATADIR_INFO
101
102#define DEFAULT_VK_DRIVERS_PATH ""
Frank Henigman5ecb4f62016-11-24 17:47:26 -0500103#if !defined(DEFAULT_VK_LAYERS_PATH)
Jamie Madill2fcbd152016-04-27 16:33:23 -0400104#define DEFAULT_VK_LAYERS_PATH ""
Frank Henigman5ecb4f62016-11-24 17:47:26 -0500105#endif
Dor Askayoa120bb32016-10-22 22:20:29 +0300106
Jamie Madill00c3c912016-04-06 18:26:46 -0400107#if !defined(LAYERS_SOURCE_PATH)
108#define LAYERS_SOURCE_PATH NULL
109#endif
Jon Ashburn1b958222015-08-06 11:22:33 -0600110#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Dor Askayoa120bb32016-10-22 22:20:29 +0300111
John Drinkwater9ac3f4f2016-08-01 17:00:00 +0100112#define HOME_VK_DRIVERS_INFO VULKAN_DIR VULKAN_ICDCONF_DIR
113#define HOME_VK_ELAYERS_INFO VULKAN_DIR VULKAN_ELAYERCONF_DIR
114#define HOME_VK_ILAYERS_INFO VULKAN_DIR VULKAN_ILAYERCONF_DIR
Ian Elliott457810e2015-02-04 11:22:39 -0700115
Ian Elliotte5369462015-02-12 16:44:56 -0700116// C99:
Jon Ashburn23d36b12016-02-02 17:47:28 -0700117#define PRINTF_SIZE_T_SPECIFIER "%zu"
Tobin Ehlisb0497852015-02-11 14:24:02 -0700118
Jon Ashburn2077e382015-06-29 11:25:34 -0600119// File IO
Jon Ashburn23d36b12016-02-02 17:47:28 -0700120static inline bool loader_platform_file_exists(const char *path) {
Jon Ashburn2077e382015-06-29 11:25:34 -0600121 if (access(path, F_OK))
122 return false;
123 else
124 return true;
125}
126
Jon Ashburn23d36b12016-02-02 17:47:28 -0700127static inline bool loader_platform_is_path_absolute(const char *path) {
Jon Ashburn15315172015-07-07 15:06:25 -0600128 if (path[0] == '/')
129 return true;
130 else
131 return false;
132}
133
Jon Ashburn23d36b12016-02-02 17:47:28 -0700134static inline char *loader_platform_dirname(char *path) {
Jon Ashburn15315172015-07-07 15:06:25 -0600135 return dirname(path);
136}
137
Jon Ashburn2077e382015-06-29 11:25:34 -0600138// Dynamic Loading of libraries:
Jon Ashburn23d36b12016-02-02 17:47:28 -0700139typedef void *loader_platform_dl_handle;
140static inline loader_platform_dl_handle
141loader_platform_open_library(const char *libPath) {
Chia-I Wu6a218342015-02-18 14:39:54 -0700142 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700143}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700144static inline const char *
145loader_platform_open_library_error(const char *libPath) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700146 return dlerror();
147}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700148static inline void
149loader_platform_close_library(loader_platform_dl_handle library) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700150 dlclose(library);
151}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700152static inline void *
153loader_platform_get_proc_address(loader_platform_dl_handle library,
154 const char *name) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700155 assert(library);
156 assert(name);
157 return dlsym(library, name);
158}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700159static inline const char *
160loader_platform_get_proc_address_error(const char *name) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700161 return dlerror();
162}
163
164// Threads:
165typedef pthread_t loader_platform_thread;
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600166#define THREAD_LOCAL_DECL __thread
Jon Ashburn23d36b12016-02-02 17:47:28 -0700167#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700168 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700169#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) pthread_once_t var;
170static inline void loader_platform_thread_once(pthread_once_t *ctl,
171 void (*func)(void)) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700172 assert(func != NULL);
173 assert(ctl != NULL);
Michael Lentine695f2c22015-09-09 12:39:13 -0700174 pthread_once(ctl, func);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700175}
176
177// Thread IDs:
178typedef pthread_t loader_platform_thread_id;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700179static inline loader_platform_thread_id loader_platform_get_thread_id() {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700180 return pthread_self();
181}
182
183// Thread mutex:
184typedef pthread_mutex_t loader_platform_thread_mutex;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700185static inline void
186loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700187 pthread_mutex_init(pMutex, NULL);
188}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700189static inline void
190loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700191 pthread_mutex_lock(pMutex);
192}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700193static inline void
194loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700195 pthread_mutex_unlock(pMutex);
196}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700197static inline void
198loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700199 pthread_mutex_destroy(pMutex);
200}
Mike Stroyaned238bb2015-05-15 08:50:57 -0600201typedef pthread_cond_t loader_platform_thread_cond;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700202static inline void
203loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) {
Mike Stroyaned238bb2015-05-15 08:50:57 -0600204 pthread_cond_init(pCond, NULL);
205}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700206static inline void
207loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond,
208 loader_platform_thread_mutex *pMutex) {
Mike Stroyaned238bb2015-05-15 08:50:57 -0600209 pthread_cond_wait(pCond, pMutex);
210}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700211static inline void
212loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) {
Mike Stroyaned238bb2015-05-15 08:50:57 -0600213 pthread_cond_broadcast(pCond);
214}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700215
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600216#define loader_stack_alloc(size) alloca(size)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700217
218#elif defined(_WIN32) // defined(__linux__)
219/* Windows-specific common code: */
Tobin Ehlis890adf12015-11-02 15:45:19 -0700220// WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
221// undefine them to avoid conflicts with VkLayerDispatchTable struct members.
222#ifdef CreateSemaphore
223#undef CreateSemaphore
224#endif
225#ifdef CreateEvent
226#undef CreateEvent
227#endif
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700228#include <assert.h>
Tony Barbour1d825c72015-06-18 16:29:32 -0600229#include <stdio.h>
Jon Ashburnfc1031e2015-11-17 15:31:02 -0700230#include <string.h>
Jon Ashburnffad94d2015-06-30 14:46:22 -0700231#include <io.h>
232#include <stdbool.h>
Cody Northrop33fa0412015-07-08 16:48:37 -0600233#include <shlwapi.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700234#ifdef __cplusplus
235#include <iostream>
236#include <string>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700237#endif // __cplusplus
238
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600239// VK Library Filenames, Paths, etc.:
Frank Henigman57173102016-11-24 22:15:20 -0500240#define PATH_SEPARATOR ';'
Jon Ashburn2077e382015-06-29 11:25:34 -0600241#define DIRECTORY_SYMBOL '\\'
Jon Ashburnffad94d2015-06-30 14:46:22 -0700242#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
Lenny Komow367c4ea2016-11-07 11:40:00 -0700243#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\" API_NAME "\\Drivers"
Jamie Madill2fcbd152016-04-27 16:33:23 -0400244#define DEFAULT_VK_DRIVERS_PATH ""
Lenny Komow367c4ea2016-11-07 11:40:00 -0700245#define DEFAULT_VK_ELAYERS_INFO "SOFTWARE\\Khronos\\" API_NAME "\\ExplicitLayers"
246#define DEFAULT_VK_ILAYERS_INFO "SOFTWARE\\Khronos\\" API_NAME "\\ImplicitLayers"
Jamie Madill00c3c912016-04-06 18:26:46 -0400247#if !defined(DEFAULT_VK_LAYERS_PATH)
Jamie Madill2fcbd152016-04-27 16:33:23 -0400248#define DEFAULT_VK_LAYERS_PATH ""
Jamie Madill00c3c912016-04-06 18:26:46 -0400249#endif
250#if !defined(LAYERS_SOURCE_PATH)
251#define LAYERS_SOURCE_PATH NULL
252#endif
Jon Ashburn1b958222015-08-06 11:22:33 -0600253#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Jon Ashburn83657862016-02-17 13:18:08 -0700254#define HOME_VK_DRIVERS_INFO ""
255#define HOME_VK_ELAYERS_INFO ""
256#define HOME_VK_ILAYERS_INFO ""
Jon Ashburn23d36b12016-02-02 17:47:28 -0700257#define PRINTF_SIZE_T_SPECIFIER "%Iu"
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600258
Jon Ashburn2077e382015-06-29 11:25:34 -0600259// File IO
Jon Ashburn23d36b12016-02-02 17:47:28 -0700260static bool loader_platform_file_exists(const char *path) {
Jon Ashburnffad94d2015-06-30 14:46:22 -0700261 if ((_access(path, 0)) == -1)
Jon Ashburn2077e382015-06-29 11:25:34 -0600262 return false;
263 else
264 return true;
265}
266
Jon Ashburn23d36b12016-02-02 17:47:28 -0700267static bool loader_platform_is_path_absolute(const char *path) {
Jon Ashburn15315172015-07-07 15:06:25 -0600268 return !PathIsRelative(path);
269}
270
271// WIN32 runtime doesn't have dirname().
Jon Ashburn23d36b12016-02-02 17:47:28 -0700272static inline char *loader_platform_dirname(char *path) {
Jon Ashburn15315172015-07-07 15:06:25 -0600273 char *current, *next;
274
275 // TODO/TBD: Do we need to deal with the Windows's ":" character?
276
277 for (current = path; *current != '\0'; current = next) {
278 next = strchr(current, DIRECTORY_SYMBOL);
279 if (next == NULL) {
280 if (current != path)
281 *(current - 1) = '\0';
282 return path;
283 } else {
284 // Point one character past the DIRECTORY_SYMBOL:
285 next++;
286 }
287 }
288 return path;
289}
290
291// WIN32 runtime doesn't have basename().
292// Microsoft also doesn't have basename(). Paths are different on Windows, and
293// so this is just a temporary solution in order to get us compiling, so that we
294// can test some scenarios, and develop the correct solution for Windows.
Jon Ashburn23d36b12016-02-02 17:47:28 -0700295// TODO: Develop a better, permanent solution for Windows, to replace this
296// temporary code:
297static char *loader_platform_basename(char *pathname) {
Jon Ashburn15315172015-07-07 15:06:25 -0600298 char *current, *next;
299
Jon Ashburn23d36b12016-02-02 17:47:28 -0700300 // TODO/TBD: Do we need to deal with the Windows's ":" character?
Jon Ashburn15315172015-07-07 15:06:25 -0600301
302 for (current = pathname; *current != '\0'; current = next) {
303 next = strchr(current, DIRECTORY_SYMBOL);
304 if (next == NULL) {
305 // No more DIRECTORY_SYMBOL's so return p:
306 return current;
307 } else {
308 // Point one character past the DIRECTORY_SYMBOL:
309 next++;
310 }
311 }
312 // We shouldn't get to here, but this makes the compiler happy:
313 return current;
314}
315
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700316// Dynamic Loading:
317typedef HMODULE loader_platform_dl_handle;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700318static loader_platform_dl_handle
319loader_platform_open_library(const char *libPath) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700320 return LoadLibrary(libPath);
321}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700322static char *loader_platform_open_library_error(const char *libPath) {
Tobin Ehlisb2dfb552016-06-07 06:07:13 -0600323 static char errorMsg[164];
Karl Schultze2ef9e62017-01-13 14:01:35 -0700324 (void)snprintf(errorMsg, 163, "Failed to open dynamic library \"%s\"",
325 libPath);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700326 return errorMsg;
327}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700328static void loader_platform_close_library(loader_platform_dl_handle library) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700329 FreeLibrary(library);
330}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700331static void *loader_platform_get_proc_address(loader_platform_dl_handle library,
332 const char *name) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700333 assert(library);
334 assert(name);
335 return GetProcAddress(library, name);
336}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700337static char *loader_platform_get_proc_address_error(const char *name) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700338 static char errorMsg[120];
Karl Schultze2ef9e62017-01-13 14:01:35 -0700339 (void)snprintf(errorMsg, 119,
340 "Failed to find function \"%s\" in dynamic library", name);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700341 return errorMsg;
342}
343
344// Threads:
345typedef HANDLE loader_platform_thread;
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600346#define THREAD_LOCAL_DECL __declspec(thread)
Jon Ashburn23d36b12016-02-02 17:47:28 -0700347#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700348 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700349#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var;
350static BOOL CALLBACK
351InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
Piers Daniell4da523a2015-02-23 16:23:13 -0700352 void (*func)(void) = (void (*)(void))Parameter;
353 func();
354 return TRUE;
355}
356
Jon Ashburn23d36b12016-02-02 17:47:28 -0700357static void loader_platform_thread_once(void *ctl, void (*func)(void)) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700358 assert(func != NULL);
359 assert(ctl != NULL);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700360 InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, func, NULL);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700361}
362
363// Thread IDs:
364typedef DWORD loader_platform_thread_id;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700365static loader_platform_thread_id loader_platform_get_thread_id() {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700366 return GetCurrentThreadId();
367}
368
369// Thread mutex:
370typedef CRITICAL_SECTION loader_platform_thread_mutex;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700371static void
372loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700373 InitializeCriticalSection(pMutex);
374}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700375static void
376loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700377 EnterCriticalSection(pMutex);
378}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700379static void
380loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700381 LeaveCriticalSection(pMutex);
382}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700383static void
384loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700385 DeleteCriticalSection(pMutex);
386}
Mike Stroyanc3d98332015-05-15 17:34:51 -0600387typedef CONDITION_VARIABLE loader_platform_thread_cond;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700388static void
389loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) {
Mike Stroyanc3d98332015-05-15 17:34:51 -0600390 InitializeConditionVariable(pCond);
391}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700392static void
393loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond,
394 loader_platform_thread_mutex *pMutex) {
Mike Stroyanc3d98332015-05-15 17:34:51 -0600395 SleepConditionVariableCS(pCond, pMutex, INFINITE);
396}
Jon Ashburn23d36b12016-02-02 17:47:28 -0700397static void
398loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) {
Mike Stroyanc3d98332015-05-15 17:34:51 -0600399 WakeAllConditionVariable(pCond);
400}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700401
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600402// Windows Registry:
Jon Ashburn23d36b12016-02-02 17:47:28 -0700403char *loader_get_registry_string(const HKEY hive, const LPCTSTR sub_key,
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600404 const char *value);
405
Jon Ashburn3f8c3002015-10-15 13:47:58 -0600406#define loader_stack_alloc(size) _alloca(size)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700407#else // defined(_WIN32)
408
409#error The "loader_platform.h" file must be modified for this OS.
410
411// NOTE: In order to support another OS, an #elif needs to be added (above the
412// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
413// contents of this file must be created.
414
415// NOTE: Other OS-specific changes are also needed for this OS. Search for
416// files with "WIN32" in it, as a quick way to find files that must be changed.
417
418#endif // defined(_WIN32)
419
jon547bbee2015-10-29 14:57:03 -0600420// returns true if the given string appears to be a relative or absolute
421// path, as opposed to a bare filename.
Jon Ashburn23d36b12016-02-02 17:47:28 -0700422static inline bool loader_platform_is_path(const char *path) {
jon547bbee2015-10-29 14:57:03 -0600423 return strchr(path, DIRECTORY_SYMBOL) != NULL;
424}