github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/vdso_clock_gettime.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <stdint.h> 16 #include <sys/time.h> 17 #include <syscall.h> 18 #include <time.h> 19 #include <unistd.h> 20 21 #include <map> 22 #include <string> 23 #include <utility> 24 25 #include "gmock/gmock.h" 26 #include "gtest/gtest.h" 27 #include "absl/strings/numbers.h" 28 #include "absl/time/clock.h" 29 #include "absl/time/time.h" 30 #include "test/util/test_util.h" 31 32 namespace gvisor { 33 namespace testing { 34 35 namespace { 36 37 std::string PrintClockId(::testing::TestParamInfo<clockid_t> info) { 38 switch (info.param) { 39 case CLOCK_MONOTONIC: 40 return "CLOCK_MONOTONIC"; 41 case CLOCK_BOOTTIME: 42 return "CLOCK_BOOTTIME"; 43 default: 44 return absl::StrCat(info.param); 45 } 46 } 47 48 class MonotonicVDSOClockTest : public ::testing::TestWithParam<clockid_t> {}; 49 50 TEST_P(MonotonicVDSOClockTest, IsCorrect) { 51 // The VDSO implementation of clock_gettime() uses the TSC. On KVM, sentry and 52 // application TSCs can be very desynchronized; see 53 // sentry/platform/kvm/kvm.vCPU.setSystemTime(). 54 SKIP_IF(GvisorPlatform() == Platform::kKVM); 55 56 // Check that when we alternate readings from the clock_gettime syscall and 57 // the VDSO's implementation, we observe the combined sequence as being 58 // monotonic. 59 struct timespec tvdso, tsys; 60 absl::Time vdso_time, sys_time; 61 ASSERT_THAT(syscall(__NR_clock_gettime, GetParam(), &tsys), 62 SyscallSucceeds()); 63 sys_time = absl::TimeFromTimespec(tsys); 64 auto end = absl::Now() + absl::Seconds(10); 65 while (absl::Now() < end) { 66 ASSERT_THAT(clock_gettime(GetParam(), &tvdso), SyscallSucceeds()); 67 vdso_time = absl::TimeFromTimespec(tvdso); 68 EXPECT_LE(sys_time, vdso_time); 69 ASSERT_THAT(syscall(__NR_clock_gettime, GetParam(), &tsys), 70 SyscallSucceeds()); 71 sys_time = absl::TimeFromTimespec(tsys); 72 EXPECT_LE(vdso_time, sys_time); 73 } 74 } 75 76 INSTANTIATE_TEST_SUITE_P(ClockGettime, MonotonicVDSOClockTest, 77 ::testing::Values(CLOCK_MONOTONIC, CLOCK_BOOTTIME), 78 PrintClockId); 79 80 } // namespace 81 82 } // namespace testing 83 } // namespace gvisor