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
31
trunk/3rdparty/st-srs/md.h
vendored
31
trunk/3rdparty/st-srs/md.h
vendored
|
@ -101,10 +101,21 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
|
|||
#error Unknown CPU architecture
|
||||
#endif
|
||||
|
||||
#define MD_GET_UTIME() \
|
||||
struct timeval tv; \
|
||||
(void) gettimeofday(&tv, NULL); \
|
||||
return (tv.tv_sec * 1000000LL + tv.tv_usec)
|
||||
#if defined (MD_OSX_NO_CLOCK_GETTIME)
|
||||
#define MD_GET_UTIME() \
|
||||
struct timeval tv; \
|
||||
(void) gettimeofday(&tv, NULL); \
|
||||
return (tv.tv_sec * 1000000LL + tv.tv_usec)
|
||||
#else
|
||||
/*
|
||||
* https://github.com/ossrs/srs/issues/3978
|
||||
* use clock_gettime to get the timestamp in microseconds.
|
||||
*/
|
||||
#define MD_GET_UTIME() \
|
||||
struct timespec ts; \
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts); \
|
||||
return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000)
|
||||
#endif
|
||||
|
||||
#elif defined (LINUX)
|
||||
|
||||
|
@ -120,13 +131,13 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
|
|||
#define MD_HAVE_SOCKLEN_T
|
||||
|
||||
/*
|
||||
* All architectures and flavors of linux have the gettimeofday
|
||||
* function but if you know of a faster way, use it.
|
||||
* https://github.com/ossrs/srs/issues/3978
|
||||
* use clock_gettime to get the timestamp in microseconds.
|
||||
*/
|
||||
#define MD_GET_UTIME() \
|
||||
struct timeval tv; \
|
||||
(void) gettimeofday(&tv, NULL); \
|
||||
return (tv.tv_sec * 1000000LL + tv.tv_usec)
|
||||
#define MD_GET_UTIME() \
|
||||
struct timespec ts; \
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts); \
|
||||
return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000)
|
||||
|
||||
#if defined(__i386__)
|
||||
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[4]))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue