1*b7893ccfSSadaf Ebrahimi /*
2*b7893ccfSSadaf Ebrahimi *
3*b7893ccfSSadaf Ebrahimi * Copyright (c) 2015-2018 The Khronos Group Inc.
4*b7893ccfSSadaf Ebrahimi * Copyright (c) 2015-2018 Valve Corporation
5*b7893ccfSSadaf Ebrahimi * Copyright (c) 2015-2018 LunarG, Inc.
6*b7893ccfSSadaf Ebrahimi *
7*b7893ccfSSadaf Ebrahimi * Licensed under the Apache License, Version 2.0 (the "License");
8*b7893ccfSSadaf Ebrahimi * you may not use this file except in compliance with the License.
9*b7893ccfSSadaf Ebrahimi * You may obtain a copy of the License at
10*b7893ccfSSadaf Ebrahimi *
11*b7893ccfSSadaf Ebrahimi * http://www.apache.org/licenses/LICENSE-2.0
12*b7893ccfSSadaf Ebrahimi *
13*b7893ccfSSadaf Ebrahimi * Unless required by applicable law or agreed to in writing, software
14*b7893ccfSSadaf Ebrahimi * distributed under the License is distributed on an "AS IS" BASIS,
15*b7893ccfSSadaf Ebrahimi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*b7893ccfSSadaf Ebrahimi * See the License for the specific language governing permissions and
17*b7893ccfSSadaf Ebrahimi * limitations under the License.
18*b7893ccfSSadaf Ebrahimi *
19*b7893ccfSSadaf Ebrahimi * Author: Ian Elliot <[email protected]>
20*b7893ccfSSadaf Ebrahimi * Author: Jon Ashburn <[email protected]>
21*b7893ccfSSadaf Ebrahimi * Author: Lenny Komow <[email protected]>
22*b7893ccfSSadaf Ebrahimi *
23*b7893ccfSSadaf Ebrahimi */
24*b7893ccfSSadaf Ebrahimi #pragma once
25*b7893ccfSSadaf Ebrahimi
26*b7893ccfSSadaf Ebrahimi #if defined(_WIN32)
27*b7893ccfSSadaf Ebrahimi // WinSock2.h must be included *BEFORE* windows.h
28*b7893ccfSSadaf Ebrahimi #include <WinSock2.h>
29*b7893ccfSSadaf Ebrahimi #endif // _WIN32
30*b7893ccfSSadaf Ebrahimi
31*b7893ccfSSadaf Ebrahimi #include "vulkan/vk_platform.h"
32*b7893ccfSSadaf Ebrahimi #include "vulkan/vk_sdk_platform.h"
33*b7893ccfSSadaf Ebrahimi
34*b7893ccfSSadaf Ebrahimi #if defined(__linux__) || defined(__APPLE__)
35*b7893ccfSSadaf Ebrahimi /* Linux-specific common code: */
36*b7893ccfSSadaf Ebrahimi
37*b7893ccfSSadaf Ebrahimi // Headers:
38*b7893ccfSSadaf Ebrahimi //#define _GNU_SOURCE 1
39*b7893ccfSSadaf Ebrahimi // TBD: Are the contents of the following file used?
40*b7893ccfSSadaf Ebrahimi #include <unistd.h>
41*b7893ccfSSadaf Ebrahimi // Note: The following file is for dynamic loading:
42*b7893ccfSSadaf Ebrahimi #include <dlfcn.h>
43*b7893ccfSSadaf Ebrahimi #include <pthread.h>
44*b7893ccfSSadaf Ebrahimi #include <assert.h>
45*b7893ccfSSadaf Ebrahimi #include <string.h>
46*b7893ccfSSadaf Ebrahimi #include <stdbool.h>
47*b7893ccfSSadaf Ebrahimi #include <stdlib.h>
48*b7893ccfSSadaf Ebrahimi #include <libgen.h>
49*b7893ccfSSadaf Ebrahimi
50*b7893ccfSSadaf Ebrahimi // VK Library Filenames, Paths, etc.:
51*b7893ccfSSadaf Ebrahimi #define PATH_SEPARATOR ':'
52*b7893ccfSSadaf Ebrahimi #define DIRECTORY_SYMBOL '/'
53*b7893ccfSSadaf Ebrahimi
54*b7893ccfSSadaf Ebrahimi #define VULKAN_DIR "/vulkan/"
55*b7893ccfSSadaf Ebrahimi #define VULKAN_ICDCONF_DIR "icd.d"
56*b7893ccfSSadaf Ebrahimi #define VULKAN_ICD_DIR "icd"
57*b7893ccfSSadaf Ebrahimi #define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
58*b7893ccfSSadaf Ebrahimi #define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
59*b7893ccfSSadaf Ebrahimi #define VULKAN_LAYER_DIR "layer"
60*b7893ccfSSadaf Ebrahimi
61*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_DRIVERS_INFO ""
62*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_ELAYERS_INFO ""
63*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_ILAYERS_INFO ""
64*b7893ccfSSadaf Ebrahimi
65*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_DRIVERS_PATH ""
66*b7893ccfSSadaf Ebrahimi #if !defined(DEFAULT_VK_LAYERS_PATH)
67*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_LAYERS_PATH ""
68*b7893ccfSSadaf Ebrahimi #endif
69*b7893ccfSSadaf Ebrahimi
70*b7893ccfSSadaf Ebrahimi #if !defined(LAYERS_SOURCE_PATH)
71*b7893ccfSSadaf Ebrahimi #define LAYERS_SOURCE_PATH NULL
72*b7893ccfSSadaf Ebrahimi #endif
73*b7893ccfSSadaf Ebrahimi #define LAYERS_PATH_ENV "VK_LAYER_PATH"
74*b7893ccfSSadaf Ebrahimi #define ENABLED_LAYERS_ENV "VK_INSTANCE_LAYERS"
75*b7893ccfSSadaf Ebrahimi
76*b7893ccfSSadaf Ebrahimi #define RELATIVE_VK_DRIVERS_INFO VULKAN_DIR VULKAN_ICDCONF_DIR
77*b7893ccfSSadaf Ebrahimi #define RELATIVE_VK_ELAYERS_INFO VULKAN_DIR VULKAN_ELAYERCONF_DIR
78*b7893ccfSSadaf Ebrahimi #define RELATIVE_VK_ILAYERS_INFO VULKAN_DIR VULKAN_ILAYERCONF_DIR
79*b7893ccfSSadaf Ebrahimi
80*b7893ccfSSadaf Ebrahimi // C99:
81*b7893ccfSSadaf Ebrahimi #define PRINTF_SIZE_T_SPECIFIER "%zu"
82*b7893ccfSSadaf Ebrahimi
83*b7893ccfSSadaf Ebrahimi // File IO
loader_platform_file_exists(const char * path)84*b7893ccfSSadaf Ebrahimi static inline bool loader_platform_file_exists(const char *path) {
85*b7893ccfSSadaf Ebrahimi if (access(path, F_OK))
86*b7893ccfSSadaf Ebrahimi return false;
87*b7893ccfSSadaf Ebrahimi else
88*b7893ccfSSadaf Ebrahimi return true;
89*b7893ccfSSadaf Ebrahimi }
90*b7893ccfSSadaf Ebrahimi
loader_platform_is_path_absolute(const char * path)91*b7893ccfSSadaf Ebrahimi static inline bool loader_platform_is_path_absolute(const char *path) {
92*b7893ccfSSadaf Ebrahimi if (path[0] == '/')
93*b7893ccfSSadaf Ebrahimi return true;
94*b7893ccfSSadaf Ebrahimi else
95*b7893ccfSSadaf Ebrahimi return false;
96*b7893ccfSSadaf Ebrahimi }
97*b7893ccfSSadaf Ebrahimi
loader_platform_dirname(char * path)98*b7893ccfSSadaf Ebrahimi static inline char *loader_platform_dirname(char *path) { return dirname(path); }
99*b7893ccfSSadaf Ebrahimi
100*b7893ccfSSadaf Ebrahimi // Dynamic Loading of libraries:
101*b7893ccfSSadaf Ebrahimi typedef void *loader_platform_dl_handle;
loader_platform_open_library(const char * libPath)102*b7893ccfSSadaf Ebrahimi static inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
103*b7893ccfSSadaf Ebrahimi // When loading the library, we use RTLD_LAZY so that not all symbols have to be
104*b7893ccfSSadaf Ebrahimi // resolved at this time (which improves performance). Note that if not all symbols
105*b7893ccfSSadaf Ebrahimi // can be resolved, this could cause crashes later. Use the LD_BIND_NOW environment
106*b7893ccfSSadaf Ebrahimi // variable to force all symbols to be resolved here.
107*b7893ccfSSadaf Ebrahimi return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
108*b7893ccfSSadaf Ebrahimi }
loader_platform_open_library_error(const char * libPath)109*b7893ccfSSadaf Ebrahimi static inline const char *loader_platform_open_library_error(const char *libPath) { return dlerror(); }
loader_platform_close_library(loader_platform_dl_handle library)110*b7893ccfSSadaf Ebrahimi static inline void loader_platform_close_library(loader_platform_dl_handle library) { dlclose(library); }
loader_platform_get_proc_address(loader_platform_dl_handle library,const char * name)111*b7893ccfSSadaf Ebrahimi static inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
112*b7893ccfSSadaf Ebrahimi assert(library);
113*b7893ccfSSadaf Ebrahimi assert(name);
114*b7893ccfSSadaf Ebrahimi return dlsym(library, name);
115*b7893ccfSSadaf Ebrahimi }
loader_platform_get_proc_address_error(const char * name)116*b7893ccfSSadaf Ebrahimi static inline const char *loader_platform_get_proc_address_error(const char *name) { return dlerror(); }
117*b7893ccfSSadaf Ebrahimi
118*b7893ccfSSadaf Ebrahimi // Threads:
119*b7893ccfSSadaf Ebrahimi typedef pthread_t loader_platform_thread;
120*b7893ccfSSadaf Ebrahimi #define THREAD_LOCAL_DECL __thread
121*b7893ccfSSadaf Ebrahimi
122*b7893ccfSSadaf Ebrahimi // The once init functionality is not used on Linux
123*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
124*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
125*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
126*b7893ccfSSadaf Ebrahimi
127*b7893ccfSSadaf Ebrahimi // Thread IDs:
128*b7893ccfSSadaf Ebrahimi typedef pthread_t loader_platform_thread_id;
loader_platform_get_thread_id()129*b7893ccfSSadaf Ebrahimi static inline loader_platform_thread_id loader_platform_get_thread_id() { return pthread_self(); }
130*b7893ccfSSadaf Ebrahimi
131*b7893ccfSSadaf Ebrahimi // Thread mutex:
132*b7893ccfSSadaf Ebrahimi typedef pthread_mutex_t loader_platform_thread_mutex;
loader_platform_thread_create_mutex(loader_platform_thread_mutex * pMutex)133*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_init(pMutex, NULL); }
loader_platform_thread_lock_mutex(loader_platform_thread_mutex * pMutex)134*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
loader_platform_thread_unlock_mutex(loader_platform_thread_mutex * pMutex)135*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
loader_platform_thread_delete_mutex(loader_platform_thread_mutex * pMutex)136*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }
137*b7893ccfSSadaf Ebrahimi typedef pthread_cond_t loader_platform_thread_cond;
loader_platform_thread_init_cond(loader_platform_thread_cond * pCond)138*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) { pthread_cond_init(pCond, NULL); }
loader_platform_thread_cond_wait(loader_platform_thread_cond * pCond,loader_platform_thread_mutex * pMutex)139*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond, loader_platform_thread_mutex *pMutex) {
140*b7893ccfSSadaf Ebrahimi pthread_cond_wait(pCond, pMutex);
141*b7893ccfSSadaf Ebrahimi }
loader_platform_thread_cond_broadcast(loader_platform_thread_cond * pCond)142*b7893ccfSSadaf Ebrahimi static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) { pthread_cond_broadcast(pCond); }
143*b7893ccfSSadaf Ebrahimi
144*b7893ccfSSadaf Ebrahimi #define loader_stack_alloc(size) alloca(size)
145*b7893ccfSSadaf Ebrahimi
146*b7893ccfSSadaf Ebrahimi #elif defined(_WIN32) // defined(__linux__)
147*b7893ccfSSadaf Ebrahimi /* Windows-specific common code: */
148*b7893ccfSSadaf Ebrahimi // WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
149*b7893ccfSSadaf Ebrahimi // undefine them to avoid conflicts with VkLayerDispatchTable struct members.
150*b7893ccfSSadaf Ebrahimi #ifdef CreateSemaphore
151*b7893ccfSSadaf Ebrahimi #undef CreateSemaphore
152*b7893ccfSSadaf Ebrahimi #endif
153*b7893ccfSSadaf Ebrahimi #ifdef CreateEvent
154*b7893ccfSSadaf Ebrahimi #undef CreateEvent
155*b7893ccfSSadaf Ebrahimi #endif
156*b7893ccfSSadaf Ebrahimi #include <assert.h>
157*b7893ccfSSadaf Ebrahimi #include <stdio.h>
158*b7893ccfSSadaf Ebrahimi #include <string.h>
159*b7893ccfSSadaf Ebrahimi #include <io.h>
160*b7893ccfSSadaf Ebrahimi #include <stdbool.h>
161*b7893ccfSSadaf Ebrahimi #include <shlwapi.h>
162*b7893ccfSSadaf Ebrahimi #ifdef __cplusplus
163*b7893ccfSSadaf Ebrahimi #include <iostream>
164*b7893ccfSSadaf Ebrahimi #include <string>
165*b7893ccfSSadaf Ebrahimi #endif // __cplusplus
166*b7893ccfSSadaf Ebrahimi
167*b7893ccfSSadaf Ebrahimi // VK Library Filenames, Paths, etc.:
168*b7893ccfSSadaf Ebrahimi #define PATH_SEPARATOR ';'
169*b7893ccfSSadaf Ebrahimi #define DIRECTORY_SYMBOL '\\'
170*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
171*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_REGISTRY_HIVE_STR "HKEY_LOCAL_MACHINE"
172*b7893ccfSSadaf Ebrahimi #define SECONDARY_VK_REGISTRY_HIVE HKEY_CURRENT_USER
173*b7893ccfSSadaf Ebrahimi #define SECONDARY_VK_REGISTRY_HIVE_STR "HKEY_CURRENT_USER"
174*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\" API_NAME "\\Drivers"
175*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_DRIVERS_PATH ""
176*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_ELAYERS_INFO "SOFTWARE\\Khronos\\" API_NAME "\\ExplicitLayers"
177*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_ILAYERS_INFO "SOFTWARE\\Khronos\\" API_NAME "\\ImplicitLayers"
178*b7893ccfSSadaf Ebrahimi #if !defined(DEFAULT_VK_LAYERS_PATH)
179*b7893ccfSSadaf Ebrahimi #define DEFAULT_VK_LAYERS_PATH ""
180*b7893ccfSSadaf Ebrahimi #endif
181*b7893ccfSSadaf Ebrahimi #if !defined(LAYERS_SOURCE_PATH)
182*b7893ccfSSadaf Ebrahimi #define LAYERS_SOURCE_PATH NULL
183*b7893ccfSSadaf Ebrahimi #endif
184*b7893ccfSSadaf Ebrahimi #define LAYERS_PATH_ENV "VK_LAYER_PATH"
185*b7893ccfSSadaf Ebrahimi #define ENABLED_LAYERS_ENV "VK_INSTANCE_LAYERS"
186*b7893ccfSSadaf Ebrahimi #define RELATIVE_VK_DRIVERS_INFO ""
187*b7893ccfSSadaf Ebrahimi #define RELATIVE_VK_ELAYERS_INFO ""
188*b7893ccfSSadaf Ebrahimi #define RELATIVE_VK_ILAYERS_INFO ""
189*b7893ccfSSadaf Ebrahimi #define PRINTF_SIZE_T_SPECIFIER "%Iu"
190*b7893ccfSSadaf Ebrahimi
191*b7893ccfSSadaf Ebrahimi #if defined(_WIN32)
192*b7893ccfSSadaf Ebrahimi // Get the key for the plug n play driver registry
193*b7893ccfSSadaf Ebrahimi // The string returned by this function should NOT be freed
LoaderPnpDriverRegistry()194*b7893ccfSSadaf Ebrahimi static inline const char *LoaderPnpDriverRegistry() {
195*b7893ccfSSadaf Ebrahimi BOOL is_wow;
196*b7893ccfSSadaf Ebrahimi IsWow64Process(GetCurrentProcess(), &is_wow);
197*b7893ccfSSadaf Ebrahimi return is_wow ? (API_NAME "DriverNameWow") : (API_NAME "DriverName");
198*b7893ccfSSadaf Ebrahimi }
199*b7893ccfSSadaf Ebrahimi
200*b7893ccfSSadaf Ebrahimi // Get the key for the plug 'n play explicit layer registry
201*b7893ccfSSadaf Ebrahimi // The string returned by this function should NOT be freed
LoaderPnpELayerRegistry()202*b7893ccfSSadaf Ebrahimi static inline const char *LoaderPnpELayerRegistry() {
203*b7893ccfSSadaf Ebrahimi BOOL is_wow;
204*b7893ccfSSadaf Ebrahimi IsWow64Process(GetCurrentProcess(), &is_wow);
205*b7893ccfSSadaf Ebrahimi return is_wow ? (API_NAME "ExplicitLayersWow") : (API_NAME "ExplicitLayers");
206*b7893ccfSSadaf Ebrahimi }
207*b7893ccfSSadaf Ebrahimi // Get the key for the plug 'n play implicit layer registry
208*b7893ccfSSadaf Ebrahimi // The string returned by this function should NOT be freed
209*b7893ccfSSadaf Ebrahimi
LoaderPnpILayerRegistry()210*b7893ccfSSadaf Ebrahimi static inline const char *LoaderPnpILayerRegistry() {
211*b7893ccfSSadaf Ebrahimi BOOL is_wow;
212*b7893ccfSSadaf Ebrahimi IsWow64Process(GetCurrentProcess(), &is_wow);
213*b7893ccfSSadaf Ebrahimi return is_wow ? (API_NAME "ImplicitLayersWow") : (API_NAME "ImplicitLayers");
214*b7893ccfSSadaf Ebrahimi }
215*b7893ccfSSadaf Ebrahimi #endif
216*b7893ccfSSadaf Ebrahimi
217*b7893ccfSSadaf Ebrahimi // File IO
loader_platform_file_exists(const char * path)218*b7893ccfSSadaf Ebrahimi static bool loader_platform_file_exists(const char *path) {
219*b7893ccfSSadaf Ebrahimi if ((_access(path, 0)) == -1)
220*b7893ccfSSadaf Ebrahimi return false;
221*b7893ccfSSadaf Ebrahimi else
222*b7893ccfSSadaf Ebrahimi return true;
223*b7893ccfSSadaf Ebrahimi }
224*b7893ccfSSadaf Ebrahimi
loader_platform_is_path_absolute(const char * path)225*b7893ccfSSadaf Ebrahimi static bool loader_platform_is_path_absolute(const char *path) {
226*b7893ccfSSadaf Ebrahimi if (!path || !*path) {
227*b7893ccfSSadaf Ebrahimi return false;
228*b7893ccfSSadaf Ebrahimi }
229*b7893ccfSSadaf Ebrahimi if (*path == DIRECTORY_SYMBOL || path[1] == ':') {
230*b7893ccfSSadaf Ebrahimi return true;
231*b7893ccfSSadaf Ebrahimi }
232*b7893ccfSSadaf Ebrahimi return false;
233*b7893ccfSSadaf Ebrahimi }
234*b7893ccfSSadaf Ebrahimi
235*b7893ccfSSadaf Ebrahimi // WIN32 runtime doesn't have dirname().
loader_platform_dirname(char * path)236*b7893ccfSSadaf Ebrahimi static inline char *loader_platform_dirname(char *path) {
237*b7893ccfSSadaf Ebrahimi char *current, *next;
238*b7893ccfSSadaf Ebrahimi
239*b7893ccfSSadaf Ebrahimi // TODO/TBD: Do we need to deal with the Windows's ":" character?
240*b7893ccfSSadaf Ebrahimi
241*b7893ccfSSadaf Ebrahimi for (current = path; *current != '\0'; current = next) {
242*b7893ccfSSadaf Ebrahimi next = strchr(current, DIRECTORY_SYMBOL);
243*b7893ccfSSadaf Ebrahimi if (next == NULL) {
244*b7893ccfSSadaf Ebrahimi if (current != path) *(current - 1) = '\0';
245*b7893ccfSSadaf Ebrahimi return path;
246*b7893ccfSSadaf Ebrahimi } else {
247*b7893ccfSSadaf Ebrahimi // Point one character past the DIRECTORY_SYMBOL:
248*b7893ccfSSadaf Ebrahimi next++;
249*b7893ccfSSadaf Ebrahimi }
250*b7893ccfSSadaf Ebrahimi }
251*b7893ccfSSadaf Ebrahimi return path;
252*b7893ccfSSadaf Ebrahimi }
253*b7893ccfSSadaf Ebrahimi
254*b7893ccfSSadaf Ebrahimi // WIN32 runtime doesn't have basename().
255*b7893ccfSSadaf Ebrahimi // Microsoft also doesn't have basename(). Paths are different on Windows, and
256*b7893ccfSSadaf Ebrahimi // so this is just a temporary solution in order to get us compiling, so that we
257*b7893ccfSSadaf Ebrahimi // can test some scenarios, and develop the correct solution for Windows.
258*b7893ccfSSadaf Ebrahimi // TODO: Develop a better, permanent solution for Windows, to replace this
259*b7893ccfSSadaf Ebrahimi // temporary code:
loader_platform_basename(char * pathname)260*b7893ccfSSadaf Ebrahimi static char *loader_platform_basename(char *pathname) {
261*b7893ccfSSadaf Ebrahimi char *current, *next;
262*b7893ccfSSadaf Ebrahimi
263*b7893ccfSSadaf Ebrahimi // TODO/TBD: Do we need to deal with the Windows's ":" character?
264*b7893ccfSSadaf Ebrahimi
265*b7893ccfSSadaf Ebrahimi for (current = pathname; *current != '\0'; current = next) {
266*b7893ccfSSadaf Ebrahimi next = strchr(current, DIRECTORY_SYMBOL);
267*b7893ccfSSadaf Ebrahimi if (next == NULL) {
268*b7893ccfSSadaf Ebrahimi // No more DIRECTORY_SYMBOL's so return p:
269*b7893ccfSSadaf Ebrahimi return current;
270*b7893ccfSSadaf Ebrahimi } else {
271*b7893ccfSSadaf Ebrahimi // Point one character past the DIRECTORY_SYMBOL:
272*b7893ccfSSadaf Ebrahimi next++;
273*b7893ccfSSadaf Ebrahimi }
274*b7893ccfSSadaf Ebrahimi }
275*b7893ccfSSadaf Ebrahimi // We shouldn't get to here, but this makes the compiler happy:
276*b7893ccfSSadaf Ebrahimi return current;
277*b7893ccfSSadaf Ebrahimi }
278*b7893ccfSSadaf Ebrahimi
279*b7893ccfSSadaf Ebrahimi // Dynamic Loading:
280*b7893ccfSSadaf Ebrahimi typedef HMODULE loader_platform_dl_handle;
loader_platform_open_library(const char * lib_path)281*b7893ccfSSadaf Ebrahimi static loader_platform_dl_handle loader_platform_open_library(const char *lib_path) {
282*b7893ccfSSadaf Ebrahimi // Try loading the library the original way first.
283*b7893ccfSSadaf Ebrahimi loader_platform_dl_handle lib_handle = LoadLibrary(lib_path);
284*b7893ccfSSadaf Ebrahimi if (lib_handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
285*b7893ccfSSadaf Ebrahimi // If that failed, then try loading it with broader search folders.
286*b7893ccfSSadaf Ebrahimi lib_handle = LoadLibraryEx(lib_path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
287*b7893ccfSSadaf Ebrahimi }
288*b7893ccfSSadaf Ebrahimi return lib_handle;
289*b7893ccfSSadaf Ebrahimi }
loader_platform_open_library_error(const char * libPath)290*b7893ccfSSadaf Ebrahimi static char *loader_platform_open_library_error(const char *libPath) {
291*b7893ccfSSadaf Ebrahimi static char errorMsg[164];
292*b7893ccfSSadaf Ebrahimi (void)snprintf(errorMsg, 163, "Failed to open dynamic library \"%s\" with error %lu", libPath, GetLastError());
293*b7893ccfSSadaf Ebrahimi return errorMsg;
294*b7893ccfSSadaf Ebrahimi }
loader_platform_close_library(loader_platform_dl_handle library)295*b7893ccfSSadaf Ebrahimi static void loader_platform_close_library(loader_platform_dl_handle library) { FreeLibrary(library); }
loader_platform_get_proc_address(loader_platform_dl_handle library,const char * name)296*b7893ccfSSadaf Ebrahimi static void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
297*b7893ccfSSadaf Ebrahimi assert(library);
298*b7893ccfSSadaf Ebrahimi assert(name);
299*b7893ccfSSadaf Ebrahimi return (void *)GetProcAddress(library, name);
300*b7893ccfSSadaf Ebrahimi }
loader_platform_get_proc_address_error(const char * name)301*b7893ccfSSadaf Ebrahimi static char *loader_platform_get_proc_address_error(const char *name) {
302*b7893ccfSSadaf Ebrahimi static char errorMsg[120];
303*b7893ccfSSadaf Ebrahimi (void)snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
304*b7893ccfSSadaf Ebrahimi return errorMsg;
305*b7893ccfSSadaf Ebrahimi }
306*b7893ccfSSadaf Ebrahimi
307*b7893ccfSSadaf Ebrahimi // Threads:
308*b7893ccfSSadaf Ebrahimi typedef HANDLE loader_platform_thread;
309*b7893ccfSSadaf Ebrahimi #define THREAD_LOCAL_DECL __declspec(thread)
310*b7893ccfSSadaf Ebrahimi
311*b7893ccfSSadaf Ebrahimi // The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the
312*b7893ccfSSadaf Ebrahimi // resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic
313*b7893ccfSSadaf Ebrahimi // ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources.
314*b7893ccfSSadaf Ebrahimi #if defined(LOADER_DYNAMIC_LIB)
315*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
316*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
317*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
318*b7893ccfSSadaf Ebrahimi #else
319*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) INIT_ONCE var = INIT_ONCE_STATIC_INIT;
320*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var;
321*b7893ccfSSadaf Ebrahimi #define LOADER_PLATFORM_THREAD_ONCE(ctl, func) loader_platform_thread_once_fn(ctl, func)
InitFuncWrapper(PINIT_ONCE InitOnce,PVOID Parameter,PVOID * Context)322*b7893ccfSSadaf Ebrahimi static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
323*b7893ccfSSadaf Ebrahimi void (*func)(void) = (void (*)(void))Parameter;
324*b7893ccfSSadaf Ebrahimi func();
325*b7893ccfSSadaf Ebrahimi return TRUE;
326*b7893ccfSSadaf Ebrahimi }
loader_platform_thread_once_fn(void * ctl,void (* func)(void))327*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_once_fn(void *ctl, void (*func)(void)) {
328*b7893ccfSSadaf Ebrahimi assert(func != NULL);
329*b7893ccfSSadaf Ebrahimi assert(ctl != NULL);
330*b7893ccfSSadaf Ebrahimi InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, (void *)func, NULL);
331*b7893ccfSSadaf Ebrahimi }
332*b7893ccfSSadaf Ebrahimi #endif
333*b7893ccfSSadaf Ebrahimi
334*b7893ccfSSadaf Ebrahimi // Thread IDs:
335*b7893ccfSSadaf Ebrahimi typedef DWORD loader_platform_thread_id;
loader_platform_get_thread_id()336*b7893ccfSSadaf Ebrahimi static loader_platform_thread_id loader_platform_get_thread_id() { return GetCurrentThreadId(); }
337*b7893ccfSSadaf Ebrahimi
338*b7893ccfSSadaf Ebrahimi // Thread mutex:
339*b7893ccfSSadaf Ebrahimi typedef CRITICAL_SECTION loader_platform_thread_mutex;
loader_platform_thread_create_mutex(loader_platform_thread_mutex * pMutex)340*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { InitializeCriticalSection(pMutex); }
loader_platform_thread_lock_mutex(loader_platform_thread_mutex * pMutex)341*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { EnterCriticalSection(pMutex); }
loader_platform_thread_unlock_mutex(loader_platform_thread_mutex * pMutex)342*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { LeaveCriticalSection(pMutex); }
loader_platform_thread_delete_mutex(loader_platform_thread_mutex * pMutex)343*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { DeleteCriticalSection(pMutex); }
344*b7893ccfSSadaf Ebrahimi typedef CONDITION_VARIABLE loader_platform_thread_cond;
loader_platform_thread_init_cond(loader_platform_thread_cond * pCond)345*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) { InitializeConditionVariable(pCond); }
loader_platform_thread_cond_wait(loader_platform_thread_cond * pCond,loader_platform_thread_mutex * pMutex)346*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond, loader_platform_thread_mutex *pMutex) {
347*b7893ccfSSadaf Ebrahimi SleepConditionVariableCS(pCond, pMutex, INFINITE);
348*b7893ccfSSadaf Ebrahimi }
loader_platform_thread_cond_broadcast(loader_platform_thread_cond * pCond)349*b7893ccfSSadaf Ebrahimi static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) { WakeAllConditionVariable(pCond); }
350*b7893ccfSSadaf Ebrahimi
351*b7893ccfSSadaf Ebrahimi #define loader_stack_alloc(size) _alloca(size)
352*b7893ccfSSadaf Ebrahimi #else // defined(_WIN32)
353*b7893ccfSSadaf Ebrahimi
354*b7893ccfSSadaf Ebrahimi #error The "loader_platform.h" file must be modified for this OS.
355*b7893ccfSSadaf Ebrahimi
356*b7893ccfSSadaf Ebrahimi // NOTE: In order to support another OS, an #elif needs to be added (above the
357*b7893ccfSSadaf Ebrahimi // "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
358*b7893ccfSSadaf Ebrahimi // contents of this file must be created.
359*b7893ccfSSadaf Ebrahimi
360*b7893ccfSSadaf Ebrahimi // NOTE: Other OS-specific changes are also needed for this OS. Search for
361*b7893ccfSSadaf Ebrahimi // files with "WIN32" in it, as a quick way to find files that must be changed.
362*b7893ccfSSadaf Ebrahimi
363*b7893ccfSSadaf Ebrahimi #endif // defined(_WIN32)
364*b7893ccfSSadaf Ebrahimi
365*b7893ccfSSadaf Ebrahimi // returns true if the given string appears to be a relative or absolute
366*b7893ccfSSadaf Ebrahimi // path, as opposed to a bare filename.
loader_platform_is_path(const char * path)367*b7893ccfSSadaf Ebrahimi static inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
368