Schedulazione in RTAI
RTAI: modulo kernel rt_hello_km.c #include <rtai.h> #include <rtai_sched.h> Thread real-time... Ciclo infinito RT_TASK task; Periodico... void task_routine() { while(1) { /* Codice real-time */ rt_task_wait_period(); rt_printk("hello World at \\ time %llu!!!\n", rt_get_time_ns()); } }... int init_module(void) {... rt_task_init(&task, task_routine, 0, stack_size, priority, 0, 0); timer_period = start_rt_timer(nano2count(1e9)); task_period = 2*timer_period; rt_task_make_periodic(&task, now, task_period); } void cleanup_module(void) { rt_task_delete(&task); stop_rt_timer(); Chiusura del modulo } Generazione del thread definizione dei parametri del thread 2 generazione del thread
Compilazione dei moduli kernel: Linux 2.6 3 Uso di make e Makefile #Makefile KERNEL_SOURCE = /usr/src/linux Variabili d'ambiente Sono necessari almeno header e configurazione del kernel corrente EXTRA_CFLAGS= -ffast-math -mhard-float -I/usr/realtime/include -I$(KERNEL_SOURCE)/include -I$(KERNEL_SOURCE)/include/asm-i386/mach-default -I/usr/include EXTRA_LDFLAGS= -L/usr/realtime/lib -lmath -static obj-m := rt_hello_km.o default: rt_hello_km rt_hello_km: rt_hello_km.c Makefile make -C ${KERNEL_SOURCE} SUBDIRS=`pwd` modules clean: make -C ${KERNEL_SOURCE} SUBDIRS=`pwd` clean Direttive del make Indicazione del modulo da generare Direttiva di default Compilazione del modulo Pulizia della directory di compilazione
RTAI API 4 hiamata alle funzioni di generazione del task int rt_task_init(rt_task*, <funzione>, <data>, <stack_size>, <priorità>, 0, 0); Crea un processo real-time task di priorità <priorità> <funzione> indica la funzione da cui task inizia l esecuzione RT_TASK è la struttura dati che identifica un processo RTAI Solo in kernel mode ltre funzioni quali rt_sem_int, rt_mbx_int, and rt_cond_init...
Considerazioni su Missed Deadline 5 Non si ha nessuna segnalazione di fault (politica As Soon As Possible Execution) Se il processo continua ad essere prioritario prosegue nell esecuzione Politiche di rilevazione e di reazione ad un evento missed deadline sono lasciate al programmatore Skip Next Execution Policy: nei processi periodici viene annullata l esecuzione nel periodo successivo a quello in cui è avvenuta la situazione di overrun
Gestione HW del tempo RTAI supporta tre timer hardware: 6 Real Time Clock (RTC) Ha una risoluzione bassa (fino a 8192 Hz) e può essere programmato solo in modalità periodica con frequenze potenze di 2 Hz Non interferisce con i timer di Linux È disponibile anche nei PC più datati ed in molti sistemi embedded PIT 8254 e APIC (IA-32) / Decrementer (PowerPC) Hanno una risoluzione più elevata e non hanno il vincolo delle potenze di 2Hz e possono essere programmati sia in modalità periodica che in modalità oneshot La lettura del PIT è lenta (bus ISA), l APIC non è presente in tutte le CPU Sono utilizzati anche da Linux
Modalità di gestione del tempo 7 Periodic Mode: la temporizzazione dei task è a frequenza fissa La frequenza impostabile (e la risoluzione temporale) dipende dal dispositivo di clock utilizzato Le decisioni di scheduling sono prese (principalmente) allo scadere del tick Il tick successivo è automaticamente (via hardware) reimpostato La funzione start_rt_timer() consente di impostare la frequenza di tick desiderata Se l unico dispositivo di clock è l RTC, questa è l unica modalità disponibile Le decisioni di scheduling sono sia clock driven, sia event driven
Modalità di gestione del tempo 8 Oneshot Mode: la temporizzazione dei task è a frequenza variabile Come nella modalità periodica, la frequenza e la risoluzione dipendono dal clock device Le decisioni di scheduling vengono prese ad istanti temporali variabili: Nel momento in cui un task oneshot viene messo in esecuzione, il tick timer è impostato per scadere a: now() + resume_time resume_time è il primo tempo di risveglio di un task a priorità maggiore (o uguale) del task corrente Le decisioni di scheduling sono solo event driven! Il tick è un evento dinamico
Problemi architetturali 9 Su architetture x86, la presenza dell APIC implica la presenza del Time Stamp Counter (TSC) Il TSC è un contatore monotono ad elevata precisione (BusFreq) La modalità oneshot in RTAI fa uso sia del TSC sia dell APIC: Lettura veloce del TSC, risoluzione temporale elevata Programmazione veloce della prossima scadenza mediante timer APIC È necessario prestare attenzione in ambiente MP in quanto il TSC è un registro per-cpu L utilizzo del PIT 8254 in modalità oneshot introduce un jitter più elevato (e la lettura è più lenta)
Punti di attivazione dello scheduler Lo scheduler di RTAI sia è clock driven che event driven Il meccanismo di scheduling viene attivato: alla ricezione di un timer interrupt (clock tick, periodico o oneshot) all uscita di una routine di gestione interrupt (ISR) alla sospensione spontanea di un task Le principali operazioni effettuate sono: Aggiornamento degli slice temporali (politica Round-Robin) Risveglio dei task scaduti od in scadenza (timing oneshot) Selezione del task READY di priorità massima (O(1), è il task successivo la testa della lista) Eventuale task switching (potrebbe non essere necessario se il task corrente è quello di massima priorità) Regolazione del timer per il clock tick successivo (timing oneshot) 10
Scheduling RM in RTAI Rate Monotonic 11 È di facile realizzazione a partire dallo scheduling FIFO Occorre determinare le priorità dei processi in funzione della loro frequenza di attivazione Se non si vuole implementare l intero meccanismo manualmente RTAI mette a disposizione una primitiva che determina la priorità dei processi real-time presenti nel sistema in funzione del periodo impostato con rt_task_make_periodic(...) void rt_spv_rms(<cpu>); Setta la priorità dei processi RTAI che eseguono sul processore <cpu> in maniera inversamente proporzionale al loro periodo di attivazione
Scheduling RM in RTAI Creare un processo figlio fork(); 12 Creare i processi real-time definendone le priorità (anche se saranno sovrascritte) rt_task_init(nam2num( TaskHF ), LOW_PR, 0, 0); rt_task_init(nam2num( TaskLF ), HIGH_PR, 0, 0); Entrare in modalità real-time rt_make_hard_real_time(); Rendere i processi periodici rt_task_make_periodic(taskhighfrequency, now +..., SHORT_PERIOD_COUNT); rt_task_make_periodic(tasklowfrequency, now +..., LONG_PERIOD_COUNT); Settare le priorità in modo inversamente proporzionale alla durata del periodo rt_spv_rms(0);
Scheduling RM in RTAI 13
Scheduling EDF in RTAI Earliest Deadline First Si ottiene a partire dall algoritmo di scheduling FIFO Occorre eseguire il processo pronto che deve terminare prima RTAI semplifica l uso di questa politica di scheduling rendendo disponibile una funzione che rende possibile l esecuzione del processo con deadline più imminente void rt_task_set_resume_end_times(<resume>, <end>); Imposta gli istanti assoluti di resume e deadline di un processo. Esso viene deschedulato ed al risveglio è inserito nella coda dello scheduler in posizione dipendente dall istante assoluto entro cui deve terminare Non è specificata alcuna periodicità, ma è possibile definire un istante di resume relativo a quello precedente e deadline relativa al resume ottenuto indicando valori negativi di <resume> e <end>
Scheduling EDF in RTAI Creare un processo figlio fork(); Creare un agente real-time per ogni processo rt_task_init(nam2num( Task1 ), LOW_PR, 0, 0); rt_task_init(nam2num( Task2 ), HIGH_PR, 0, 0); Entrare in modalità real-time rt_make_hard_real_time(); Rendere i processi periodici rt_task_make_periodic(task1, now +..., PERIOD_1); rt_task_make_periodic(task2, now +..., PERIOD_2); Settare gli istanti di attivazione e di deadline per ogni processo rt_task_set_resume_end_times(now +..., -REL_DEADL_1); rt_task_set_resume_end_times(now +..., -REL_DEADL_2); Un processo al termine di ogni suo job deve risettare i propri istanti di attivazione e di deadline rt_task_set_resume_end_times(-period_n,-rel_deadl_n);
Scheduling EDF in RTAI 16