blob: a9cd4df1f9bcea89db2b5026103e11fa3ad8a7d9 [file] [log] [blame]
Ian Elliott81ac44c2015-01-13 17:52:38 -07001/*
2 * XGL
3 *
4 * Copyright (C) 2015 LunarG, Inc.
5 * Copyright 2014 Valve Software
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Ian Elliott <ian@lunarg.com>
28 */
29
30#ifndef LOADER_PLATFORM_H
31#define LOADER_PLATFORM_H
32
33#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>
44
45// C99:
46#define STATIC_INLINE static inline
47
48// Dynamic Loading:
49typedef void * loader_platform_dl_handle;
50static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
51{
52 // NOTE: The prior (Linux only) loader code always used RTLD_LAZY. In one
53 // place, it used RTLD_DEEPBIND. It probably doesn't hurt to always use
54 // RTLD_DEEPBIND, and so that is what is being done.
55 return dlopen(libPath, RTLD_LAZY | RTLD_DEEPBIND | RTLD_LOCAL);
56}
57static inline char * loader_platform_open_library_error(const char* libPath)
58{
59 return dlerror();
60}
61static inline void loader_platform_close_library(loader_platform_dl_handle library)
62{
63 dlclose(library);
64}
65static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
66 const char *name)
67{
68 assert(library);
69 assert(name);
70 return dlsym(library, name);
71}
72static inline char * loader_platform_get_proc_address_error(const char *name)
73{
74 return dlerror();
75}
76
77// Threads:
78typedef pthread_t loader_platform_thread;
79#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
80 pthread_once_t var = PTHREAD_ONCE_INIT;
81static inline void loader_platform_thread_once(void *ctl, void (* func) (void))
82{
83 assert(func != NULL);
84 assert(ctl != NULL);
85 pthread_once((pthread_once_t *) ctl, func);
86}
87
88// Thread IDs:
89typedef pthread_t loader_platform_thread_id;
90static inline loader_platform_thread_id loader_platform_get_thread_id()
91{
92 return pthread_self();
93}
94
95// Thread mutex:
96typedef pthread_mutex_t loader_platform_thread_mutex;
97static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
98{
99 pthread_mutex_init(pMutex, NULL);
100}
101static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
102{
103 pthread_mutex_lock(pMutex);
104}
105static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
106{
107 pthread_mutex_unlock(pMutex);
108}
109static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
110{
111 pthread_mutex_destroy(pMutex);
112}
113
114
115#elif defined(_WIN32) // defined(__linux__)
116/* Windows-specific common code: */
117
118// Headers:
119#include <windows.h>
120#include <assert.h>
121#ifdef __cplusplus
122#include <iostream>
123#include <string>
124using namespace std;
125#endif // __cplusplus
126
127// C99:
128// Microsoft didn't implement C99 in Visual Studio; but started adding it with
129// VS2013. However, VS2013 still didn't have snprintf(). The following is a
130// work-around.
131#define snprintf _snprintf
132#define STATIC_INLINE static
133// Microsoft also doesn't have basename(). Paths are different on Windows, and
134// so this is just a temporary solution in order to get us compiling, so that we
135// can test some scenarios, and develop the correct solution for Windows.
136 // TODO: Develop a better, permanent solution for Windows, to replace this
137 // temporary code:
138static char *basename(char *pathname)
139{
140 char *current, *next;
141
142#define DIRECTORY_SYMBOL '\\'
143
144// TODO/TBD: Do we need to deal with the Windows's ":" character?
145
146 for (current = pathname; *current != '\0'; current = next) {
147 next = strchr(current, DIRECTORY_SYMBOL);
148 if (next == NULL) {
149 // No more DIRECTORY_SYMBOL's so return p:
150 return current;
151 } else {
152 // Point one character past the DIRECTORY_SYMBOL:
153 next++;
154 }
155 }
156}
157
158// Dynamic Loading:
159typedef HMODULE loader_platform_dl_handle;
160static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
161{
162 return LoadLibrary(libPath);
163}
164static char * loader_platform_open_library_error(const char* libPath)
165{
166 static char errorMsg[120];
167 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
168 return errorMsg;
169}
170static void loader_platform_close_library(loader_platform_dl_handle library)
171{
172 FreeLibrary(library);
173}
174static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
175 const char *name)
176{
177 assert(library);
178 assert(name);
179 return GetProcAddress(library, name);
180}
181static char * loader_platform_get_proc_address_error(const char *name)
182{
183 static char errorMsg[120];
184 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
185 return errorMsg;
186}
187
188// Threads:
189typedef HANDLE loader_platform_thread;
190#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
191 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
192static void loader_platform_thread_once(void *ctl, void (* func) (void))
193{
194 assert(func != NULL);
195 assert(ctl != NULL);
196 InitOnceExecuteOnce((PINIT_ONCE) ctl, (PINIT_ONCE_FN) func, NULL, NULL);
197}
198
199// Thread IDs:
200typedef DWORD loader_platform_thread_id;
201static loader_platform_thread_id loader_platform_get_thread_id()
202{
203 return GetCurrentThreadId();
204}
205
206// Thread mutex:
207typedef CRITICAL_SECTION loader_platform_thread_mutex;
208static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
209{
210 InitializeCriticalSection(pMutex);
211}
212static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
213{
214 EnterCriticalSection(pMutex);
215}
216static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
217{
218 LeaveCriticalSection(pMutex);
219}
220static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
221{
222 DeleteCriticalSection(pMutex);
223}
224
225#else // defined(_WIN32)
226
227#error The "loader_platform.h" file must be modified for this OS.
228
229// NOTE: In order to support another OS, an #elif needs to be added (above the
230// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
231// contents of this file must be created.
232
233// NOTE: Other OS-specific changes are also needed for this OS. Search for
234// files with "WIN32" in it, as a quick way to find files that must be changed.
235
236#endif // defined(_WIN32)
237
238#endif /* LOADER_PLATFORM_H */