Line data Source code
1 : /*
2 : Minetest
3 : Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 :
5 : This program is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU Lesser General Public License as published by
7 : the Free Software Foundation; either version 2.1 of the License, or
8 : (at your option) any later version.
9 :
10 : This program is distributed in the hope that it will be useful,
11 : but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU Lesser General Public License for more details.
14 :
15 : You should have received a copy of the GNU Lesser General Public License along
16 : with this program; if not, write to the Free Software Foundation, Inc.,
17 : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : /*
21 : Random portability stuff
22 : */
23 :
24 : #ifndef PORTING_HEADER
25 : #define PORTING_HEADER
26 :
27 : #ifdef _WIN32
28 : #ifdef _WIN32_WINNT
29 : #undef _WIN32_WINNT
30 : #endif
31 : #define _WIN32_WINNT 0x0501 // We need to do this before any other headers
32 : // because those might include sdkddkver.h which defines _WIN32_WINNT if not already set
33 : #endif
34 :
35 : #include <string>
36 : #include <vector>
37 : #include "irrlicht.h"
38 : #include "irrlichttypes.h" // u32
39 : #include "irrlichttypes_extrabloated.h"
40 : #include "debug.h"
41 : #include "constants.h"
42 : #include "gettime.h"
43 : #include "threads.h"
44 :
45 : #ifdef _MSC_VER
46 : #define SWPRINTF_CHARSTRING L"%S"
47 : #else
48 : #define SWPRINTF_CHARSTRING L"%s"
49 : #endif
50 :
51 : //currently not needed
52 : //template<typename T> struct alignment_trick { char c; T member; };
53 : //#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
54 :
55 : #ifdef _WIN32
56 : #include <windows.h>
57 :
58 : #define sleep_ms(x) Sleep(x)
59 : #else
60 : #include <unistd.h>
61 : #include <stdint.h> //for uintptr_t
62 :
63 : #if (defined(linux) || defined(__linux) || defined(__GNU__)) && !defined(_GNU_SOURCE)
64 : #define _GNU_SOURCE
65 : #endif
66 :
67 : #include <sched.h>
68 :
69 : #ifdef __FreeBSD__
70 : #include <pthread_np.h>
71 : typedef cpuset_t cpu_set_t;
72 : #elif defined(__sun) || defined(sun)
73 : #include <sys/types.h>
74 : #include <sys/processor.h>
75 : #elif defined(_AIX)
76 : #include <sys/processor.h>
77 : #elif __APPLE__
78 : #include <mach/mach_init.h>
79 : #include <mach/thread_policy.h>
80 : #endif
81 :
82 : #define sleep_ms(x) usleep(x*1000)
83 :
84 : #define THREAD_PRIORITY_LOWEST 0
85 : #define THREAD_PRIORITY_BELOW_NORMAL 1
86 : #define THREAD_PRIORITY_NORMAL 2
87 : #define THREAD_PRIORITY_ABOVE_NORMAL 3
88 : #define THREAD_PRIORITY_HIGHEST 4
89 : #endif
90 :
91 : #ifdef _MSC_VER
92 : #define ALIGNOF(x) __alignof(x)
93 : #define strtok_r(x, y, z) strtok_s(x, y, z)
94 : #define strtof(x, y) (float)strtod(x, y)
95 : #define strtoll(x, y, z) _strtoi64(x, y, z)
96 : #define strtoull(x, y, z) _strtoui64(x, y, z)
97 : #define strcasecmp(x, y) stricmp(x, y)
98 : #define strncasecmp(x, y, n) strnicmp(x, y, n)
99 : #else
100 : #define ALIGNOF(x) __alignof__(x)
101 : #endif
102 :
103 : #ifdef __MINGW32__
104 : #define strtok_r(x, y, z) mystrtok_r(x, y, z)
105 : #endif
106 :
107 : // strlcpy is missing from glibc. thanks a lot, drepper.
108 : // strlcpy is also missing from AIX and HP-UX because they aim to be weird.
109 : // We can't simply alias strlcpy to MSVC's strcpy_s, since strcpy_s by
110 : // default raises an assertion error and aborts the program if the buffer is
111 : // too small.
112 : #if defined(__FreeBSD__) || defined(__NetBSD__) || \
113 : defined(__OpenBSD__) || defined(__DragonFly__) || \
114 : defined(__APPLE__) || \
115 : defined(__sun) || defined(sun) || \
116 : defined(__QNX__) || defined(__QNXNTO__)
117 : #define HAVE_STRLCPY
118 : #endif
119 :
120 : // So we need to define our own.
121 : #ifndef HAVE_STRLCPY
122 : #define strlcpy(d, s, n) mystrlcpy(d, s, n)
123 : #endif
124 :
125 : #define PADDING(x, y) ((ALIGNOF(y) - ((uintptr_t)(x) & (ALIGNOF(y) - 1))) & (ALIGNOF(y) - 1))
126 :
127 : #if defined(__APPLE__)
128 : #include <mach-o/dyld.h>
129 : #include <CoreFoundation/CoreFoundation.h>
130 : #endif
131 :
132 : namespace porting
133 : {
134 :
135 : /*
136 : Signal handler (grabs Ctrl-C on POSIX systems)
137 : */
138 :
139 : void signal_handler_init(void);
140 : // Returns a pointer to a bool.
141 : // When the bool is true, program should quit.
142 : bool * signal_handler_killstatus(void);
143 :
144 : /*
145 : Path of static data directory.
146 : */
147 : extern std::string path_share;
148 :
149 : /*
150 : Directory for storing user data. Examples:
151 : Windows: "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
152 : Linux: "~/.<PROJECT_NAME>"
153 : Mac: "~/Library/Application Support/<PROJECT_NAME>"
154 : */
155 : extern std::string path_user;
156 :
157 : /*
158 : Get full path of stuff in data directory.
159 : Example: "stone.png" -> "../data/stone.png"
160 : */
161 : std::string getDataPath(const char *subpath);
162 :
163 : /*
164 : Initialize path_share and path_user.
165 : */
166 : void initializePaths();
167 :
168 : /*
169 : Get number of online processors in the system.
170 : */
171 : int getNumberOfProcessors();
172 :
173 : /*
174 : Set a thread's affinity to a particular processor.
175 : */
176 : bool threadBindToProcessor(threadid_t tid, int pnumber);
177 :
178 : /*
179 : Set a thread's priority.
180 : */
181 : bool threadSetPriority(threadid_t tid, int prio);
182 :
183 : /*
184 : Return system information
185 : e.g. "Linux/3.12.7 x86_64"
186 : */
187 : std::string get_sysinfo();
188 :
189 : void initIrrlicht(irr::IrrlichtDevice * );
190 :
191 : /*
192 : Resolution is 10-20ms.
193 : Remember to check for overflows.
194 : Overflow can occur at any value higher than 10000000.
195 : */
196 : #ifdef _WIN32 // Windows
197 : #ifndef _WIN32_WINNT
198 : #define _WIN32_WINNT 0x0501
199 : #endif
200 : #include <windows.h>
201 :
202 : inline u32 getTimeS()
203 : {
204 : return GetTickCount() / 1000;
205 : }
206 :
207 : inline u32 getTimeMs()
208 : {
209 : return GetTickCount();
210 : }
211 :
212 : inline u32 getTimeUs()
213 : {
214 : LARGE_INTEGER freq, t;
215 : QueryPerformanceFrequency(&freq);
216 : QueryPerformanceCounter(&t);
217 : return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000.0);
218 : }
219 :
220 : inline u32 getTimeNs()
221 : {
222 : LARGE_INTEGER freq, t;
223 : QueryPerformanceFrequency(&freq);
224 : QueryPerformanceCounter(&t);
225 : return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000000.0);
226 : }
227 :
228 : #else // Posix
229 : #include <sys/time.h>
230 : #include <time.h>
231 : #if defined(__MACH__) && defined(__APPLE__)
232 : #include <mach/clock.h>
233 : #include <mach/mach.h>
234 : #endif
235 :
236 0 : inline u32 getTimeS()
237 : {
238 : struct timeval tv;
239 0 : gettimeofday(&tv, NULL);
240 0 : return tv.tv_sec;
241 : }
242 :
243 1438167 : inline u32 getTimeMs()
244 : {
245 : struct timeval tv;
246 1438167 : gettimeofday(&tv, NULL);
247 1438167 : return tv.tv_sec * 1000 + tv.tv_usec / 1000;
248 : }
249 :
250 0 : inline u32 getTimeUs()
251 : {
252 : struct timeval tv;
253 0 : gettimeofday(&tv, NULL);
254 0 : return tv.tv_sec * 1000000 + tv.tv_usec;
255 : }
256 :
257 0 : inline u32 getTimeNs()
258 : {
259 : struct timespec ts;
260 : // from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
261 : #if defined(__MACH__) && defined(__APPLE__) // OS X does not have clock_gettime, use clock_get_time
262 : clock_serv_t cclock;
263 : mach_timespec_t mts;
264 : host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
265 : clock_get_time(cclock, &mts);
266 : mach_port_deallocate(mach_task_self(), cclock);
267 : ts.tv_sec = mts.tv_sec;
268 : ts.tv_nsec = mts.tv_nsec;
269 : #else
270 0 : clock_gettime(CLOCK_REALTIME, &ts);
271 : #endif
272 0 : return ts.tv_sec * 1000000000 + ts.tv_nsec;
273 : }
274 :
275 : /*#include <sys/timeb.h>
276 : inline u32 getTimeMs()
277 : {
278 : struct timeb tb;
279 : ftime(&tb);
280 : return tb.time * 1000 + tb.millitm;
281 : }*/
282 : #endif
283 :
284 0 : inline u32 getTime(TimePrecision prec)
285 : {
286 0 : switch (prec) {
287 : case PRECISION_SECONDS:
288 0 : return getTimeS();
289 : case PRECISION_MILLI:
290 0 : return getTimeMs();
291 : case PRECISION_MICRO:
292 0 : return getTimeUs();
293 : case PRECISION_NANO:
294 0 : return getTimeNs();
295 : }
296 0 : return 0;
297 : }
298 :
299 : /**
300 : * Delta calculation function taking two 32bit arguments.
301 : * @param old_time_ms old time for delta calculation (order is relevant!)
302 : * @param new_time_ms new time for delta calculation (order is relevant!)
303 : * @return positive 32bit delta value
304 : */
305 51 : inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms)
306 : {
307 51 : if (new_time_ms >= old_time_ms) {
308 51 : return (new_time_ms - old_time_ms);
309 : } else {
310 0 : return (old_time_ms - new_time_ms);
311 : }
312 : }
313 :
314 : #if defined(linux) || defined(__linux)
315 : #include <sys/prctl.h>
316 :
317 8 : inline void setThreadName(const char *name) {
318 : /* It would be cleaner to do this with pthread_setname_np,
319 : * which was added to glibc in version 2.12, but some major
320 : * distributions are still runing 2.11 and previous versions.
321 : */
322 8 : prctl(PR_SET_NAME, name);
323 8 : }
324 : #elif defined(__FreeBSD__) || defined(__OpenBSD__)
325 : #include <pthread.h>
326 : #include <pthread_np.h>
327 :
328 : inline void setThreadName(const char *name) {
329 : pthread_set_name_np(pthread_self(), name);
330 : }
331 : #elif defined(__NetBSD__)
332 : #include <pthread.h>
333 :
334 : inline void setThreadName(const char *name) {
335 : pthread_setname_np(pthread_self(), name);
336 : }
337 : #elif defined(_MSC_VER)
338 : typedef struct tagTHREADNAME_INFO {
339 : DWORD dwType; // must be 0x1000
340 : LPCSTR szName; // pointer to name (in user addr space)
341 : DWORD dwThreadID; // thread ID (-1=caller thread)
342 : DWORD dwFlags; // reserved for future use, must be zero
343 : } THREADNAME_INFO;
344 :
345 : inline void setThreadName(const char *name) {
346 : THREADNAME_INFO info;
347 : info.dwType = 0x1000;
348 : info.szName = name;
349 : info.dwThreadID = -1;
350 : info.dwFlags = 0;
351 : __try {
352 : RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *) &info);
353 : } __except (EXCEPTION_CONTINUE_EXECUTION) {}
354 : }
355 : #elif defined(__APPLE__)
356 : #include <pthread.h>
357 :
358 : inline void setThreadName(const char *name) {
359 : pthread_setname_np(name);
360 : }
361 : #elif defined(_WIN32) || defined(__GNU__)
362 : inline void setThreadName(const char* name) {}
363 : #else
364 : #warning "Unrecognized platform, thread names will not be available."
365 : inline void setThreadName(const char* name) {}
366 : #endif
367 :
368 : #ifndef SERVER
369 : float getDisplayDensity();
370 :
371 : v2u32 getDisplaySize();
372 : v2u32 getWindowSize();
373 :
374 : std::vector<core::vector3d<u32> > getSupportedVideoModes();
375 : std::vector<irr::video::E_DRIVER_TYPE> getSupportedVideoDrivers();
376 : const char *getVideoDriverName(irr::video::E_DRIVER_TYPE type);
377 : const char *getVideoDriverFriendlyName(irr::video::E_DRIVER_TYPE type);
378 : #endif
379 :
380 5 : inline const char *getPlatformName()
381 : {
382 : return
383 : #if defined(ANDROID)
384 : "Android"
385 : #elif defined(linux) || defined(__linux) || defined(__linux__)
386 5 : "Linux"
387 : #elif defined(_WIN32) || defined(_WIN64)
388 : "Windows"
389 : #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
390 : defined(__NetBSD__) || defined(__OpenBSD__)
391 : "BSD"
392 : #elif defined(__APPLE__) && defined(__MACH__)
393 : #if TARGET_OS_MAC
394 : "OSX"
395 : #elif TARGET_OS_IPHONE
396 : "iOS"
397 : #else
398 : "Apple"
399 : #endif
400 : #elif defined(_AIX)
401 : "AIX"
402 : #elif defined(__hpux)
403 : "HP-UX"
404 : #elif defined(__sun) || defined(sun)
405 : #if defined(__SVR4)
406 : "Solaris"
407 : #else
408 : "SunOS"
409 : #endif
410 : #elif defined(__CYGWIN__)
411 : "Cygwin"
412 : #elif defined(__unix__) || defined(__unix)
413 : #if defined(_POSIX_VERSION)
414 : "Posix"
415 : #else
416 : "Unix"
417 : #endif
418 : #else
419 : "?"
420 : #endif
421 : ;
422 : }
423 :
424 : void setXorgClassHint(const video::SExposedVideoData &video_data,
425 : const std::string &name);
426 :
427 : // This only needs to be called at the start of execution, since all future
428 : // threads in the process inherit this exception handler
429 : void setWin32ExceptionHandler();
430 :
431 : } // namespace porting
432 :
433 : #ifdef __ANDROID__
434 : #include "porting_android.h"
435 : #endif
436 :
437 : #endif // PORTING_HEADER
438 :
|