%20(no%20VDSO)%20en%20x86_64%20usando%20HPET%3F.png)
Mientras buscaba cómo usarlo gettimeofday()
por enésima vez, decidí esta vez hacer una inmersión rápida en vDSO, ya que solo tenía una vaga conciencia de ello y me preguntaba si había algún problema de uso al que debería prestar atención.
De acuerdo ahttps://stackoverflow.com/questions/42622427/gettimeofday-not-using-vdso, si el vDSO está en uso, strace
deberíanuncamostrar gettimeofday
o clock_gettime
.
Bueno, parece que mi ThinkPad T400 lleva algún tiempo averiado: siempre lo he visto*montones*de estas llamadas strace
desde que tengo uso de razón. (Particularmente de QEMU.)
Si intento testgtod.c
(que se ejecuta gettimeofday()
1000 veces) la pregunta anterior:
$ strace ./testgtod 2>&1 | grep clock_gettime | wc -l
1000
Actualmente, la única diferencia que puedo encontrar entre mi ThinkPad y mi computadora de escritorio i3 es que el i3 usa TSC, mientras que el ThinkPad usa HPET porque tsc: Marking TSC unstable due to TSC halts in idle
. (Me pregunté si esto podría ser una cuestión de suspensión/reanudación, pero luego noté la marca de tiempo: esto es 1,53 segundos después del inicio). El T400 está (actualmente...) ejecutando Arch, mientras que el i3 ejecuta Debian 9.
La pregunta anterior también hacía referencia a dump-vdso.c
. El vDSO del T400 me parece bastante bueno:
$ 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
Otro enlace que encontré,https://bert-hubert.blogspot.com/2017/03/on-linux-vdso-and-clockgettime.html, dice que el código vDSO carece de soporte para ciertos temporizadores y recurrirá a una llamada al sistema si usa uno de esos. Ese artículo es de 2017 y los detalles enhttps://lore.kernel.org/linux-arm-kernel/[correo electrónico protegido]/(junio de 2019) sugiere que casi todos (¿si no todos?) los temporizadores tienen soporte vDSO ahora, pero en cualquier caso, el testgtod
programa mencionado anteriormente se llama CLOCK_REALTIME
, que según el artículo de 2017 era compatible con vDSO en ese entonces.
Entonces: estoy oficialmente confundido :)
leyendohttp://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/, Veo unlotede referencias al TSC. El artículo realmente no lo menciona, pero estoy empezando a pensar que tal vez RDTSC{,P}
sea una instrucción sin privilegios que se puede llamar desde el espacio de usuario, mientras que la lectura desde HPET requiere acceso a nivel de kernel (a valores de hardware o temporizador). Lo que explicaría totalmente el retroceso de la llamada al sistema.
Por cierto, el Core2 P8600 de mi T400 admite tsc
y constant_tsc
, pero no nonstop_tsc
.
Ninguno detsc obtener hora del día reloj-gettime vdso mascotaexistieron, si alguien con más reputación quiere agregar uno o más de ellos.
Respuesta1
El artículo realmente no lo menciona, pero estoy empezando a pensar que tal vez
RDTSC{,P}
sea una instrucción sin privilegios que se puede llamar desde el espacio de usuario, mientras que la lectura desde HPET requiere acceso a nivel de kernel (a valores de hardware o temporizador). Lo que explicaría totalmente el retroceso de la llamada al sistema.
Esta es la razón.
Puede verificar el cambio en el comportamiento de vDSO entre los dos relojes en cualquier sistema que admita ambos tsc
y hpet
como fuente de tiempo:
$ 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 +++
(Recuerde restaurar la fuente del reloj original).
RDTSC
es una instrucción sin privilegios, y puedes ver un ejemplo de su uso enel manual del CCG: busque rdtsc
allí, compile el código de ejemplo y verá que puede ejecutarlo en el espacio de usuario. (Estrictamente hablando, RDTSC
yRDTSCP
puede ser privilegiado, no están por defecto en Linux, pero puedentener privilegios de usoprctl
.)
En vDSO, clock_gettimeofday
las funciones relacionadas dependen de modos de reloj específicos; ver__arch_get_hw_counter
. Si el modo de reloj es VCLOCK_TSC
, la hora se lee sin una llamada al sistema, usando RDTSC
; si es VCLOCK_PVCLOCK
o VCLOCK_HVCLOCK
, se lee desde una página específica para recuperar la información del hipervisor. HPETno declara un modo de reloj, por lo que termina con el valor predeterminadoVCLOCK_NONE
y el vDSO emite una llamada al sistema para recuperar la hora.
El conjunto de parches al que se vinculóNo se trataba de unificar el manejo del reloj entre relojes, sino de unificarlo entre arquitecturas. Todavía hay algunos relojes sin soporte vDSO, entre ellos HPET y ACPI.