Linux Kernel MO806I –2s2009 Ng Kin Jin ra045565
Transcription
Linux Kernel MO806I –2s2009 Ng Kin Jin ra045565
Linux Kernel MO806I –2s2009 Ng Kin Jin ra045565 Outline Motivação 1. 2. 3. 4. 5. 6. Clock e Timer Circuits The Linux Timekeeping Architecture Atualização de data e hora Atualização de estatísticas do sistema Software times e delay functions Chamadas de sistema relacionadas a medidas de tempo 2 Motivação Medir intervalos de tempo e comparar tempos Informações sobre o instante corrente, data e hora. Postergar operações por uma quantidade específica de tempo Escalonamento assíncrono de funções para que sejam executadas porteriormente Através destas funcionalidades é possível implementar CPU time sharing, atualizar o horário do sistema e as estatísticas de uso de recursos, e manter os temporizadores de programa, verificando a ocorrência de time-outs 3 Outline Motivação 1. Clock e Timer Circuits 2. The Linux Timekeeping Architecture 3. Atualização de data e hora 4. Atualização de estatísticas do sistema 5. Software times e delay functions 6. Chamadas de sistema relacionadas a medidas de tempo 4 1. Clock e Timer Circuits (1/7) Real Time Clock (RTC) Time Stamp Counter (TSC) Programmable Interval Timer (PIT) CPU Local Timer High Precision Event Timer (HPET) ACPI Power Management Timer (ACPI PMT) 5 1. Clock e Timer Circuits (2/7) Real Time Clock (RTC) Presente em todos PC’s Independente de outros chips Alimentado por uma pequena bateria Emite interrupções periódicas No Linux, usado para extrair hora e data Programável por processos via arquivo $/dev/rtc Acessado pelo kernel por portas de I/O 0x70 e 0x71 Time Stamp Counter (TSC) 6 1. Clock e Timer Circuits (3/7) Real Time Clock (RTC) Time Stamp Counter (TSC) Contador incrementado a cada sinal de clock recebido pelo CLK input pin do microprocessador a partir de um oscilador externo rdtsc instrução assembly que lê o RTC calibrate_tsc() função chamada pelo kernel durante a inicialização do sistema que computa a freqüência do sinal de clock da CPU 7 1. Clock e Timer Circuits (4/7) Time Stamp Counter (TSC) Programmable Interval Timer (PIT) Emite a interrupção timer interrupt para informar ao kernel o decorrimento de um intervalo de tempo Ao contrário do alarm clock, emite interrupções em uma freqüência fixa, definida pelo kernel CPU Local Timer 8 1. Clock e Timer Circuits (5/7) Programmable Interval Timer (PIT) CPU Local Timer 16 bits (pode ser programado para emitir interrupções em baixa freqüência) Emite uma interrupção global Usa seus próprios sinais de clock, podendo ser programado de forma mais flexível High Precision Event Timer (HPET) 9 1. Clock e Timer Circuits (6/7) CPU Local Timer High Precision Event Timer (HPET) Chip desenvolvido em conjunto pela MS e Intel Contém mais de 8 contadores independentes Freqüência mínima de operação de 10Mhz Programável pelo kernel do SO através de registradores mapeados em memória Preferível aos outros mecanismos devido à sua arquitetura ACPI Power Management Timer (ACPI PMT) 10 1. Clock e Timer Circuits (7/7) High Precision Event Timer (HPET) ACPI Power Management Timer (ACPI PMT) Freqüência fixa de 3.58MHz 32 bits Envia interrupções somente para seus processador Baseado no sinal de clock do barramento (opera somente em freqüências derivadas do barramento) Mais adequado para DFVS do que TSC 11 Outline Motivação 1. 2. 3. 4. 5. 6. Clock e Timer Circuits The Linux Timekeeping Architecture Atualização de data e hora Atualização de estatísticas do sistema Software times e delay functions Chamadas de sistema relacionadas a medidas de tempo 12 2. The Linux Timekeeping Architercture Overview Arquitetura Estruturas UP x Mp Implementação de Low-resolution Timers Generic Time Subsystem High-resolution Timers Broadcast Mode 13 2.1 Arquitetura: Overview Figure 1: Subsistema de timing[LinuxKernelArch] 14 2.1 Estruturas: Overview Timer object: time_opts Nome do campo Descrição name String que identifica o timer source mark_offset Registra o instante exato do último tick. É invocado pelo handler do timer interrupt. get_offset Retorna o tempo decorrido desde o último tick. monotonic_clock Retorna o número de nanosegundos decorridos desde a inicialização do kernel. delay Espera por um dado número de ciclos. 15 2.1 Estruturas: Overview Timer object: time_opts Nome do Timer object timer_hpet timer_pmtmr timer_tsc timer_pit timer_none Descrição High Precision Event Timer (HPET) ACPI Power Management Timer (ACPI PMT) Time Stamp Counter (TSC) Programmable Interval Timer (PIT) Generic dummy timer source (used during kernel initialization) Interpolação Atraso HPET HPET ACPI PMT TSC TSC TSC PIT Tight loop (none) Tight loop Table: Típicos objetos de timer para a arquitetura 80x86 16 2.1 Estruturas: Overview Timer object: time_opts armazena o endereço de um objeto timer [coluna 1, tabela 2]. Inicializado com timer_none e atualizado para o source mais adequado com select_timer(). Mark_offset() e get_offset() utilizam os timer sources da [coluna 3, tabela 2] para obter sub-ticks. Delay()utiliza os timer sources da [coluna 4, tabela 2] cur_timer jiffies 17 2.1 Estruturas: Overview jiffies Contador de 32 bits que armazena o número de ticks a partir da inicialização. Inicializado com 0xfffb6c20(16)(=300k(10)) para evidenciar rapidamente o não tratamento de overflow do jiffies jiffies_64: não pode ser lido diretamente em sistemas de 32 bits (viola a atomicidade) unsigned long long get_jiffies_64(void) { unsigned long seq; unsigned long long ret; do { // A operação de leitura é protegida pelo seqlock xtime_lock seq = read_seqbegin(&xtime_lock); ret = jiffies_64; } while (read_seqretry(&xime_lock, seq)); return ret; } 18 2.1 Estruturas: Overview xtime Do tipo timespec Programas de usuário utilizam para obter data e hora xtime_lock seqlock: define várias regiões críticas na arquitetura de timekeeping do kernel. Evita condição de disputa durante o acesso à variável xtime. A mesma função desempenhada para a variável jiffies_64. Nome do campo Descrição tv_sec Armazena o número de segundos desde 00:00:00h de 1/1/1970 (UTC) tv_nsec Armazena o número de nanosegundos decorridos desde o último segundo. 19 2.1 UP x MP: Overview Em sistemas uniprocessados, os eventos são disparados por um timer global (PIT ou HPET) Para sistemas multiprocessados, as atividades comuns são controladas por um timer global, enquanto as atividades específicas da CPU são disparadas por interrupções emitidas pelo timer APCI local. 20 2.1.1 Uniprocessor Systems: Overview Inicialização Timer Interrupt Handler 21 2.1.1 Uniprocessor Systems: Overview Inicialização 1. Inicializa a variável xtime, lido do RTC (real-time clock) através da função get_cmos_time() 2. Inicializa a variável wall_to_monotonic 3. Caso o kernel suporte HPET, chama hpet_enable() que verifica se o firmware do ACPI mapeou seus registradores no espaço de endereçamento de memória. Usa PIT c.c. 4. Invoca select_timer() e atribui em cur_timer o endereço do timer object associado ao melhor timer source. 5. Invoca setup_irq() para configurar a porta correspondente à interrupção IRQ0 22 2.1.1 Uniprocessor Systems: Overview Inicialização Timer Interrupt Handler timer_interrupt() é a interrupt service routine(ISR) para PIT e HPET 1. Protege as variáveis de tempo do kernel obtendo lock de escrita sobre o seqlock xtime_lock através da chamada 2. write_seqlock() Executa cur_timer->mark_offset(). 3. do_timer_interrupt() { inc(jiffies_64) update_times() update_process_times() profile_tick() 4. } Chama write_sequnlock() e libera o seqlock xtime_lock 23 2.1.2 Multiprocessor Systems: Overview Inicialização Global Local Timer Interrupt Handler Global Local 24 2.1.2 Multiprocessor Systems: Overview Inicialização Global Inicializa o handler de interrupção do global timer através do time_init() como nos sistemas uniprocessados Local O kernel linux reserva o vetor de interrupções 0xef para as interrupções do timer local apic_intr_init() configura as portas correspondentes às interrupções do vetor 0xef a serem tratadas pelo handler apic_timer_interrupt() Invoca calibrate_APIC_clock() para computar quantos sinais de clocks do barramento foram recebicos pelo APIC local da CPU que realizou o boot durante um tick (1ms). Invoca setup_APIC_timer() para cada CPU do sistema para programar os APIC’s locais de modo a gerar interrupções de tempo a cada tick. Timer Interrupt Handler 25 2.1.2 Multiprocessor Systems: Overview Inicialização Timer Interrupt Handler Global Difere em poucos pontos da versão UP Não invoca update_process_times() e profile_tick() por ser específico de cada CPU. Local smp_apic_timer_interrupt() { Obtém número lógico da CPU Incrementa a nth posição de apic_timer_irqs Chama irq_enter() Chama smp_local_timer_interrupt () {profile_click(); update_process_times();} Chama irq_exit(); } 26 2.1 Low x High-resolution Timers: Overview Low: Timers clássicos Sua implementação se encontra em kernel/timer.c Baseado em eventos periódicos, jiffies High: Subsistema de temporização adicionado ao kernel 2.6 que oferece maior precisão e alcança resoluções da ordem de nanosegundos. Baseado em eventos de clocks (time stamps de nanosegundos) O framework introduzido foi reaproveitado pela tipo lowresolution de timers (de fato a versão low é construída sobre o mecanismo da high) 27 2.2 Implementação de Low-resolution Timers – Timer Activation Figure 2: Overview de interrupções disparadas por temporizadores lowresolution em arquiteturas IA-32 e AMD64 [LinuxKernelArch] 28 2.2 Implementação de Low-resolution Timers Figure 3: Fluxo de código para do_time() 29 2.2 Implementação de Low-resolution Timers – Dynamic Timers Figure 4: Estruturas de dados para gerenciamento de temporizadores dinâmicos. 30 2.3 Generic Time Subsystem 1. Clock Sources - struct clocksource 2. Clock Event Devices struct clock_event_device 3. Tick Device - struct tick_device Figure 5: Overview de um subsistema genérico de tempo. 31 2.4 High-resolution Timers Figure: Estruturas de dados utilizadas para implementar high-resolution timers. (Red-black tree – um tipo de árvore de busca binária auto-balanceada) 32 2.6 Broadcast Mode Figure: Cenário quando broadcasting substitui dispositivos de tick não funcionais. [*] inter-processor interrupt (IPI) kernel/tick/tick-broadcast.c 33 Outline Motivação 1. 2. 3. 4. 5. 6. Clock e Timer Circuits The Linux Timekeeping Architecture Atualização de data e hora Atualização de estatísticas do sistema Software times e delay functions Chamadas de sistema relacionadas a medidas de tempo 34 3. Atualização de data e hora Data e hora armazenadas na variável xtime // Executado após adquirir seqlock xtime_lock para escrita void update_times(void) { unsigned long ticks; // wall_jiffies guarda o instante da última atualização de jiffies ticks = jiffies - wall_jiffies; if (ticks) { wall_jiffies += ticks; // em geral soma 106 a xtime.tv_nsec e atualiza xtime.tv_sec update_wall_time(ticks); } // conta o no de processos nos estados TASK_RUNNING ou // TASK_UNINTERRUPTIBLE para atualizar a média de carga do sistema calc_load(ticks); } 35 Outline Motivação 1. 2. 3. 4. 5. 6. Clock e Timer Circuits The Linux Timekeeping Architecture Atualização de data e hora Atualização de estatísticas do sistema Software times e delay functions Chamadas de sistema relacionadas a medidas de tempo 36 4. Atualização de Estatísticas do Sistema (1/2) O kernel coleta dados periodicamente para: Verificar os limites de recursos da CPU dos processos em execução Atualizar estatísticas acerca da carga de trabalho da CPU Computar a média de carga do sistema Perfilar (Profiling) do código do kernel (Algoritmo de Monte Carlo) $ readprofile -> /proc/profile OProfile: profile_tick(), timer_notify() 37 4. Atualização de Estatísticas do Sistema (2/2) Atualização de estatísticas locais da CPU update_process_times() chamada por timer global (UP) ou handler local para interrupções de timer (MP) 1. 2. 3. 4. 5. Verifica a quanto tempo o processo está executando. Executa account_user_time() para User Mode e a account_system_time() para Kernel Mode Invoca raise_softirq() para ativar a tasklet TIMER_SOFTIRQ na CPU local Caso uma estrutura de dados antiga guardada por RCU-protected (Read-Copy Update)tenha sido recuperada, verifica se a CPU local alcançou o estado quiescente e em seguida invoca tasklet_schedule() para ativar a tasklet rcu_tasklet da CPU local Invoca scheduler_tick(), que decrementa o contador de time slice do processo corrente e verifica se o quantum de tempo foi consumido. 38 Outline Motivação 1. 2. 3. 4. 5. 6. Clock e Timer Circuits The Linux Timekeeping Architecture Atualização de data e hora Atualização de estatísticas do sistema Software times e delay functions Chamadas de sistema relacionadas a medidas de tempo 39 5. Software times e Delay Functions (1/4) Dynamic Timers Race Conditions: Liberar o recurso sem parar o timer pode levar a inconsistência de estado ou corrupção de dados quando a função do timer for ativada quando não houver mais recursos ... del_timer(&t); X_Release_Resources( ); ... Parar o timer antes de liberar os recursos também não é seguro em sistemas multiprocessados, pois a função de timer pode já estar rodando em outra CPU quando del_timer() for chamada. 40 5. Software times e Delay Functions (2/4) Timers e Time-outs Dynamic Timers Podem ser criados e destruídos Armazenados em estruturas do tipo struct timer_list { // Utilizado para inserir o sw timer // em uma lista circular duplamente ligada struct list_head entry; // indica quanto o timer expira unsigned long expires; spinlock_t lock; unsigned long magic; //Ponteiro para função a ser executada no time-out do timer void (*function)(unsigned long); unsigned long data; tvec_base_t *base; }; 41 5. Software times e Delay Functions (3/4) Dynamic Timers Race Conditions [patch-time-fix]: race #1: __run_timers() { // is running on CPU0: list_del(&timer->entry); timer->base = NULL; [*] set_running_timer(base, timer); spin_unlock_irq(&base->lock); [**] fn(data); spin_lock_irq(&base->lock); } CPU0 pára em [*] antes de timer->base ser setado para NULL, mas antes de base->running_timer pointer ser configurado. Caso uma CPU1 execute del_timer_sync(), ela não encontrará a referêncai timer->base ou base->running_timer para sincronizar, reportando que o timer foi deletado. Caso a CPU1 continue a execução do timer fn(data), isso levará ao crash. Para contornar basta reordenar os comando timer->base, limpar com set_running_timer()e usar wmb() entre estes comandos. 42 5. Software times e Delay Functions (4/4) Delay Functions Conveniente para drivers Menor overhead em comparação aos timers dinâmicos Introduz um atraso, retornando após um intervalo determinado void udelay(unsigned long usecs) { //microsegundos unsigned long loops; loops = (usecs*HZ*current_cpu_data.loops_per_jiffy)/1000000; cur_timer>delay(loops); } void ndelay(unsigned long nsecs) { //nanosegundos unsigned long loops; loops =(nsecs*HZ*current_cpu_data.loops_per_jiffy)/1000000000; cur_timer->delay(loops); } 43 Outline Motivação 1. 2. 3. 4. 5. 6. Clock e Timer Circuits The Linux Timekeeping Architecture Atualização de data e hora Atualização de estatísticas do sistema Software times e delay functions Chamadas de sistema relacionadas a medidas de tempo 44 6. Chamadas de Sistema Relacionadas a medidas de tempo (1/2) Chamadas de Sistema Descrição time() Retorna o número de segundos decorridos desde 00:00:00h 1/1/1970(UTC) gettimeofday() Retorna na struct timeval os segundos decorridos desde 00:00:00h 1/1/1970(UTC) e os microsegundos decorridos no último segundo adjtimex() Permite a sincronização via Network Time Protocol (NTP). Recebe o ponteiro para uma struct timex como parâmetro e retorna nela os valores atuais do kernel. setitimer() Define valores de intervalo de tempo alarm() Envia um SIGALRM para o processo que o invocou quando o intervalo de tempo especificado termina. 45 6. Chamadas de Sistema Relacionadas a medidas de tempo (2/2) POSIX Timers (kernel 2.6) oltado para aplicações multithreaded e real-time CLOCK_REALTIME: Clock virtual que representa o clock real-time do sistema, cujo valor está emxtime variável. Resolução de aproximadamente 1000 atualizações da variável xtime por segundo CLOCK_MONOTONIC : Clock virtual que representa a soma das variáveis xtime e wall_to_monotonic(=é do mesmo tipo de xtime e armazena o número d segundos e nanosegundos a serem adicionados a xtime de modo a obter um fluxo monotônico crescente de tempo). Chamadas de sistema disponíveis: clock_gettime() clock_settime() clock_getres() timer_create() timer_gettime() timer_settime() timer_getoverrun() timer_delete() clock_nanosleep() 46 Referências [LinuxKernelArch] Mauerer, Wolfgang. Professional Linux Kernel Architecture. Wiley Publishing, Inc. 2008. Capítulo 15. [Bovet et al] Bovet, Daniel P. Cesati, Marco. Understanding Linux Kernel 3rd ed. O’Reilly publisher. Nov 2005. Capítulo 6. [LinuxLove] Love, Robert. Linux Kernel Development 2nd ed. Sams Publishing. Jan 2005. Capítulo 10. [Corbet et al] Corbet, Jonathan. Kroha-Hartman, Greg. Rubini, Alessandro. Linux Device Drivers. O’Reilly publisher. Feb 2005. Capítulo 7. [patch-time-fix] SMP races in the timer code, timer-fix-2.6.0-test7-A0 http://lkml.indiana.edu/hypermail/linux/kernel/0310.1/0774.html 47