Clock

我應該使用 HPET 在 x86_64 上看到(非 VDSO)clock_gettime() 系統呼叫嗎?

  • November 25, 2019

在無數次查找如何使用gettimeofday()時,我決定這次快速了解 vDSO,因為我對它只有模糊的認識,並想知道是否有任何我應該注意的使用陷阱。

根據https://stackoverflow.com/questions/42622427/gettimeofday-not-using-vdso ,如果vDSO正在使用中,strace則不應顯示or 。gettimeofday``clock_gettime

好吧,看起來我的 ThinkPad T400 已經壞了一段時間了:從我記事起,我就一直看到的這些電話strace。(特別是來自 QEMU。)

如果我從上述問題嘗試testgtod.c(執行1000 次):gettimeofday()

$ strace ./testgtod 2>&1 | grep clock_gettime | wc -l
1000

目前,我能在 ThinkPad 和 i3 桌面之間找到的唯一區別是 i3 使用 TSC,而 ThinkPad 使用 HPET,因為tsc: Marking TSC unstable due to TSC halts in idle. (想知道這是否可能是暫停/恢復的事情,但隨後注意到時間戳 - 這是啟動後的 1.53 秒。)T400(目前……)執行 Arch,而 i3 機器執行 Debian 9。

上面的問題也提到了dump-vdso.c。T400 上的 vDSO 在我看來相當不錯:

$ objdump -T vdso.so

vdso.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000740  w   DF .text  000000000000005e  LINUX_2.6   clock_gettime
00000000000007a0 g    DF .text  0000000000000067  LINUX_2.6   __vdso_gettimeofday
00000000000007a0  w   DF .text  0000000000000067  LINUX_2.6   gettimeofday
0000000000000810 g    DF .text  0000000000000010  LINUX_2.6   __vdso_time
0000000000000810  w   DF .text  0000000000000010  LINUX_2.6   time
0000000000000740 g    DF .text  000000000000005e  LINUX_2.6   __vdso_clock_gettime
0000000000000000 g    DO *ABS*  0000000000000000  LINUX_2.6   LINUX_2.6
0000000000000820 g    DF .text  0000000000000025  LINUX_2.6   __vdso_getcpu
0000000000000820  w   DF .text  0000000000000025  LINUX_2.6   getcpu

我發現的另一個連結https://bert-hubert.blogspot.com/2017/03/on-linux-vdso-and-clockgettime.html表示 vDSO 程式碼缺乏對某些計時器的支持,並將回退到系統呼叫,如果你使用其中之一。那篇文章來自 2017 年,https://lore.kernel.org/linux-arm-kernel/20190621095252.32307-1-vincenzo.frascino@arm.com/(2019 年 6 月)中的詳細資訊表明幾乎所有(如果不是全部? ) 計時器現在支持 vDSO,但無論如何,testgtod上面提到的程序稱為CLOCK_REALTIME,2017 年的文章說當時支持 vDSO。

所以:我正式感到困惑:)

通過http://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/閱讀,我看到很多對 TSC 的引用。這篇文章並沒有真正提到它,但我開始認為這可能RDTSC{,P}是一個可以從使用者空間呼叫的非特權指令,而從 HPET 讀取需要核心級訪問(對硬體或計時器值)。這將完全解釋系統呼叫回退。

順便說一句,我的 T400 中的 Core2 P8600 確實支持tscand constant_tsc,但不支持nonstop_tsc

tsc gettimeofday clock-gettime vdso hpet 都不存在,如果有更多聲譽的人想要添加其中的一個或多個。

這篇文章並沒有真正提到它,但我開始認為這可能RDTSC{,P}是一個可以從使用者空間呼叫的非特權指令,而從 HPET 讀取需要核心級訪問(對硬體或計時器值)。這將完全解釋系統呼叫回退。

這就是原因。

您可以在任何同時支持tschpet作為時間源的系統上驗證兩個時鐘之間的 vDSO 行為變化:

$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm

$ echo tsc | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource > /dev/null

$ strace -e clock_gettime date
Sun 24 Nov 10:49:49 CET 2019
+++ exited with 0 +++

$ echo hpet | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource > /dev/null

$ strace -e clock_gettime date
clock_gettime(CLOCK_REALTIME, {tv_sec=1574589034, tv_nsec=589851883}) = 0
Sun 24 Nov 10:50:34 CET 2019
+++ exited with 0 +++

(記得恢復原來的時鐘源。)

RDTSC是一個非特權指令,你可以在GCC 手冊中看到它的使用範例:在那裡搜尋rdtsc,編譯範常式式碼,你會看到你可以在使用者空間中執行它。(嚴格來說,RDTSC並且RDTSCP 可以是 privileged,它們在 Linux 下不是預設的,但可以使用 來獲得特權prctl。)

在 vDSO 中,clock_gettimeofday相關功能依賴於特定的時鐘模式;見__arch_get_hw_counter。如果時鐘模式為VCLOCK_TSC,則無需系統呼叫即可讀取時間,使用RDTSC; 如果是VCLOCK_PVCLOCKVCLOCK_HVCLOCK,則從特定頁面讀取以從管理程序中檢索資訊。HPET沒有聲明時鐘模式,因此它以預設值結束VCLOCK_NONE,並且 vDSO 發出系統呼叫來檢索時間。

您連結到的更新檔集不是關於跨時鐘統一時鐘處理,而是跨架構統一它。還有一些時鐘不支持 vDSO,其中包括 HPET 和 ACPI。

引用自:https://unix.stackexchange.com/questions/553845