%20clock_gettime()-Systemaufrufe%20auf%20x86_64%20mit%20HPET%20sehen%3F.png)
Als ich zum gefühlt hundertsten Mal nach der Verwendung suchte, gettimeofday()
beschloss ich, mich dieses Mal kurz mit vDSO zu befassen, da ich nur vage Kenntnisse darüber hatte und mich fragte, ob es bei der Verwendung irgendwelche Fallstricke gab, auf die ich achten sollte.
Entsprechendhttps://stackoverflow.com/questions/42622427/gettimeofday-not-using-vdso, wenn der vDSO im Einsatz ist, strace
sollteniemalsanzeigen gettimeofday
oder clock_gettime
.
Nun, es sieht so aus, als wäre mein ThinkPad T400 schon seit einiger Zeit kaputt: Ich habe immer gesehen*Tonnen*dieser Anrufe, strace
soweit ich mich erinnern kann. (Insbesondere von QEMU.)
Wenn ich es aus der obigen Frage heraus versuche testgtod.c
(was 1000 Mal passiert ):gettimeofday()
$ strace ./testgtod 2>&1 | grep clock_gettime | wc -l
1000
Der einzige Unterschied, den ich derzeit zwischen meinem ThinkPad und meinem i3-Desktop feststellen kann, ist, dass der i3 TSC verwendet, während das ThinkPad HPET verwendet, weil tsc: Marking TSC unstable due to TSC halts in idle
. (Ich habe mich gefragt, ob dies eine Suspend/Resume-Sache sein könnte, aber dann ist mir der Zeitstempel aufgefallen – er ist 1,53 Sekunden nach dem Booten.) Auf dem T400 läuft (derzeit...) Arch, während auf der i3-Box Debian 9 läuft.
Die obige Frage bezog sich auch auf dump-vdso.c
. Das vDSO auf dem T400 sieht für mich ziemlich gut aus:
$ 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
Ein weiterer Link, den ich gefunden habe,https://bert-hubert.blogspot.com/2017/03/on-linux-vdso-and-clockgettime.html, besagt, dass der vDSO-Code bestimmte Timer nicht unterstützt und auf einen Systemaufruf zurückgreift, wenn Sie einen dieser Timer verwenden. Dieser Artikel stammt aus dem Jahr 2017 und die Details inhttps://lore.kernel.org/linux-arm-kernel/[email geschützt]/(Juni 2019) lässt darauf schließen, dass mittlerweile fast alle (wenn nicht alle?) Timer vDSO-Unterstützung bieten, aber auf jeden Fall wurde das testgtod
oben erwähnte Programm namens CLOCK_REALTIME
, das dem Artikel von 2017 zufolge damals vDSO-unterstützt war, trotzdem unterstützt.
Also: Ich bin offiziell verwirrt :)
Durchlesenhttp://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/, Ich sehe einvielvon Verweisen auf den TSC. Der Artikel erwähnt es nicht wirklich, aber ich fange an zu denken, dass es sich vielleicht RDTSC{,P}
um eine nicht privilegierte Anweisung handelt, die aus dem Benutzerbereich aufgerufen werden kann, während das Lesen vom HPET Zugriff auf Kernelebene (auf Hardware- oder Timerwerte) erfordert. Das würde den Syscall-Fallback völlig erklären.
Übrigens unterstützt der Core2 P8600 in meinem T400 tsc
und constant_tsc
, aber nicht nonstop_tsc
.
Keiner vontsc gettimeofday Uhr-Gettime vdso hpetexistiert, falls jemand mit höherem Ansehen einen oder mehrere davon hinzufügen möchte.
Antwort1
Der Artikel erwähnt es nicht wirklich, aber ich fange an zu denken, dass es sich vielleicht
RDTSC{,P}
um eine nicht privilegierte Anweisung handelt, die aus dem Benutzerbereich aufgerufen werden kann, während das Lesen vom HPET Zugriff auf Kernelebene (auf Hardware- oder Timerwerte) erfordert. Das würde den Syscall-Fallback völlig erklären.
Das ist der Grund.
Sie können die Änderung im vDSO-Verhalten zwischen den beiden Uhren auf jedem System überprüfen, das sowohl tsc
als auch hpet
als Zeitquelle unterstützt:
$ 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 +++
(Denken Sie daran, die ursprüngliche Taktquelle wiederherzustellen.)
RDTSC
ist eine nicht privilegierte Anweisung. Ein Beispiel für ihre Verwendung finden Sie indas GCC-Handbuch: Suchen Sie rdtsc
dort nach, kompilieren Sie den Beispielcode und Sie werden sehen, dass Sie ihn im Userspace ausführen können. (Genau genommen RDTSC
undRDTSCP
kann privilegiert sein, sie sind nicht standardmäßig unter Linux, aber sie könnenprivilegiert werden durchprctl
.)
Im vDSO clock_gettimeofday
und verwandten Funktionen sind bestimmte Taktmodi erforderlich; siehe__arch_get_hw_counter
. Wenn der Uhrmodus ist VCLOCK_TSC
, wird die Zeit ohne Systemaufruf gelesen, indem verwendet wird RDTSC
; wenn es VCLOCK_PVCLOCK
oder ist VCLOCK_HVCLOCK
, wird sie von einer bestimmten Seite gelesen, um die Informationen vom Hypervisor abzurufen. HPETdeklariert keinen Uhrmodus, so dass am Ende die StandardeinstellungVCLOCK_NONE
, und der vDSO gibt einen Systemaufruf aus, um die Zeit abzurufen.
Das von Ihnen verlinkte Patchsetging es nicht darum, die Taktverarbeitung über mehrere Uhren hinweg zu vereinheitlichen, sondern über mehrere Architekturen hinweg. Es gibt immer noch einige Uhren ohne vDSO-Unterstützung, darunter HPET und ACPI.