Implementace jádra

Jádro plní dvě základní funkce: implementuje mechanismus doručování zpráv a řídí plánování procesů. Mimo to obsahuje nejnižší úroveň obslužných rutin přerušení a zajišťuje převod hardwarového přerušení na zaslání zprávy příslušnému tasku. Mechanismus předávání zpráv i plánovač již byly popsány ve dřívějších sekcích, proto se zde uvedeme pouze poznámky sloužící jako vodítko pro implementaci.

Doposud jsme se v souvislosti s předáváním zpráv odkazovali na primitiva SEND, RECEIVE a SENDREC. Jejich skutečná implementace je realizována pomocí maker, jež jsou využívána ostatními vrstvami systému, včetně systémových knihoven. Makro se rozvine na vyvolání softwarového přerušení, které je nasměrováno na dále popisovanou rutinu jádra s_call. Parametry volání se předávají v registrech. Jde zejména o informaci o typu primitiva (SEND/RECEIVE/SENDREC), identifikace procesu, kterému se má zpráva předat, resp. od kterého se má zpráva převzít a pointer na buffer se zprávou (near pointer, v rámci adresového prostoru právě běžícího procesu). Pro určení odesílatele zprávy a přepočet virtuální adresy bufferu se zprávou potřebujeme určit proces, který primitivu zavolal. Tímto procesem však může být jedině právě běžící proces, jehož identifikaci v podobě pozice v tabulce procesů najdeme v proměnné cur_proc.

Přesný formát predávaných parametru je třeba stanovit a zdokumentovat.

Kernel sestává ze tří zdrojových souborů: PROC.C, MPX88.S a KERNEL88.S (viz pseudokódy). Poslední dva jsou napsány v assembleru, PROC.C je stejně jako zbytek systému v C.

Kernel obhospodaruje následující proměnné:

int cur_proc - index právě běžícího procesu v tabulce proc[]
struct struct_proc *proc_ptr; /* &proc[cur_proc]) */
 - pointer na prvek proc[] patřící právě běžícího procesu v tabulce 

struct struct_proc *bill_ptr; 
 - pointer na (uživatelský) proces, kterému se bude účtovat tik hodin

struct struct_proc *rdy_head[NQ];
 - pointer na pole začátků front běhuschopných procesů
struct struct_proc *rdy_tail[NQ];
 - pointer na pole konců front běhuschopných procesů

unsigned busy_map;
 - bitmapa: každý bit odpovídá jednomu tasku. Jednička na příslušném bitu indikuje, že se 
	obslužná rutina přerušení svázaného s daným taskem pokoušela předat tasku zprávu,
ale task byl zaneprázdněn. Proto se musí funkce interrupt() při dalším přerušení pokusit
zprávu doručit znovu. Zpráva je mezitím uložena na odpovídající pozici pole task_mess[NR_TASKS].

message task_mess[NR_TASKS]; 
	Pole pro uložení zpráv o přerušení, které dosud nemohly být doručeny příslušným taskům z důvodu jejich zaneprázdněnosti.

proc_ptr int_message - buffer pro zprávu, která se vytváří v době přerušení a odesílá se příslušnému tasku

int sig_procs - počet procesů, jimž má být doručen signál

Jednotlivé moduly obsahují zejména dále popsané funkce

MPX88.S

Nejnižší úroveň přepínání procesů a obsluhy přerušení. Obsahuje zejména tyto rutiny

KERNEL88.S

Implementuje skupinu pomocných nízkoúrovňových funkcí, které mohou být volány tasky (připomeňme, že jádro je s tasky slinkováno). Jde např. o funkce podporující kopírování bloků (lineární) paměti, povolování přerušení, vstup/výstup z portů atd., viz pseudokód. Jelikož těchto rutin využívají tasky, je nezbytné zdokumentovat jejich rozhraní a funkci a poskytnout odpovídající C-headery, které umožní volání rutin z C-kódu stejně jako by se volaly C-funkce. Parametry funkcí se tedy předávají přes zásobník ve volací konvenci podporované jazykem C.

PROC.C

Vyšší úroven obsluhy prerušení (prevod na zprávy), mechanismus dorucování zpráv, plánovac

Obsluha prerušení

Rutiny plánovače