Atlas - SDL_systimer.c

Home / ext / SDL / src / timer / unix Lines: 1 | Size: 5309 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#ifdef SDL_TIMER_UNIX 24 25#include <stdio.h> 26#include <sys/time.h> 27#include <unistd.h> 28#include <errno.h> 29 30#include "../SDL_timer_c.h" 31 32#ifdef SDL_PLATFORM_EMSCRIPTEN 33#include <emscripten.h> 34#endif 35 36/* The clock_gettime provides monotonous time, so we should use it if 37 it's available. The clock_gettime function is behind ifdef 38 for __USE_POSIX199309 39 Tommi Kyntola ([email protected]) 27/09/2005 40*/ 41/* Reworked monotonic clock to not assume the current system has one 42 as not all linux kernels provide a monotonic clock (yeah recent ones 43 probably do) 44 Also added macOS Monotonic clock support 45 Based on work in https://github.com/ThomasHabets/monotonic_clock 46 */ 47#if defined(HAVE_NANOSLEEP) || defined(HAVE_CLOCK_GETTIME) 48#include <time.h> 49#endif 50#ifdef SDL_PLATFORM_APPLE 51#include <mach/mach_time.h> 52#endif 53 54// Use CLOCK_MONOTONIC_RAW, if available, which is not subject to adjustment by NTP 55#ifdef HAVE_CLOCK_GETTIME 56// Older Android phones have a buggy CLOCK_MONOTONIC_RAW, use CLOCK_MONOTONIC 57// See fix: https://github.com/torvalds/linux/commit/dbb236c1ceb697a559e0694ac4c9e7b9131d0b16 58#if defined(CLOCK_MONOTONIC_RAW) && !defined(__ANDROID__) 59#define SDL_MONOTONIC_CLOCK CLOCK_MONOTONIC_RAW 60#else 61#define SDL_MONOTONIC_CLOCK CLOCK_MONOTONIC 62#endif 63#endif 64 65// The first ticks value of the application 66#if !defined(HAVE_CLOCK_GETTIME) && defined(SDL_PLATFORM_APPLE) 67mach_timebase_info_data_t mach_base_info; 68#endif 69static bool checked_monotonic_time = false; 70static bool has_monotonic_time = false; 71 72static void CheckMonotonicTime(void) 73{ 74#ifdef HAVE_CLOCK_GETTIME 75 struct timespec value; 76 if (clock_gettime(SDL_MONOTONIC_CLOCK, &value) == 0) { 77 has_monotonic_time = true; 78 } 79#elif defined(SDL_PLATFORM_APPLE) 80 if (mach_timebase_info(&mach_base_info) == 0) { 81 has_monotonic_time = true; 82 } 83#endif 84 checked_monotonic_time = true; 85} 86 87Uint64 SDL_GetPerformanceCounter(void) 88{ 89 Uint64 ticks; 90 91 if (!checked_monotonic_time) { 92 CheckMonotonicTime(); 93 } 94 95 if (has_monotonic_time) { 96#ifdef HAVE_CLOCK_GETTIME 97 struct timespec now; 98 99 clock_gettime(SDL_MONOTONIC_CLOCK, &now); 100 ticks = now.tv_sec; 101 ticks *= SDL_NS_PER_SECOND; 102 ticks += now.tv_nsec; 103#elif defined(SDL_PLATFORM_APPLE) 104 ticks = mach_absolute_time(); 105#else 106 SDL_assert(false); 107 ticks = 0; 108#endif 109 } else { 110 struct timeval now; 111 112 gettimeofday(&now, NULL); 113 ticks = now.tv_sec; 114 ticks *= SDL_US_PER_SECOND; 115 ticks += now.tv_usec; 116 } 117 return ticks; 118} 119 120Uint64 SDL_GetPerformanceFrequency(void) 121{ 122 if (!checked_monotonic_time) { 123 CheckMonotonicTime(); 124 } 125 126 if (has_monotonic_time) { 127#ifdef HAVE_CLOCK_GETTIME 128 return SDL_NS_PER_SECOND; 129#elif defined(SDL_PLATFORM_APPLE) 130 Uint64 freq = mach_base_info.denom; 131 freq *= SDL_NS_PER_SECOND; 132 freq /= mach_base_info.numer; 133 return freq; 134#endif 135 } 136 137 return SDL_US_PER_SECOND; 138} 139 140void SDL_SYS_DelayNS(Uint64 ns) 141{ 142 int was_error; 143 144#ifdef HAVE_NANOSLEEP 145 struct timespec tv, remaining; 146#else 147 struct timeval tv; 148 Uint64 then, now, elapsed; 149#endif 150 151#ifdef SDL_PLATFORM_EMSCRIPTEN 152 if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, true)) { 153 // pseudo-synchronous pause, used directly or through e.g. SDL_WaitEvent 154 emscripten_sleep(ns / SDL_NS_PER_MS); 155 return; 156 } 157#endif 158 159 // Set the timeout interval 160#ifdef HAVE_NANOSLEEP 161 remaining.tv_sec = (time_t)(ns / SDL_NS_PER_SECOND); 162 remaining.tv_nsec = (long)(ns % SDL_NS_PER_SECOND); 163#else 164 then = SDL_GetTicksNS(); 165#endif 166 do { 167 errno = 0; 168 169#ifdef HAVE_NANOSLEEP 170 tv.tv_sec = remaining.tv_sec; 171 tv.tv_nsec = remaining.tv_nsec; 172 was_error = nanosleep(&tv, &remaining); 173#else 174 // Calculate the time interval left (in case of interrupt) 175 now = SDL_GetTicksNS(); 176 elapsed = (now - then); 177 then = now; 178 if (elapsed >= ns) { 179 break; 180 } 181 ns -= elapsed; 182 tv.tv_sec = (ns / SDL_NS_PER_SECOND); 183 tv.tv_usec = SDL_NS_TO_US(ns % SDL_NS_PER_SECOND); 184 185 was_error = select(0, NULL, NULL, NULL, &tv); 186#endif // HAVE_NANOSLEEP 187 } while (was_error && (errno == EINTR)); 188} 189 190#endif // SDL_TIMER_UNIX 191
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.