PB173 - Ovladače jádra - Linux VIII. Jiří Slabý ITI, Fakulta Informatiky 16. 11. 2010 J. Slabý (ITI) PB173/01 16. 11. 2010 1 /1 Přerušení LDD3 kap. 7 a 10 • Práce s časem • Pozdržení vykonávání kódu (spánek) • Časovače • Odložené vykonání kódu • Přerušení HW • Změny v kontextu přerušení • Zámky • Alokace J. Slabý (ITI) PB173/01 16.11.2010 2/1 Pozdržení vykonávání Čekání na událost trvající pevně danou dobu O Spánek • Zapojení plánovače • Rozlišení: 1-10 ms (podle hodnoty hz - jiffies) O Busy-waiting Smyčka • Rozlišení: ns API • linux/delay.h • ad 1. ssleep, msleep • ad 2. mdelay, udelay, ndelay V jádře lze čekat jen omezenou dobu J. Slabý (ITI) PB173/01 16.11.2010 3/1 Časovače • Documentation/timers/* • Činnost v nastavených časech (i periodicky) • Kontext přerušení (nelze spát) • /proc/timer_iist (jen nová jádra) 2 druhy O Obyčejné • Fungují na každé architektuře • Založené na jiffies • Rozlišení: 1-10 ms O High-res • Jen pro vybrané architektury » Ve valné většině kódu není třeba • Rozlišení: ns J. Slabý (ITI) PB173/01 16.11.2010 4/1 Obyčejné časovače API • linux/timer.h, struct timer_list • DEFINE_TIMERS, setup_timerD • mod.timer (=del_timer+add_timer) • del_timer_sync static void my.fun (unsigned long data); static DEFINE.TIMER( my.timer , my.fun, 0, 30); static void my.fun (unsigned long data) { my.timer. data *= 2; mod-timer(&my_timer, jiffies + msecs.to.jiffies (data)) ; } mod-timer(&my_timer, jiffies + msecs.to.j if f ies (1 00)) ; del_timer_sync(&my_timer) ; Úkol: Každou vteřinu, kdy je modul v systému, vypsat hz a jiffies J. Slabý (ITI) PB173/01 16. 11. 2010 5/1 Odložené vykonání kódu Při potřebě vykonat kód, který nelze vykonat teď • Držím zámek, jsem v přerušení, ... • Nespecifikuje se pevně daný moment (na rozdíl od časovačů) 2 druhy O Workqueue O Tasklet Rozdíly « Rychlost zavolání • Kontext zavolání • Množství kódu (tj. rychlost vykonání) J. Slabý (ITI) PB173/01 16. 11. 2010 6/1 Workqueue a Speciální proces volající funkce ve frontě • Lze spát a Spustí se, až se plánovač rozhodne API • linux/workqueue.h, struct work.struct a Definice funkce (práce): declare_works, init_workd a Globální proces: • Zařazení do fronty: schedule_work, cancel.work.sync a Vlastní proces: • Vytvoření procesu: create.workqueue, destroy_workqueue a Zařazení do fronty: queue-work, cancel.work.sync a Delayed (zavolej nejdřív za ...): *_deiayed_work Úkol: nahrát modul ieee80211 (request jnodule). Nelze volat přímo v moduie_init a je nutný i vlastní proces J. Slabý (ITI) PB173/01 16. 11. 2010 7/1 Tasklet • Běží v kontextu přerušení (jako časovače) • Nelze spát a Musí být rychlý • Spustí se po příštím přerušení API • linux/interrupt.h, struct tasklet_struct • Definice funkce (taskletu): declare_tasklets, taskiet_initD • Zařazení do fronty: tasklet_schedule, tasklet.kill Úkol: vytvořit tasklet, spustit a vypsat function trace (dump_stack) J. Slabý (ITI) PB173/01 16. 11. 2010 8/1 Přerušení HW • HW informuje o změně stavu • Časovač tiknul, přišel paket, přečten blok z disku, ... • CPU přeruší chod programu/jádra a zavolá jádro • Priority přerušení • OS musí obsloužit přerušení • Zjistí zdroj a zavolá odpovídající ovladač (jeho obsluhu přerušení) • Přerušeni je identifikováno číslem (IRQ) • Vynuluje přerušení na řadiči přerušení Nutná podpora HW (CPU, řadiče, sběrnice, zařízení) J. Slabý (ITI) PB173/01 16. 11. 2010 9/1 Přerušení v Linuxu • 1inux/interrupt.h • request_irq, free_irq • Flags: hlavně irqf_shared • Návratová hodnota z obsluhy: irq_none, irq_handled • /proc/interrupts static irqreturn.t my.handler( int irq , void *data) { /* data == my.data */ return my.device.raised.interrupt ? IRQ-HANDLED : IRQ.NONE; } static int my.probe( struct pci.dev *pdev, ...) { /* enable device etc. */ my.data = kmalloc (...) ; ret = request.irq (pdev->irq , my.handler, IRQF.SHARED, "my", my.data); } Úkol: vytvořte obsluhu pro Combo (zatím vracejte irq_handled) J. Slabý (ITI) PB173/01 16. 11. 2010 10/1 Kontext přerušení Změny • Zámky a Třeba používat *_irqf lags varianty • Jinak by mohlo dojít k deadlocku • Alokace • gfp_atomic • A tedy nevelké alokace • Kód • Rychlý, krátký 16. 11. 2010 11/1 Úkol Práce s přerušením (součást domácího) O Vytvořit pojmenování (makra) pro registry O Spustit 100 ms periodický časovač (pro každé Combo zařízení) • Vyvolat z Comba přerušení 0x1000 (registr 0x60) O Navázat se v probe na přerušení (request_irq) O Povolit v Combu přerušení 0x1000 (registr 0x44) O Implementovat obsluhu • Přečíst stav (registr 0x40), vypsat stav - limitované • Nenula: odsouhlasit přerušení (registr 0x64), vrátit irq_handled » Jinak: vrátit irq_none Offset Len R/W Contents Meaning 0x0040 4B R bitmap Raised interrupts 0x0044 4B R/W bitmap Enabled interrupts 0x0060 4B W bitmap Raise interrupts 0x0064 4B W bitmap Acknowledge interrupts Tabulka: Specifikace baru 0 (pokračování z minula) J. Slabý (ITI) PB173/01 16. 11. 2010 12/1