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>