Luanti 5.15.0-dev
 
Loading...
Searching...
No Matches
porting.h
Go to the documentation of this file.
1// Luanti
2// SPDX-License-Identifier: LGPL-2.1-or-later
3// Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5/*
6 Random portability stuff
7*/
8
9#pragma once
10
11#if (defined(__linux__) || defined(__GNU__)) && !defined(_GNU_SOURCE)
12 #define _GNU_SOURCE
13#endif
14
15// Be mindful of what you include here!
16#include <csignal>
17#include <string>
18#include "config.h"
19#include "irrlichttypes.h" // u64
20#include "debug.h"
21#include "util/timetaker.h" // TimePrecision
22
23#ifdef _MSC_VER
24 #define SWPRINTF_CHARSTRING L"%S"
25#else
26 #define SWPRINTF_CHARSTRING L"%s"
27#endif
28
29#ifdef _WIN32
30 #include <windows.h>
31
32 #define sleep_ms(x) Sleep(x)
33 #define sleep_us(x) Sleep((x)/1000)
34
35 #define SLEEP_ACCURACY_US 2000
36
37 #define setenv(n,v,o) _putenv_s(n,v)
38 #define unsetenv(n) _putenv_s(n,"")
39#else
40 #include <unistd.h>
41 #include <cstdlib> // setenv
42
43 #define SLEEP_ACCURACY_US 200
44
45 #define sleep_ms(x) usleep((x)*1000)
46 #define sleep_us(x) usleep(x)
47#endif
48
49#ifdef _MSC_VER
50 #define strtok_r(x, y, z) strtok_s(x, y, z)
51 #define strtof(x, y) (float)strtod(x, y)
52 #define strtoll(x, y, z) _strtoi64(x, y, z)
53 #define strtoull(x, y, z) _strtoui64(x, y, z)
54 #define strcasecmp(x, y) stricmp(x, y)
55 #define strncasecmp(x, y, n) strnicmp(x, y, n)
56#endif
57
58#if !HAVE_STRLCPY
59 #define strlcpy(d, s, n) mystrlcpy(d, s, n)
60#endif
61
62#ifndef _WIN32 // POSIX
63 #include <sys/time.h>
64 #include <ctime>
65 #if defined(__MACH__) && defined(__APPLE__)
66 #include <TargetConditionals.h>
67 #endif
68#endif
69
70namespace porting
71{
72
73/*
74 Signal handler (grabs Ctrl-C on POSIX systems)
75*/
76
78// Returns a pointer to a bool.
79// When the bool is true, program should quit.
80[[nodiscard]] volatile std::sig_atomic_t *signal_handler_killstatus();
81
82/*
83 Path of static data directory.
84*/
85extern std::string path_share;
86
87/*
88 Directory for storing user data. Examples:
89 Windows: "C:\Documents and Settings\user\Application Data<PROJECT_NAME>"
90 Linux: "~/.<PROJECT_NAME>"
91 Mac: "~/Library/Application Support/<PROJECT_NAME>"
92*/
93extern std::string path_user;
94
95/*
96 Path to gettext locale files
97*/
98extern std::string path_locale;
99
100/*
101 Path to directory for storing caches.
102*/
103extern std::string path_cache;
104
105/*
106 Gets the path of our executable.
107*/
108[[nodiscard]]
109bool getCurrentExecPath(char *buf, size_t len);
110
111/*
112 Concatenate subpath to path_share.
113*/
114[[nodiscard]]
115std::string getDataPath(const char *subpath);
116
117/*
118 Initialize path_*.
119*/
120void initializePaths();
121
122/*
123 Return system information
124 e.g. "Linux/3.12.7 x86_64"
125*/
126const std::string &get_sysinfo();
127
128
129/*
130 Return size of system RAM in MB
131 (or 0 if unavailable/error)
132*/
133u32 getMemorySizeMB();
134
135// Monotonic timer
136
137#ifdef _WIN32 // Windows
138
139extern double perf_freq;
140
141inline u64 os_get_time(double mult)
142{
143 LARGE_INTEGER t;
144 QueryPerformanceCounter(&t);
145 return static_cast<double>(t.QuadPart) / (perf_freq / mult);
146}
147
148// Resolution is <1us.
149inline u64 getTimeS() { return os_get_time(1); }
150inline u64 getTimeMs() { return os_get_time(1000); }
151inline u64 getTimeUs() { return os_get_time(1000*1000); }
152inline u64 getTimeNs() { return os_get_time(1000*1000*1000); }
153
154#else // POSIX
155
156inline void os_get_clock(struct timespec *ts)
157{
158#if defined(CLOCK_MONOTONIC_RAW)
159 clock_gettime(CLOCK_MONOTONIC_RAW, ts);
160#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK > 0
161 clock_gettime(CLOCK_MONOTONIC, ts);
162#else
163# if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK == 0
164 // zero means it might be supported at runtime
165 if (clock_gettime(CLOCK_MONOTONIC, ts) == 0)
166 return;
167# endif
168 struct timeval tv;
169 gettimeofday(&tv, NULL);
170 TIMEVAL_TO_TIMESPEC(&tv, ts);
171#endif
172}
173
174inline u64 getTimeS()
175{
176 struct timespec ts;
177 os_get_clock(&ts);
178 return ts.tv_sec;
179}
180
181inline u64 getTimeMs()
182{
183 struct timespec ts;
184 os_get_clock(&ts);
185 return ((u64) ts.tv_sec) * 1000LL + ((u64) ts.tv_nsec) / 1000000LL;
186}
187
188inline u64 getTimeUs()
189{
190 struct timespec ts;
191 os_get_clock(&ts);
192 return ((u64) ts.tv_sec) * 1000000LL + ((u64) ts.tv_nsec) / 1000LL;
193}
194
195inline u64 getTimeNs()
196{
197 struct timespec ts;
198 os_get_clock(&ts);
199 return ((u64) ts.tv_sec) * 1000000000LL + ((u64) ts.tv_nsec);
200}
201
202#endif
203
204inline u64 getTime(TimePrecision prec)
205{
206 switch (prec) {
207 case PRECISION_SECONDS: return getTimeS();
208 case PRECISION_MILLI: return getTimeMs();
209 case PRECISION_MICRO: return getTimeUs();
210 case PRECISION_NANO: return getTimeNs();
211 }
212 FATAL_ERROR("Called getTime with invalid time precision");
213}
214
221inline u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms)
222{
223 if (new_time_ms >= old_time_ms) {
224 return (new_time_ms - old_time_ms);
225 }
226
227 return (old_time_ms - new_time_ms);
228}
229
230inline void preciseSleepUs(u64 sleep_time)
231{
232 if (sleep_time > 0)
233 {
234 u64 target_time = porting::getTimeUs() + sleep_time;
235 if (sleep_time > SLEEP_ACCURACY_US)
236 sleep_us(sleep_time - SLEEP_ACCURACY_US);
237
238 // Busy-wait the remaining time to adjust for sleep inaccuracies
239 // The target - now > 0 construct will handle overflow gracefully (even though it should
240 // never happen)
241 while ((s64)(target_time - porting::getTimeUs()) > 0) {}
242 }
243}
244
245inline const char *getPlatformName()
246{
247 return
248#if defined(ANDROID)
249 "Android"
250#elif defined(__linux__)
251 "Linux"
252#elif defined(_WIN32) || defined(_WIN64)
253 "Windows"
254#elif defined(__DragonFly__) || defined(__FreeBSD__) || \
255 defined(__NetBSD__) || defined(__OpenBSD__)
256 "BSD"
257#elif defined(__APPLE__) && defined(__MACH__)
258 #if TARGET_OS_MAC
259 "OSX"
260 #elif TARGET_OS_IPHONE
261 "iOS"
262 #else
263 "Apple"
264 #endif
265#elif defined(_AIX)
266 "AIX"
267#elif defined(__hpux)
268 "HP-UX"
269#elif defined(__sun) || defined(sun)
270 #if defined(__SVR4)
271 "Solaris"
272 #else
273 "SunOS"
274 #endif
275#elif defined(__HAIKU__)
276 "Haiku"
277#elif defined(__CYGWIN__)
278 "Cygwin"
279#elif defined(__unix__) || defined(__unix)
280 #if defined(_POSIX_VERSION)
281 "POSIX"
282 #else
283 "Unix"
284 #endif
285#else
286 "?"
287#endif
288 ;
289}
290
291// Securely fills buffer with bytes from system's random source
292[[nodiscard]] bool secure_rand_fill_buf(void *buf, size_t len);
293
294// Call once near beginning of main function.
295void osSpecificInit();
296
297// This attaches to the parents process console, or creates a new one if it doesnt exist.
299
300#if HAVE_MALLOC_TRIM
306void TrackFreedMemory(size_t amount);
307
312void TriggerMemoryTrim();
313#else
314static inline void TrackFreedMemory(size_t amount) { (void)amount; }
315static inline void TriggerMemoryTrim() { (void)0; }
316#endif
317
318#ifdef _WIN32
319// Quotes an argument for use in a CreateProcess() commandline (not cmd.exe!!)
320[[nodiscard]] std::string QuoteArgv(const std::string &arg);
321
322// Convert an error code (e.g. from GetLastError()) into a string.
323[[nodiscard]] std::string ConvertError(DWORD error_code);
324#endif
325
326// snprintf wrapper
327int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...);
328
337bool open_url(const std::string &url);
338
347bool open_directory(const std::string &path);
348
349} // namespace porting
350
351#ifdef __ANDROID__
352#include "porting_android.h"
353#endif
#define FATAL_ERROR(msg)
Definition debug.h:32
Definition porting.cpp:85
u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms)
Delta calculation function arguments.
Definition porting.h:221
std::string path_locale
Definition porting.cpp:164
bool secure_rand_fill_buf(void *buf, size_t len)
Definition porting.cpp:761
u32 getMemorySizeMB()
Definition porting.cpp:274
std::string path_share
Definition porting.cpp:162
volatile std::sig_atomic_t * signal_handler_killstatus()
Definition porting.cpp:93
int mt_snprintf(char *buf, const size_t buf_size, const char *fmt,...)
Definition porting.cpp:857
void os_get_clock(struct timespec *ts)
Definition porting.h:156
void signal_handler_init(void)
Definition porting.cpp:118
void osSpecificInit()
Definition porting.cpp:782
static void TrackFreedMemory(size_t amount)
Definition porting.h:314
bool open_directory(const std::string &path)
Opens a directory in the default file manager.
Definition porting.cpp:916
u64 getTimeS()
Definition porting.h:174
std::string path_cache
Definition porting.cpp:165
std::string path_user
Definition porting.cpp:163
u64 getTime(TimePrecision prec)
Definition porting.h:204
u64 getTimeMs()
Definition porting.h:181
bool open_url(const std::string &url)
Opens URL in default web browser.
Definition porting.cpp:906
u64 getTimeNs()
Definition porting.h:195
const char * getPlatformName()
Definition porting.h:245
bool getCurrentExecPath(char *buf, size_t len)
Definition porting.cpp:427
std::string getDataPath(const char *subpath)
Definition porting.cpp:168
void initializePaths()
Definition porting.cpp:631
void attachOrCreateConsole()
Definition porting.cpp:795
void preciseSleepUs(u64 sleep_time)
Definition porting.h:230
static void TriggerMemoryTrim()
Definition porting.h:315
u64 getTimeUs()
Definition porting.h:188
const std::string & get_sysinfo()
Definition porting.cpp:268
#define sleep_us(x)
Definition porting.h:46
#define SLEEP_ACCURACY_US
Definition porting.h:43
TimePrecision
Definition timetaker.h:11
@ PRECISION_SECONDS
Definition timetaker.h:12
@ PRECISION_NANO
Definition timetaker.h:15
@ PRECISION_MICRO
Definition timetaker.h:14
@ PRECISION_MILLI
Definition timetaker.h:13