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

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

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

根據https://stackoverflow.com/questions/42622427/gettimeofday-not-using-vdso,如果正在使用 vDSO,strace應該絕不顯示gettimeofdayclock_gettime.

嗯,看起來我的 ThinkPad T400 已經壞了一段時間了:我總是看到*噸*strace從我記事起,就一直有這樣的電話。 (特別是來自 QEMU。)

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

$ 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/[電子郵件受保護]/(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 確實支援tscconstant_tsc,但不支援nonstop_tsc

沒有 存在,如果有更多聲譽的人想要添加其中一個或多個。

答案1

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

這就是原因。

tsc您可以在支援和hpet作為時間源的任何系統上驗證兩個時鐘之間 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是一條非特權指令,您可以在中查看其使用範例海灣合作委員會手冊:搜尋rdtsc那裡,編譯範例程式碼,你會發現可以在使用者空間中運行它。 (嚴格來說,RDTSC並且RDTSCP 可以享有特權,預設情況下它們不在 Linux 下,但它們可以獲得特權使用prctl.)

在vDSO中,clock_gettimeofday相關功能依賴特定的時鐘模式;看__arch_get_hw_counter。如果時鐘模式為VCLOCK_TSC,則無需系統呼叫即可讀取時間,使用RDTSC;如果是VCLOCK_PVCLOCKVCLOCK_HVCLOCK,則從特定頁面讀取以從管理程式檢索資訊。高溫PET沒有聲明時鐘模式,所以最終得到預設值VCLOCK_NONE,並且 vDSO 發出系統呼叫來檢索時間。

您連結到的補丁集不是要統一跨時脈的時脈處理,而是統一跨架構的時脈處理。還有一些時脈不支援 vDSO,其中包括 HPET 和 ACPI。

相關內容