Sollte ich (nicht-VDSO) clock_gettime()-Systemaufrufe auf x86_64 mit HPET sehen?

Sollte ich (nicht-VDSO) clock_gettime()-Systemaufrufe auf x86_64 mit HPET sehen?

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, stracesollteniemalsanzeigen gettimeofdayoder 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, stracesoweit 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 testgtodoben 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 tscund constant_tsc, aber nicht nonstop_tsc.

Keiner von existiert, 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 tscals auch hpetals 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.)

RDTSCist eine nicht privilegierte Anweisung. Ein Beispiel für ihre Verwendung finden Sie indas GCC-Handbuch: Suchen Sie rdtscdort nach, kompilieren Sie den Beispielcode und Sie werden sehen, dass Sie ihn im Userspace ausführen können. (Genau genommen RDTSCundRDTSCP kann privilegiert sein, sie sind nicht standardmäßig unter Linux, aber sie könnenprivilegiert werden durchprctl.)

Im vDSO clock_gettimeofdayund 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_PVCLOCKoder 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.

verwandte Informationen