mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
ST: Use clock_gettime to prevent time jumping backwards. v7.0.17 (#3979)
try to fix #3978 **Background** check #3978 **Research** I referred the Android platform's solution, because I have android background, and there is a loop to handle message inside android.ff007a03c0/core/java/android/os/Handler.java (L701-L706C6)
``` public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } ```59d9dc1f50/libutils/SystemClock.cpp (L37-L51)
``` /* * native public static long uptimeMillis(); */ int64_t uptimeMillis() { return nanoseconds_to_milliseconds(uptimeNanos()); } /* * public static native long uptimeNanos(); */ int64_t uptimeNanos() { return systemTime(SYSTEM_TIME_MONOTONIC); } ```59d9dc1f50/libutils/Timers.cpp (L32-L55)
``` #if defined(__linux__) nsecs_t systemTime(int clock) { checkClockId(clock); static constexpr clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID, CLOCK_BOOTTIME}; static_assert(clock_id_max == arraysize(clocks)); timespec t = {}; clock_gettime(clocks[clock], &t); return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec; } #else nsecs_t systemTime(int clock) { // TODO: is this ever called with anything but REALTIME on mac/windows? checkClockId(clock); // Clock support varies widely across hosts. Mac OS doesn't support // CLOCK_BOOTTIME (and doesn't even have clock_gettime until 10.12). // Windows is windows. timeval t = {}; gettimeofday(&t, nullptr); return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL; } #endif ``` For Linux system, we can use `clock_gettime` api, but it's first appeared in Mac OSX 10.12. `man clock_gettime` The requirement is to find an alternative way to get the timestamp in microsecond unit, but the `clock_gettime` get nanoseconds, the math formula is the nanoseconds / 1000 = microsecond. Then I check the performance of this api + math division. I used those code to check the `clock_gettime` performance. ``` #include <sys/time.h> #include <time.h> #include <stdio.h> #include <unistd.h> int main() { struct timeval tv; struct timespec ts; clock_t start; clock_t end; long t; while (1) { start = clock(); gettimeofday(&tv, NULL); end = clock(); printf("gettimeofday clock is %lu\n", end - start); printf("gettimeofday is %lld\n", (tv.tv_sec * 1000000LL + tv.tv_usec)); start = clock(); clock_gettime(CLOCK_MONOTONIC, &ts); t = ts.tv_sec * 1000000L + ts.tv_nsec / 1000L; end = clock(); printf("clock_monotonic clock is %lu\n", end - start); printf("clock_monotonic: seconds is %ld, nanoseconds is %ld, sum is %ld\n", ts.tv_sec, ts.tv_nsec, t); start = clock(); clock_gettime(CLOCK_MONOTONIC_RAW, &ts); t = ts.tv_sec * 1000000L + ts.tv_nsec / 1000L; end = clock(); printf("clock_monotonic_raw clock is %lu\n", end - start); printf("clock_monotonic_raw: nanoseconds is %ld, sum is %ld\n", ts.tv_nsec, t); sleep(3); } return 0; } ``` Here is output: env: Mac OS M2 chip. ``` gettimeofday clock is 11 gettimeofday is 1709775727153949 clock_monotonic clock is 2 clock_monotonic: seconds is 1525204, nanoseconds is 409453000, sum is 1525204409453 clock_monotonic_raw clock is 2 clock_monotonic_raw: nanoseconds is 770493000, sum is 1525222770493 ``` We can see the `clock_gettime` is faster than `gettimeofday`, so there are no performance risks. **MacOS solution** `clock_gettime` api only available until mac os 10.12, for the mac os older than 10.12, just keep the `gettimeofday`. check osx version in `auto/options.sh`, then add MACRO in `auto/depends.sh`, the MACRO is `MD_OSX_HAS_NO_CLOCK_GETTIME`. **CYGWIN** According to google search, it seems the `clock_gettime(CLOCK_MONOTONIC)` is not support well at least 10 years ago, but I didn't own an windows machine, so can't verify it. so keep win's solution. --------- Co-authored-by: winlin <winlinvip@gmail.com>
This commit is contained in:
parent
0de887d374
commit
e7d78462fe
9 changed files with 168 additions and 15 deletions
|
@ -266,6 +266,9 @@ fi
|
|||
# for osx, use darwin for st, donot use epoll.
|
||||
if [[ $SRS_OSX == YES ]]; then
|
||||
_ST_MAKE=darwin-debug && _ST_OBJ="DARWIN_`uname -r`_DBG"
|
||||
if [[ $SRS_OSX_HAS_CLOCK_GETTIME != YES ]]; then
|
||||
_ST_EXTRA_CFLAGS="$_ST_EXTRA_CFLAGS -DMD_OSX_NO_CLOCK_GETTIME"
|
||||
fi
|
||||
fi
|
||||
# for windows/cygwin
|
||||
if [[ $SRS_CYGWIN64 = YES ]]; then
|
||||
|
|
|
@ -112,6 +112,8 @@ SRS_CROSS_BUILD_HOST=
|
|||
SRS_CROSS_BUILD_PREFIX=
|
||||
# For cache build
|
||||
SRS_BUILD_CACHE=YES
|
||||
# Only support MacOS 10.12+ for clock_gettime, see https://github.com/ossrs/srs/issues/3978
|
||||
SRS_OSX_HAS_CLOCK_GETTIME=YES
|
||||
#
|
||||
#####################################################################################
|
||||
# Toolchain for cross-build on Ubuntu for ARM or MIPS.
|
||||
|
@ -150,7 +152,9 @@ function apply_system_options() {
|
|||
OS_IS_RISCV=$(gcc -dM -E - </dev/null |grep -q '#define __riscv 1' && echo YES)
|
||||
|
||||
# Set the os option automatically.
|
||||
if [[ $OS_IS_OSX == YES ]]; then SRS_OSX=YES; fi
|
||||
if [[ $OS_IS_OSX == YES ]]; then
|
||||
SRS_OSX=YES;
|
||||
fi
|
||||
if [[ $OS_IS_CYGWIN == YES ]]; then SRS_CYGWIN64=YES; fi
|
||||
|
||||
if [[ $OS_IS_OSX == YES ]]; then SRS_JOBS=$(sysctl -n hw.ncpu 2>/dev/null || echo 1); fi
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue