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