Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ST: Use clock_gettime to prevent time jumping backwards. v7.0.17 #3979

Merged
merged 5 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions trunk/3rdparty/st-srs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,9 @@ endif
# make EXTRA_CFLAGS=-UMD_HAVE_EPOLL <target>
#
# or to enable sendmmsg(2) support:
#
# make EXTRA_CFLAGS="-DMD_HAVE_SENDMMSG -D_GNU_SOURCE"
#
# or to enable stats for ST:
#
# make EXTRA_CFLAGS=-DDEBUG_STATS
#
# or cache the stack and reuse it:
Expand All @@ -201,6 +199,9 @@ endif
# or enable support for asan:
# make EXTRA_CFLAGS="-DMD_ASAN -fsanitize=address -fno-omit-frame-pointer"
#
# or to disable the clock_gettime for MacOS before 10.12, see https://github.com/ossrs/srs/issues/3978
# make EXTRA_CFLAGS=-DMD_OSX_NO_CLOCK_GETTIME
#
# or enable the coverage for utest:
# make UTEST_FLAGS="-fprofile-arcs -ftest-coverage"
#
Expand Down
31 changes: 21 additions & 10 deletions trunk/3rdparty/st-srs/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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]))
Expand Down
3 changes: 3 additions & 0 deletions trunk/auto/depends.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion trunk/auto/options.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion trunk/configure
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ if [[ $SRS_UTEST == YES ]]; then
MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_kernel" "srs_utest_core"
"srs_utest_config" "srs_utest_rtmp" "srs_utest_http" "srs_utest_avc" "srs_utest_reload"
"srs_utest_mp4" "srs_utest_service" "srs_utest_app" "srs_utest_rtc" "srs_utest_config2"
"srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2" "srs_utest_protocol3")
"srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2" "srs_utest_protocol3"
"srs_utest_st")
if [[ $SRS_SRT == YES ]]; then
MODULE_FILES+=("srs_utest_srt")
fi
Expand Down
1 change: 1 addition & 0 deletions trunk/doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v7-changes"></a>

## SRS 7.0 Changelog
* v7.0, 2024-10-15, Merge [#3979](https://github.com/ossrs/srs/pull/3979): ST: Use clock_gettime to prevent time jumping backwards. v7.0.17 (#3979)
* v7.0, 2024-09-09, Merge [#4158](https://github.com/ossrs/srs/pull/4158): Proxy: Support proxy server for SRS. v7.0.16 (#4158)
* v7.0, 2024-09-09, Merge [#4171](https://github.com/ossrs/srs/pull/4171): Heartbeat: Report ports for proxy server. v7.0.15 (#4171)
* v7.0, 2024-09-01, Merge [#4165](https://github.com/ossrs/srs/pull/4165): FLV: Refine source and http handler. v7.0.14 (#4165)
Expand Down
2 changes: 1 addition & 1 deletion trunk/src/core/srs_core_version7.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@

#define VERSION_MAJOR 7
#define VERSION_MINOR 0
#define VERSION_REVISION 16
#define VERSION_REVISION 17

#endif
117 changes: 117 additions & 0 deletions trunk/src/utest/srs_utest_st.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//
// Copyright (c) 2013-2024 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_utest_st.hpp>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

using namespace std;

VOID TEST(StTest, StUtimeInMicroseconds)
{
st_utime_t st_time_1 = st_utime();
// sleep 1 microsecond
#if !defined(SRS_CYGWIN64)
usleep(1);
#endif
st_utime_t st_time_2 = st_utime();

EXPECT_GT(st_time_1, 0);
EXPECT_GT(st_time_2, 0);
EXPECT_GE(st_time_2, st_time_1);
// st_time_2 - st_time_1 should be in range of [1, 100] microseconds
EXPECT_GE(st_time_2 - st_time_1, 0);
EXPECT_LE(st_time_2 - st_time_1, 100);
}

static inline st_utime_t time_gettimeofday() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000000LL + tv.tv_usec);
}

VOID TEST(StTest, StUtimePerformance)
{
clock_t start;
int gettimeofday_elapsed_time = 0;
int st_utime_elapsed_time = 0;

// Both the st_utime(clock_gettime or gettimeofday) and gettimeofday's
// elpased time to execute is dependence on whether it is the first time be called.
// In general, the gettimeofday has better performance, but the gap between
// them is really small, maybe less than 10 clock ~ 10 microseconds.

// check st_utime first, then gettimeofday
{
start = clock();
st_utime_t t2 = st_utime();
int elapsed_time = clock() - start;
st_utime_elapsed_time += elapsed_time;
EXPECT_GT(t2, 0);

start = clock();
st_utime_t t1 = time_gettimeofday();
elapsed_time = clock() - start;
gettimeofday_elapsed_time += elapsed_time;
EXPECT_GT(t1, 0);


EXPECT_GE(gettimeofday_elapsed_time, 0);
EXPECT_GE(st_utime_elapsed_time, 0);

// pass the test, if
EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
gettimeofday_elapsed_time - st_utime_elapsed_time :
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);
}

// check gettimeofday first, then st_utime
{
start = clock();
st_utime_t t1 = time_gettimeofday();
int elapsed_time = clock() - start;
gettimeofday_elapsed_time += elapsed_time;
EXPECT_GT(t1, 0);

start = clock();
st_utime_t t2 = st_utime();
elapsed_time = clock() - start;
st_utime_elapsed_time += elapsed_time;
EXPECT_GT(t2, 0);

EXPECT_GE(gettimeofday_elapsed_time, 0);
EXPECT_GE(st_utime_elapsed_time, 0);

EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
gettimeofday_elapsed_time - st_utime_elapsed_time :
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);
}

// compare st_utime & gettimeofday in a loop
for (int i = 0; i < 100; i++) {
start = clock();
st_utime_t t2 = st_utime();
int elapsed_time = clock() - start;
st_utime_elapsed_time = elapsed_time;
EXPECT_GT(t2, 0);
usleep(1);

start = clock();
st_utime_t t1 = time_gettimeofday();
elapsed_time = clock() - start;
gettimeofday_elapsed_time = elapsed_time;
EXPECT_GT(t1, 0);
usleep(1);

EXPECT_GE(gettimeofday_elapsed_time, 0);
EXPECT_GE(st_utime_elapsed_time, 0);

EXPECT_LT(gettimeofday_elapsed_time > st_utime_elapsed_time ?
gettimeofday_elapsed_time - st_utime_elapsed_time :
st_utime_elapsed_time - gettimeofday_elapsed_time, 10);

}
}
15 changes: 15 additions & 0 deletions trunk/src/utest/srs_utest_st.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Copyright (c) 2013-2024 The SRS Authors
//
// SPDX-License-Identifier: MIT
//

#ifndef SRS_UTEST_ST_HPP
#define SRS_UTEST_ST_HPP

#include <srs_utest.hpp>

#include <st.h>

#endif // SRS_UTEST_ST_HPP

Loading