Devo ver syscalls clock_gettime() (não VDSO) em x86_64 usando HPET?

Devo ver syscalls clock_gettime() (não VDSO) em x86_64 usando HPET?

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, stracedeveránuncamostrar gettimeofdayou clock_gettime.

Bem, parece que meu ThinkPad T400 está quebrado há algum tempo: sempre vi*toneladas*dessas ligações stracedesde 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 testgtodprograma 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 tsce constant_tsc, mas não nonstop_tsc.

Nenhum existiam, 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 tsce hpetcomo 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 rdtsclá, compile o código de exemplo e você verá que pode executá-lo no espaço do usuário. (Estritamente falando, RDTSCeRDTSCP pode ser privilegiado, eles não são por padrão no Linux, mas podemser privilegiado usandoprctl.)

No vDSO, clock_gettimeofdayas 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_PVCLOCKou 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.

informação relacionada