%20(n%C3%A3o%20VDSO)%20em%20x86_64%20usando%20HPET%3F.png)
Enquanto procurava como usar gettimeofday()
pela enésima vez, decidi desta vez fazer um mergulho rápido no vDSO, já que eu só tinha uma vaga consciência dele e me perguntei se havia alguma dica de uso que eu deveria procurar.
De acordo comhttps://stackoverflow.com/questions/42622427/gettimeofday-not-using-vdso, se o vDSO estiver em uso, strace
deveránuncamostrar gettimeofday
ou clock_gettime
.
Bem, parece que meu ThinkPad T400 está quebrado há algum tempo: sempre vi*toneladas*dessas ligações strace
desde que me lembro. (Particularmente do QEMU.)
Se eu tentar testgtod.c
(que é executado gettimeofday()
1000 vezes) a partir da pergunta acima:
$ strace ./testgtod 2>&1 | grep clock_gettime | wc -l
1000
Atualmente, a única diferença que encontro entre meu ThinkPad e meu desktop i3 é que o i3 está usando o TSC, enquanto o ThinkPad está usando o HPET porque tsc: Marking TSC unstable due to TSC halts in idle
. (Me perguntei se isso poderia ser uma coisa de suspensão/retomada, mas então notei o carimbo de data/hora - isso é 1,53 segundos após a inicialização.) O T400 está (atualmente...) executando o Arch, enquanto a caixa i3 está executando o Debian 9.
A pergunta acima também fez referência a dump-vdso.c
. O vDSO no T400 parece muito bom para mim:
$ 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
Outro link que encontrei,https://bert-hubert.blogspot.com/2017/03/on-linux-vdso-and-clockgettime.html, diz que o código vDSO não tem suporte para determinados temporizadores e retornará para um syscall se você usar um deles. Esse artigo é de 2017 e os detalhes emhttps://lore.kernel.org/linux-arm-kernel/[e-mail protegido]/(junho de 2019) sugere que quase todos (se não todos?) Os temporizadores têm suporte para vDSO agora, mas, em qualquer caso, o testgtod
programa mencionado acima é chamado de CLOCK_REALTIME
, que o artigo de 2017 diz que era compatível com vDSO naquela época.
Então: estou oficialmente confuso :)
Lendohttp://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/, Eu vejo umamuitode referências ao TSC. O artigo realmente não menciona isso, mas estou começando a pensar que talvez RDTSC{,P}
seja uma instrução sem privilégios que pode ser chamada no espaço do usuário, enquanto a leitura do HPET requer acesso no nível do kernel (aos valores de hardware ou de timer). O que explicaria totalmente o substituto do syscall.
Aliás, o Core2 P8600 no meu T400 suporta tsc
e constant_tsc
, mas não nonstop_tsc
.
Nenhumtsc obterhoradodia relógio-gettime vdso HPpetexistiam, se alguém com mais reputação quiser adicionar um ou mais deles.
Responder1
O artigo realmente não menciona isso, mas estou começando a pensar que talvez
RDTSC{,P}
seja uma instrução sem privilégios que pode ser chamada no espaço do usuário, enquanto a leitura do HPET requer acesso no nível do kernel (aos valores de hardware ou de timer). O que explicaria totalmente o substituto do syscall.
Esta é a razão.
Você pode verificar a mudança no comportamento do vDSO entre os dois relógios em qualquer sistema que suporte ambos tsc
e hpet
como fonte de horário:
$ 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 +++
(Lembre-se de restaurar a fonte do relógio original.)
RDTSC
é uma instrução sem privilégios, e você pode ver um exemplo de seu uso emo manual do GCC: pesquise rdtsc
lá, compile o código de exemplo e você verá que pode executá-lo no espaço do usuário. (Estritamente falando, RDTSC
eRDTSCP
pode ser privilegiado, eles não são por padrão no Linux, mas podemser privilegiado usandoprctl
.)
No vDSO, clock_gettimeofday
as funções relacionadas dependem de modos de relógio específicos; ver__arch_get_hw_counter
. Se o modo do relógio for VCLOCK_TSC
, a hora é lida sem syscall, usando RDTSC
; se for VCLOCK_PVCLOCK
ou VCLOCK_HVCLOCK
, é lido em uma página específica para recuperar as informações do hipervisor. HPETnão declara um modo de relógio, então termina com o padrãoVCLOCK_NONE
, e o vDSO emite uma chamada de sistema para recuperar a hora.
O patchset ao qual você vinculounão se tratava de unificar o gerenciamento de relógios entre relógios, mas de unificá-lo entre arquiteturas. Ainda existem alguns relógios sem suporte a vDSO, entre eles HPET e ACPI.