Fix problem with newer MinGW runtimes
[oweals/minetest.git] / src / porting.h
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 "irrlichttypes.h" // u32
37 #include "debug.h"
38 #include "constants.h"
39 #include "gettime.h"
40 #include "threads.h"
41
42 #ifdef _MSC_VER
43         #define SWPRINTF_CHARSTRING L"%S"
44 #else
45         #define SWPRINTF_CHARSTRING L"%s"
46 #endif
47
48 //currently not needed
49 //template<typename T> struct alignment_trick { char c; T member; };
50 //#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
51
52 #ifdef _WIN32
53         #include <windows.h>
54         
55         #define sleep_ms(x) Sleep(x)
56 #else
57         #include <unistd.h>
58         #include <stdint.h> //for uintptr_t
59         
60         #if (defined(linux) || defined(__linux)) && !defined(_GNU_SOURCE)
61                 #define _GNU_SOURCE
62         #endif
63
64         #include <sched.h>
65
66         #ifdef __FreeBSD__
67                 #include <pthread_np.h>
68                 typedef cpuset_t cpu_set_t;
69         #elif defined(__sun) || defined(sun)
70                 #include <sys/types.h>
71                 #include <sys/processor.h>
72         #elif defined(_AIX)
73                 #include <sys/processor.h>
74         #elif __APPLE__
75                 #include <mach/mach_init.h>
76                 #include <mach/thread_policy.h>
77         #endif
78
79         #define sleep_ms(x) usleep(x*1000)
80         
81         #define THREAD_PRIORITY_LOWEST       0
82         #define THREAD_PRIORITY_BELOW_NORMAL 1
83         #define THREAD_PRIORITY_NORMAL       2
84         #define THREAD_PRIORITY_ABOVE_NORMAL 3
85         #define THREAD_PRIORITY_HIGHEST      4
86 #endif
87
88 #ifdef _MSC_VER
89         #define ALIGNOF(x) __alignof(x)
90         #define strtok_r(x, y, z) strtok_s(x, y, z)
91         #define strtof(x, y) (float)strtod(x, y)
92         #define strtoll(x, y, z) _strtoi64(x, y, z)
93         #define strtoull(x, y, z) _strtoui64(x, y, z)
94         #define strcasecmp(x, y) stricmp(x, y)
95         #define strncasecmp(x, y, n) strnicmp(x, y, n)
96 #else
97         #define ALIGNOF(x) __alignof__(x)
98 #endif
99
100 #ifdef __MINGW32__
101         #define strtok_r(x, y, z) mystrtok_r(x, y, z)
102 #endif
103
104 // strlcpy is missing from glibc.  thanks a lot, drepper.
105 // strlcpy is also missing from AIX and HP-UX because they aim to be weird.
106 // We can't simply alias strlcpy to MSVC's strcpy_s, since strcpy_s by
107 // default raises an assertion error and aborts the program if the buffer is
108 // too small.
109 #if defined(__FreeBSD__) || defined(__NetBSD__)    || \
110         defined(__OpenBSD__) || defined(__DragonFly__) || \
111         defined(__APPLE__)   ||                           \
112         defined(__sun)       || defined(sun)           || \
113         defined(__QNX__)     || defined(__QNXNTO__)
114         #define HAVE_STRLCPY
115 #endif
116
117 // So we need to define our own.
118 #ifndef HAVE_STRLCPY
119         #define strlcpy(d, s, n) mystrlcpy(d, s, n)
120 #endif
121
122 #define PADDING(x, y) ((ALIGNOF(y) - ((uintptr_t)(x) & (ALIGNOF(y) - 1))) & (ALIGNOF(y) - 1))
123
124 namespace porting
125 {
126
127 /*
128         Signal handler (grabs Ctrl-C on POSIX systems)
129 */
130
131 void signal_handler_init(void);
132 // Returns a pointer to a bool.
133 // When the bool is true, program should quit.
134 bool * signal_handler_killstatus(void);
135
136 /*
137         Path of static data directory.
138 */
139 extern std::string path_share;
140
141 /*
142         Directory for storing user data. Examples:
143         Windows: "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
144         Linux: "~/.<PROJECT_NAME>"
145         Mac: "~/Library/Application Support/<PROJECT_NAME>"
146 */
147 extern std::string path_user;
148
149 /*
150         Get full path of stuff in data directory.
151         Example: "stone.png" -> "../data/stone.png"
152 */
153 std::string getDataPath(const char *subpath);
154
155 /*
156         Initialize path_share and path_user.
157 */
158 void initializePaths();
159
160 /*
161         Get number of online processors in the system.
162 */
163 int getNumberOfProcessors();
164
165 /*
166         Set a thread's affinity to a particular processor.
167 */
168 bool threadBindToProcessor(threadid_t tid, int pnumber);
169
170 /*
171         Set a thread's priority.
172 */
173 bool threadSetPriority(threadid_t tid, int prio);
174
175 /*
176         Return system information
177         e.g. "Linux/3.12.7 x86_64"
178 */
179 std::string get_sysinfo();
180
181 /*
182         Resolution is 10-20ms.
183         Remember to check for overflows.
184         Overflow can occur at any value higher than 10000000.
185 */
186 #ifdef _WIN32 // Windows
187 #ifndef _WIN32_WINNT
188         #define _WIN32_WINNT 0x0501
189 #endif
190         #include <windows.h>
191         
192         inline u32 getTimeS()
193         {
194                 return GetTickCount() / 1000;
195         }
196         
197         inline u32 getTimeMs()
198         {
199                 return GetTickCount();
200         }
201         
202         inline u32 getTimeUs()
203         {
204                 LARGE_INTEGER freq, t;
205                 QueryPerformanceFrequency(&freq);
206                 QueryPerformanceCounter(&t);
207                 return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000.0);
208         }
209         
210         inline u32 getTimeNs()
211         {
212                 LARGE_INTEGER freq, t;
213                 QueryPerformanceFrequency(&freq);
214                 QueryPerformanceCounter(&t);
215                 return (double)(t.QuadPart) / ((double)(freq.QuadPart) / 1000000000.0);
216         }
217         
218 #else // Posix
219         #include <sys/time.h>
220         #include <time.h>
221         
222         inline u32 getTimeS()
223         {
224                 struct timeval tv;
225                 gettimeofday(&tv, NULL);
226                 return tv.tv_sec;
227         }
228         
229         inline u32 getTimeMs()
230         {
231                 struct timeval tv;
232                 gettimeofday(&tv, NULL);
233                 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
234         }
235         
236         inline u32 getTimeUs()
237         {
238                 struct timeval tv;
239                 gettimeofday(&tv, NULL);
240                 return tv.tv_sec * 1000000 + tv.tv_usec;
241         }
242         
243         inline u32 getTimeNs()
244         {
245                 struct timespec ts;
246                 clock_gettime(CLOCK_REALTIME, &ts);
247                 return ts.tv_sec * 1000000000 + ts.tv_nsec;
248         }
249         
250         /*#include <sys/timeb.h>
251         inline u32 getTimeMs()
252         {
253                 struct timeb tb;
254                 ftime(&tb);
255                 return tb.time * 1000 + tb.millitm;
256         }*/
257 #endif
258
259 inline u32 getTime(TimePrecision prec)
260 {
261         switch (prec) {
262                 case PRECISION_SECONDS:
263                         return getTimeS();
264                 case PRECISION_MILLI:
265                         return getTimeMs();
266                 case PRECISION_MICRO:
267                         return getTimeUs();
268                 case PRECISION_NANO:
269                         return getTimeNs();
270         }
271         return 0;
272 }
273
274 #if (defined(linux) || defined(__linux))
275
276 #include <sys/prctl.h>
277
278 inline void setThreadName(const char* name) {
279         prctl(PR_SET_NAME,name);
280 }
281 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
282 /* BSD doesn't seem to support thread names. If you know about a way 
283  * to add this feature please create a pull request.
284  * "setproctitle" doesn't work for threadnames.
285  */
286 inline void setThreadName(const char* name) {}
287 #elif defined(_WIN32)
288 // threadnames are not supported on windows
289 inline void setThreadName(const char* name) {}
290 #else
291 #warning "Unknown platform for setThreadName support, you wont have threadname support."
292 inline void setThreadName(const char* name) {}
293 #endif
294
295 } // namespace porting
296
297 #endif // PORTING_HEADER
298