From 1d4338a0c8b0c2b6be4a21236bc254b5eec3e847 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Wed, 24 Mar 2021 11:21:55 +0100 Subject: [PATCH] [core] Added SRT_SYNC_CLOCK_TYPE preprocessor definition (#1885) --- docs/API-functions.md | 14 +++++++++----- srtcore/api.cpp | 2 ++ srtcore/sync.h | 41 ++++++++++++++++++++++++++++++++++++--- srtcore/sync_posix.cpp | 44 ++++++++++++++++++++++-------------------- 4 files changed, 72 insertions(+), 29 deletions(-) diff --git a/docs/API-functions.md b/docs/API-functions.md index 2f3b030b8..e00e2e74f 100644 --- a/docs/API-functions.md +++ b/docs/API-functions.md @@ -2492,7 +2492,7 @@ the sending to a stream with a handler function that will receive them. [:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) ---- +--- ### srt_setlogflags @@ -2513,6 +2513,9 @@ The following flags are available, as collected in the `logging_api.h` public he - `SRT_LOGF_DISABLE_SEVERITY`: Do not provide severity information in the header - `SRT_LOGF_DISABLE_EOL`: Do not add the end-of-line character to the log line +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- ## Time Access @@ -2578,7 +2581,6 @@ although it's highly recommended to use one of the above monotonic clocks, as system clock is vulnerable to time modifications during transmission. - [:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) @@ -2624,9 +2626,11 @@ and `msTimeStamp` value of the `SRT_TRACEBSTATS` (see [statistics.md](statistics | | | ---- +[:arrow_up:   Back to List of Functions & Structures](#srt-api-functions) + +--- - ## Diagnostics +## Diagnostics General notes concerning the `getlasterror` diagnostic functions: when an API function ends up with error, this error information is stored in a thread-local @@ -3221,7 +3225,7 @@ The operation timed out. This can happen if you have a timeout set by an option extra argument ([`srt_epoll_wait`](#srt_epoll_wait) or [`srt_accept_bond`](#srt_accept_bond)) and the function call was blocking, but the required timeout time has passed. - + #### `SRT_ECONGEST` **NOTE**: This error is used only in an experimental version that requires diff --git a/srtcore/api.cpp b/srtcore/api.cpp index f2bc0c709..4293d8021 100644 --- a/srtcore/api.cpp +++ b/srtcore/api.cpp @@ -287,6 +287,8 @@ int CUDTUnited::startup() m_bGCStatus = true; + HLOGC(inlog.Debug, log << "SRT Clock Type: " << SRT_SYNC_CLOCK_STR); + return 0; } diff --git a/srtcore/sync.h b/srtcore/sync.h index 85cb96047..271b15426 100644 --- a/srtcore/sync.h +++ b/srtcore/sync.h @@ -11,8 +11,15 @@ #ifndef INC_SRT_SYNC_H #define INC_SRT_SYNC_H -//#define ENABLE_STDCXX_SYNC -//#define ENABLE_CXX17 +// Possible internal clock types +#define SRT_SYNC_CLOCK_STDCXX_STEADY 0 // C++11 std::chrono::steady_clock +#define SRT_SYNC_CLOCK_GETTIME_MONOTONIC 1 // clock_gettime with CLOCK_MONOTONIC +#define SRT_SYNC_CLOCK_WINQPC 2 +#define SRT_SYNC_CLOCK_MACH_ABSTIME 3 +#define SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY 4 +#define SRT_SYNC_CLOCK_AMD64_RDTSC 5 +#define SRT_SYNC_CLOCK_IA32_RDTSC 6 +#define SRT_SYNC_CLOCK_IA64_ITC 7 #include #include @@ -21,9 +28,37 @@ #include #include #include +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_STDCXX_STEADY +#define SRT_SYNC_CLOCK_STR "STDCXX_STEADY" #else #include + +// Defile clock type to use +#ifdef IA32 +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA32_RDTSC +#define SRT_SYNC_CLOCK_STR "IA32_RDTSC" +#elif defined(IA64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_IA64_ITC +#define SRT_SYNC_CLOCK_STR "IA64_ITC" +#elif defined(AMD64) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_AMD64_RDTSC +#define SRT_SYNC_CLOCK_STR "AMD64_RDTSC" +#elif defined(_WIN32) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_WINQPC +#define SRT_SYNC_CLOCK_STR "WINQPC" +#elif TARGET_OS_MAC +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_MACH_ABSTIME +#define SRT_SYNC_CLOCK_STR "MACH_ABSTIME" +#elif defined(ENABLE_MONOTONIC_CLOCK) +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_GETTIME_MONOTONIC +#define SRT_SYNC_CLOCK_STR "GETTIME_MONOTONIC" +#else +#define SRT_SYNC_CLOCK SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY +#define SRT_SYNC_CLOCK_STR "POSIX_GETTIMEOFDAY" #endif + +#endif // ENABLE_STDCXX_SYNC + #include "utilities.h" class CUDTException; // defined in common.h @@ -773,7 +808,7 @@ namespace this_thread #if !defined(_WIN32) usleep(count_microseconds(t)); // microseconds #else - Sleep(count_milliseconds(t)); + Sleep((DWORD) count_milliseconds(t)); #endif } } diff --git a/srtcore/sync_posix.cpp b/srtcore/sync_posix.cpp index d40e23713..56a89d6b9 100644 --- a/srtcore/sync_posix.cpp +++ b/srtcore/sync_posix.cpp @@ -21,14 +21,10 @@ #include "common.h" #if defined(_WIN32) -#define TIMING_USE_QPC #include "win/wintime.h" #include #elif TARGET_OS_MAC -#define TIMING_USE_MACH_ABS_TIME #include -#elif defined(ENABLE_MONOTONIC_CLOCK) -#define TIMING_USE_CLOCK_GETTIME #endif namespace srt_logging @@ -44,7 +40,7 @@ namespace sync void rdtsc(uint64_t& x) { -#ifdef IA32 +#if SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_IA32_RDTSC uint32_t lval, hval; // asm volatile ("push %eax; push %ebx; push %ecx; push %edx"); // asm volatile ("xor %eax, %eax; cpuid"); @@ -52,30 +48,32 @@ void rdtsc(uint64_t& x) // asm volatile ("pop %edx; pop %ecx; pop %ebx; pop %eax"); x = hval; x = (x << 32) | lval; -#elif defined(IA64) +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_IA64_ITC asm("mov %0=ar.itc" : "=r"(x)::"memory"); -#elif defined(AMD64) +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_AMD64_RDTSC uint32_t lval, hval; asm("rdtsc" : "=a"(lval), "=d"(hval)); x = hval; x = (x << 32) | lval; -#elif defined(TIMING_USE_QPC) +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_WINQPC // This function should not fail, because we checked the QPC // when calling to QueryPerformanceFrequency. If it failed, // the m_bUseMicroSecond was set to true. QueryPerformanceCounter((LARGE_INTEGER*)&x); -#elif defined(TIMING_USE_MACH_ABS_TIME) +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_MACH_ABSTIME x = mach_absolute_time(); -#elif defined(TIMING_USE_CLOCK_GETTIME) +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_GETTIME_MONOTONIC // get_cpu_frequency() returns 1 us accuracy in this case timespec tm; clock_gettime(CLOCK_MONOTONIC, &tm); x = tm.tv_sec * uint64_t(1000000) + (tm.tv_nsec / 1000); -#else +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_POSIX_GETTIMEOFDAY // use system call to read time clock for other archs timeval t; gettimeofday(&t, 0); x = t.tv_sec * uint64_t(1000000) + t.tv_usec; +#else +#error Wrong SRT_SYNC_CLOCK #endif } @@ -83,21 +81,25 @@ int64_t get_cpu_frequency() { int64_t frequency = 1; // 1 tick per microsecond. -#if defined(TIMING_USE_QPC) +#if SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_WINQPC LARGE_INTEGER ccf; // in counts per second if (QueryPerformanceFrequency(&ccf)) + { frequency = ccf.QuadPart / 1000000; // counts per microsecond + } + else + { + // Can't throw an exception, it won't be handled. + LOGC(inlog.Error, log << "IPE: QueryPerformanceFrequency failed with " << GetLastError()); + } -#elif defined(TIMING_USE_CLOCK_GETTIME) - frequency = 1; - -#elif defined(TIMING_USE_MACH_ABS_TIME) - +#elif SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_MACH_ABSTIME mach_timebase_info_data_t info; mach_timebase_info(&info); frequency = info.denom * int64_t(1000) / info.numer; -#elif defined(IA32) || defined(IA64) || defined(AMD64) +#elif SRT_SYNC_CLOCK >= SRT_SYNC_CLOCK_AMD64_RDTSC && SRT_SYNC_CLOCK <= SRT_SYNC_CLOCK_IA64_ITC + // SRT_SYNC_CLOCK_AMD64_RDTSC or SRT_SYNC_CLOCK_IA32_RDTSC or SRT_SYNC_CLOCK_IA64_ITC uint64_t t1, t2; rdtsc(t1); @@ -287,7 +289,7 @@ Condition::~Condition() {} void Condition::init() { pthread_condattr_t* attr = NULL; -#if ENABLE_MONOTONIC_CLOCK +#if SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_GETTIME_MONOTONIC pthread_condattr_t CondAttribs; pthread_condattr_init(&CondAttribs); pthread_condattr_setclock(&CondAttribs, CLOCK_MONOTONIC); @@ -311,7 +313,7 @@ void Condition::wait(UniqueLock& lock) bool Condition::wait_for(UniqueLock& lock, const steady_clock::duration& rel_time) { timespec timeout; -#if ENABLE_MONOTONIC_CLOCK +#if SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_GETTIME_MONOTONIC clock_gettime(CLOCK_MONOTONIC, &timeout); const uint64_t now_us = timeout.tv_sec * uint64_t(1000000) + (timeout.tv_nsec / 1000); #else @@ -422,7 +424,7 @@ void srt::sync::CThread::join() #ifdef HEAVY_LOGGING else { - LOGC(inlog.Debug, log << "pthread_join SUCCEEDED"); + HLOGC(inlog.Debug, log << "pthread_join SUCCEEDED"); } #endif // After joining, joinable should be false