1/83 Ada Podpora paralelismu Systémy real-time Omezující profily Praktický pohled na programování systémů v reálném čase Petr Holub hopet@ics.muni.cz Laboratoř pokročilých síťových technologií IA158 2014–04–30 2/83 Ada Podpora paralelismu Systémy real-time Omezující profily Přehled přednášky Ada Podpora paralelismu na úrovni jazyka Systémy real-time Plánování a spouštění vláken Řazení do front Časovače a události Komunikace mezi vlákny Omezující profily 3/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ada     “Regression testing?” What’s that? If it compiles, it is good, if it boots up it is perfect. – Linus Torvalds     Compilable but broken code is even worse than working code. – Alan Cox during a bright moment on the linux-kernel list     Ada: Ideally, when compiles fine it also runs fine. 4/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ada Ada 83/95/2005 jazyk orientovaný na spolehlivé aplikace: vojáci, letectví, ... WORM: write once read many silně typovaný jazyk podpora paralelismu enkapsulace, výjimky, objekty, správa paměti, atd. GNAT ◾ volně dostupný překladač, frontend k GCC materiály na webu ◾ (Annotated) Reference Manual http://www.adaic.org/standards/ada05.html ◾ http://stwww.weizmann.ac.il/g-cs/benari/books/index.html#ase ◾ http://en.wikibooks.org/wiki/Programming:Ada ◾ http://www.adahome.com/Tutorials/Lovelace/lovelace.htm ◾ http://www.pegasoft.ca/resources/boblap/book.html 5/83 Ada Podpora paralelismu Systémy real-time Omezující profily Na co se podívat Struktura balíků, enkapsulace, pojmenování souborů Typový systém Ada, typy a podtypy, ukazatele (access vs. access all), generika, objekty, atributy proměnných Správa paměti Generické kontejnery Volby kompilace: gnatmake hello.adb vs. gnatmake -gnatya -gnatyb -gnatyc -gnatye -gnatyf -gnatyi -gnatyk -gnatyl -gnatyn -gnatyp -gnatyr -gnatyt -g -gnato -gnatf -fstack-check hello.adb 6/83 Ada Podpora paralelismu Systémy real-time Omezující profily Co v Adě neuděláte ... tedy co v ní neuděláte (takhle). 1 if(c = ntoa(b)) {} 7/83 Ada Podpora paralelismu Systémy real-time Omezující profily Co v Adě neuděláte ... tedy co v ní neuděláte (takhle). 1 send(to, from, count) register short *to, *from; 3 register count; { 5 register n = (count + 7) / 8; switch(count % 8) { 7 case 0: do { *to = *from++; case 7: *to = *from++; 9 case 6: *to = *from++; case 5: *to = *from++; 11 case 4: *to = *from++; case 3: *to = *from++; 13 case 2: *to = *from++; case 1: *to = *from++; 15 } while(--n > 0); } 17 } Zdroj: https://en.wikipedia.org/wiki/Duff%27s_device Kopírování pole do memory-mapped výstupu, nikoli kopie pole. 8/83 Ada Podpora paralelismu Systémy real-time Omezující profily Co v Adě neuděláte ... tedy co v ní neuděláte (takhle). 1 if(c = ntoa(b)) {} 3 #define _ -F<00||--F-OO--; int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO() 5 { _-_-_-_ 7 _-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_ 9 _-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 11 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 13 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 15 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 17 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_ 19 _-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_ 21 _-_-_-_ } Zdroj: http://www0.us.ioccc.org/1988/westley.c 9/83 Ada Podpora paralelismu Systémy real-time Omezující profily Protected Types – Monitory Implementace monitorů ◾ funkce – nemohou měnit data procedury – mohou měnit data entry – strážený vstup, mohou měnit data ◾ efektivní paralelizace: podobne ReadWriteLocku v Javě funkce mohou přistupovat paralelně procedury a entries musí pracovat exkluzivně protected type Muj_Typ is 2 procedure Nastav_hodnotu (n : Integer); procedure Odnastav_hodnotu; 4 function Zjisti_hodnotu return Integer; entry Pockej_na_nastaveni (n : Integer); 6 private Hodnota : Integer; 8 Nastaveno : Boolean := False; end Muj_Typ; 10/83 Ada Podpora paralelismu Systémy real-time Omezující profily Protected Types – monitory 10 protected body Muj_Typ is procedure Nastav_hodnotu (n : Integer) is 12 begin Hodnota := n; 14 Nastaveno := True; end Nastav_hodnotu; 16 procedure Odnastav_hodnotu is 18 begin Nastaveno := False; 20 end Odnastav_hodnotu; 22 function Zjisti_hodnotu return Integer is begin 24 return Hodnota; end Zjisti_hodnotu; 26 entry Pockej_na_nastaveni 28 when Nastaveno is begin 30 null; end Pockej_na_nastaveni; 32 end Muj_Typ; 11/83 Ada Podpora paralelismu Systémy real-time Omezující profily Guarded Entries chránění dle privátního stavu protected type Chraneno_Stavem is 2 entry Vstup; private 4 I : Integer; end Chraneno_Stavem; 6 protected body Chraneno_Stavem is 8 entry Vstup when I > 0 is begin 10 null; end Vstup; 12 end Chraneno_Stavem; ◾ používat pouze privátní proměnné ◾ např. implementace mutexů a semaforů 12/83 Ada Podpora paralelismu Systémy real-time Omezující profily Guarded Entries Chránění dle atributů 1 protected type Chraneno_Stavem is entry Vstup; 3 private I : Integer; 5 end Chraneno_Stavem; 7 protected body Chraneno_Stavem is entry Vstup when Vstup’Count > 4 is 9 begin null; 11 end Vstup; end Chraneno_Stavem; ◾ možnost použití atributů ◾ atribut E’Count vrátí počet zablokovaných vláken na vstupu do entry E ◾ např. implementace bariér ◾ funguje bezpečně pouze u chráněných objektů, nikoli tasků 13/83 Ada Podpora paralelismu Systémy real-time Omezující profily Problém řízení přístupu ke zdrojům Aspekty synchronizace požadavků (Bloom, 1979) 1. typ požadované služby 2. pořadí požadavků 3. interní stav přijímajícího vlákna 4. priorita volajícího 5. parametry požadavků Priorita: RT systémy Parametry: requeue 14/83 Ada Podpora paralelismu Systémy real-time Omezující profily Problém řízení přístupu ke zdrojům Definice příkladu problému: ◾ n zdrojů (vidliček v příborníku) ◾ každé vlákno si může požadovat alokaci 1 . . . m zdrojů (vidliček) kde m ≤ n Problém alokace více zdrojů najednou: ◾ musím vstoupit do procedury, abych ověřil dostupnost zdrojů Možné řešení: ◾ pollování (zodpovědnost vlákna) ◾ rodiny entries (entry families) pro malé m ◾ podpora přístupu k in parametrům předávaným v rámci volání rendezvous – možnost jejich použití ve stráži není v Adě podporováno implementováno např. v jazce SR (Synchronizing Resources) problém s efektivitou implementace (bariéra se musí vyhodnocovat při každém řazení vlákna do fronty entry, nikoli jen jednou per entry) ◾ requeue 15/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rodiny entries Úplná formální signatura entry accept Entry_Name(Family_Index)(P : Parameters) do 2 -- sequence of statements exception 4 -- exception handling part end Entry_Name; Rodiny entries ◾ např. prioritizace a odlišení volajících vláken task Multiplexer is 2 entry Channel(1..3)(X : in Data); end Multiplexer; 16/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rodiny entries Příklad použití s vláknem ◾ multiplexer vynucuje pořadí vstupů cyklicky 1, 2, 3 1 task body Multiplexer is begin 3 loop for I in 1..3 loop 5 accept Channel(I)(X : in Data) do -- consume input data on channel I 7 end Channel; end loop; 9 end loop; end Multiplexer; 17/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rodiny entries Příklad řízení zdrojů 1 type Request_Range is range 1 .. Max; 3 protected Resource_Controller is entry Allocate(Request_Range)(R : out Resource); 5 procedure Release(R : Resource; Amount : Request_Range); private 7 Free : Request_Range := Request_Range’Last; end Resource_Controller; 9 protected body Resource_Controller is 11 entry Allocate(for F in Request_Range)(R : out Resource) when F <= Free is 13 begin Free := Free - F; 15 end Allocate; procedure Release(R : Resource; Amount : Request_Range) is 17 begin Free := Free + Amount; 19 end Release; end Resource_Controller; 18/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rodiny entries Příklad řízení zdrojů Problémy ◾ nevhodné pro větší množství alokovatelných zdrojů v jednom požadavku (m) ◾ v případě soutěžení je výběr náhodný (prioritu lze nastavovat v rámci Real-Time Systems Annex) 19/83 Ada Podpora paralelismu Systémy real-time Omezující profily „Eggshell” model volání chráněného objektu 20/83 Ada Podpora paralelismu Systémy real-time Omezující profily „Eggshell” model volání chráněného objektu Přednost entry calls čekajících ve frontě Zámek vnější slupky ◾ nedovolí vstup do slupky, pokud je jiné vlákno aktivní voláním procedury nebo entry ◾ po vstupu se vyhodnocuje asociovaná podmínka (stráž) ◾ tento mechanismus zajišťuje bezpečnost použití ’Count 21/83 Ada Podpora paralelismu Systémy real-time Omezující profily „Eggshell” model volání chráněného objektu Vnitřní slupka ◾ po výstupu z každé procedury a entry se vyhodnocují podmínky a eventuálně se propouští volání čekající na vnitřní slupce 22/83 Ada Podpora paralelismu Systémy real-time Omezující profily requeue Jak poslat za dveře někoho, koho už jsme si pustili do místnosti? requeue umožňuje vysunout aktivní vlákno v chráněném objektu do fronty před vnitřní slupku ◾ nové volání musí mít stejnou signaturu ◾ implicitně není přerušitelné pomocí abort, aby objekt nezůstal v rozpracovaném stavu ◾ nové volání může být přerušitelné requeue with abort requeue umí fungovat i napříč více chráněnými objekty/úlohami ◾ neobvyklé, používat opatrně 23/83 Ada Podpora paralelismu Systémy real-time Omezující profily requeue type Request_Range is range 1 .. Max; 2 protected Resource_Controller is 4 entry Allocate(R : out Resource; Amount : Request_Range); procedure Release(R : Resource; Amount : Request_Range); 6 private entry Assign(R : out Resource; Amount : Request_Range); 8 Free : Request_Range := Request_Range’Last; New_Resources_Released : Boolean := False; 10 To_Try : Natural := 0; ... 12 end Resource_Controller; 14 protected body Resource_Controller is entry Allocate(R : out Resource; Amount : Request_Range) 16 when Free > 0 is begin 18 if Amount <= Free then Free := Free - Amount; 20 -- allocate else 22 requeue Assign; end if; 24 end Allocate; 24/83 Ada Podpora paralelismu Systémy real-time Omezující profily requeue entry Assign(R : out Resource; Amount : Request_Range) 2 when New_Resources_Released is begin 4 To_Try := To_Try - 1; if To_Try = 0 then 6 New_Resources_Released := False; end if; 8 if Amount <= Free then Free := Free - Amount; 10 -- allocate else 12 requeue Assign; end if; 14 end Assign; 25/83 Ada Podpora paralelismu Systémy real-time Omezující profily requeue procedure Release(R : Resource; Amount : Request_Range) is 2 begin Free := Free + Amount; 4 -- free resources if Assign’Count > 0 then 6 To_Try := Assign’Count; New_Resources_Released := True; 8 end if; end Release; 10 end Resource_Controller; 26/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ada: Tasks, Rendezvous Koncept CSP: Communicating Sequential Processes ◾ Hoare, 1978 ◾ paralelně běžící sekvenční procesy ◾ komunikace: zasílání zpráv ◾ synchronizace: synchronní zasílání zpráv odesílatel se zablokuje, dokud příjemce není schopen přijmout zprávu příjemce se zablokuje, dokud není schopen od odesílatele přijmout zprávu 27/83 Ada Podpora paralelismu Systémy real-time Omezující profily Tasks, Rendezvous 28/83 Ada Podpora paralelismu Systémy real-time Omezující profily Tasks task ◾ lokálně definované běží od začátku rozsahu, v němž jsou definované ◾ dynamicky alokované access typ alokace pomocí new běží až od alokace ◾ pole tasků ukončování ◾ spontánní ◾ abort 29/83 Ada Podpora paralelismu Systémy real-time Omezující profily Tasks task T is 2 end T; 4 task body T is begin 6 makam; end T; 8 task type T_Type is 10 end T; 12 task body T_Type is begin 14 loop makam; 16 end loop; end T_Type; 18 Pole_T : array (1..10) of T_Type; 20 type T_Type_Access is access T_Type; 22 Dynamicky_T : T_Type_Access; Dynamicky_T := new T_Type; 30/83 Ada Podpora paralelismu Systémy real-time Omezující profily Parametrizace vláken předávání parametrů při vzniku vlákna užitečné s typy vláken 1 type Monitor_Procedure_Type is access procedure; 3 task type Monitor_Task_Type (Mon_Proc : Monitor_Procedure_Type) is entry Run; 5 entry Stop; entry Request_Terminate; 7 end Monitor_Task_Type; 31/83 Ada Podpora paralelismu Systémy real-time Omezující profily Parametrizace vláken 1 task body Monitor_Task_Type is Finish_Flag : Boolean := False; 3 Terminate_Flag : Boolean := False; begin 5 while not Terminate_Flag loop 7 select accept Run; 9 while not (Finish_Flag or Terminate_Flag) loop 11 select accept Stop do 13 Finish_Flag := True; end Stop; 15 else Mon_Proc.all; 17 end select; end loop; 19 or accept Request_Terminate do 21 Terminate_Flag := True; end Request_Terminate; 23 end select; Finish_Flag := False; 25 end loop; end Monitor_Task_Type; 32/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rendezvous místa synchronizace – předávání dat entry ◾ deklarace rendezvous bodu ◾ in, out, in out parametry accept ◾ implementace v těle tasku 33/83 Ada Podpora paralelismu Systémy real-time Omezující profily Tasks, Rendezvous procedure Task1 is 2 task Vlakno is 4 entry ZadejX (X : in Integer); entry PrectiX (X : out Integer); 6 end Vlakno; 8 task body Vlakno is Hodnota : Integer; 10 begin accept ZadejX (X : in Integer) do 12 Hodnota := X; end ZadejX; 14 Hodnota := Hodnota + 1; accept PrectiX (X : out Integer) do 16 X := Hodnota; end PrectiX; 18 end Vlakno; 20 Chci_Inkrementovat : Integer; 22 begin Vlakno.ZadejX(Chci_Inkrementovat); 24 Vlakno.PrectiX(Chci_Inkrementovat); end Task1; 34/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rendezvous select ◾ výběr z více accept možností 1 task body T is begin 3 loop select 5 accept Rande1 do neco; 7 end Rande1; or 9 accept Rande2 do neco; 11 end Rande2; neco; 13 accept Rande3 do neco; 15 end Rande3; or 17 terminate; end loop; 19 end T; 35/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rendezvous select ◾ časovaný výběr 1 task body T is begin 3 loop select 5 accept Rande1 do neco; 7 end Rande1; or 9 delay 10.0; taky_neco; 11 end select; end loop; 13 end T; 36/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rendezvous select ◾ časovaný výběr 1 task body T is begin 3 loop select 5 accept Rande1 do neco; 7 end Rande1; else -- ekvivalent "or delay 0.0" 9 null; -- busy waiting end select; 11 end loop; end T; 37/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rendezvous výjimky během rendezvous ◾ jsou doručeny jak volajícímu vláknu, tak i vlastnímu vláknu ◾ pokud výjimka není ošetřena ve vláknu, je vlákno ukončeno a výjimka se nepropaguje do rodiče (považováno za příliš disruptivní) begin 2 select accept Volani do 4 ... raise Chyba; 6 ... end Volani; 8 end select; exception 10 when Chyba => Naprav_Stav; 12 when other => Oznam_Uzivateli; 14 end; 38/83 Ada Podpora paralelismu Systémy real-time Omezující profily Rendezvous výjimky během rendezvous ◾ jsou doručeny jak volajícímu vláknu, tak i vlastnímu vláknu ◾ pokud výjimka není ošetřena ve vláknu, je vlákno ukončeno a výjimka se nepropaguje do rodiče (považováno za příliš disruptivní) -- 2 -- 4 begin T.Volani; 6 exception when Chyba => 8 Oznam_Uzivateli; end; 39/83 Ada Podpora paralelismu Systémy real-time Omezující profily Chráněné entries u vláken podobně jako u chráněných objektů s mírně odlišnou syntaxí task body Ukazka is 2 Zinicializovano : Boolean := False; Hodnota : Data; 4 begin loop 6 select when Zinicializovano => 8 accept Cti (H : out Data) do H := Hodnota; 10 end; or 12 accept Zapis (H : in Data) do Hodnota := H; 14 end; Zinicializovano := True; 16 end select; end loop; 18 end Ukazka; ◾ podmínka se vyhodnocuje při každém průchodu přes select ◾ pokud není žádná podmínka splněna, je vyhozena výjimka Program_Error (možno použít strukturu select ... else ... end select;) ◾ změna hodnot mezi testem a rendezvous (viz komentář u ’Count) 40/83 Ada Podpora paralelismu Systémy real-time Omezující profily Atributy vláken Ada 95 Quality and Style Guide, Section 6.2.3 ’Terminated ◾ bezpečné pouze testování na True (po ukončení vlákno nemůže obživnout) ’Callable ◾ bezpečné pouze testování na False (po ukončení vlákno nemůže obživnout) 41/83 Ada Podpora paralelismu Systémy real-time Omezující profily Atributy vláken Ada 95 Quality and Style Guide, Section 6.2.3 ’Count ◾ chování vlákna by nemělo záviset na tomto atributu (používat raději jen s chráněnými objekty) select 2 when Transmit’Count > 0 and Receive’Count = 0 => accept Transmit; 4 ... or 6 accept Receive; ... 8 end select; stav ’Count se může změnit mezi vyhodnocením a následnou akcí (např. volající použil časově omezené volání a mezi testem a accept se ukončil) ◾ u chráněných objektů: každá práce s frontou je chráněná (viz eggshell model) 42/83 Ada Podpora paralelismu Systémy real-time Omezující profily Chráněné entries s timeoutem Nelze implementovat pomocí chráněných typů, jsou třeba vlákna task body Ukazka is 2 Zinicializovano : Boolean := False; Hodnota : Data; 4 begin loop 6 select when Zinicializovano => 8 accept Cti (H : out Data) do H := Hodnota; 10 end; or 12 delay 1.0; -- neco 14 end select; end loop; 16 end Ukazka; 43/83 Ada Podpora paralelismu Systémy real-time Omezující profily Vynucené ukončování vláken Alternativní příklad select 2 T.Ukonci; or 4 delay 180*Seconds; abort T; 6 end select; nebo pokud nevěříme, že se úloha po T.Ukonci ukončí select 2 T.Ukonci; delay 60*Seconds; 4 or delay 180*Seconds; 6 end select; abort T; ◾ pozor na nebezpečí použití abort pragma Restrictions (No_Abort_Statements); ◾ ani druhé řešení není blbuvzdorné (pokud se T.Ukonci může zakousnout v rámci bloku accept, použití requeue) 44/83 Ada Podpora paralelismu Systémy real-time Omezující profily Asynchronous Transfer of Control Potřeba rychle reagovat na asynchronní události ◾ reakce na chyby (např. výpadek HW, kvůli němuž se akce nikdy nedokončí) ◾ změny režimů v důsledku (neočekávaných) událostí ◾ dosažení co nejlepšího výsledku v případě iterativního přerušitelného výpočtu ◾ přerušení uživatelem 45/83 Ada Podpora paralelismu Systémy real-time Omezující profily Asynchronous Transfer of Control Struktura select 2 -- triggering_statement delay 5.0; 4 -- post_trigger_part Put_Line ("Tudy cesta nevede!"); 6 then abort -- abortable_part 8 Prevelevelmidlouhe_Volani; end select; ◾ pokud abortable_part doběhne dříve než triggering_statement, pokusí se ukončit triggering_statement ◾ pokud triggering_statement doběhne dřív než abortable_part, je abortable_part ukončena a provede se část post_trigger_part ◾ triggering_statement – v Ada 95 delay/entry, v Ada 2005 i procedury ◾ abortable_part nemusí být implementována jako samostatný task 46/83 Ada Podpora paralelismu Systémy real-time Omezující profily Asynchronous Transfer of Control Příklad: iterativní dlouhý výpočet, chceme nejlepší odhad v době, kdy jej potřebujeme (J. Barnes, Ada 95) ◾ chráněný objekt na předávání posledního výsledku 1 begin Result is procedure Set_Estimate(X : in Data); 3 function Get_Estimate return Data; private 5 Est : Data; end; ◾ signalizační objekt (např. uživatel chce výsledek) begin Trigger is 2 entry Wait; -- when Flag 4 procedure Signal; private 6 Flag : Boolean := False; end; 47/83 Ada Podpora paralelismu Systémy real-time Omezující profily Asynchronous Transfer of Control Příklad: iterativní dlouhý výpočet, chceme nejlepší odhad v době, kdy jej potřebujeme (J. Barnes, Ada 95) ◾ použití 1 select Trigger.Wait; 3 then abort Computation; 5 end select; 1 Trigger.Signal; E := Result.Get_Estimate; ◾ oddělení logiky výpočtu od jeho ukončování – výpočet nemusí zjišťovat, kdy má končit 48/83 Ada Podpora paralelismu Systémy real-time Omezující profily Asynchronous Transfer of Control Výjimky při ATC ◾ pokud se odehraje jen jedna výjimka (v jedné z částí), je možno ji zachytit ◾ pokud se odehrají dvě výjimky současně v řídící i přerušitelné části, je výjimka z přerušitelné části ztracena 49/83 Ada Podpora paralelismu Systémy real-time Omezující profily Plánování a spouštění vláken Task dispatching ◾ proces výběru vlákna, které má běžet na daném procesoru Dispatching points ◾ místa v kódu, kde dochází k přepínání ◾ vždy: 1. blokování na volání (rendezvous, chráněný objekt) 2. ukončování úlohy ◾ další místa jsou definována annexem pro specifické politiky Politika plánování se nastavuje per partition ◾ partition – dělení aplikace podle Distributed Annex Nedeterminismus v Adě je zapříčiněn ◾ plánováním a prokládáním běhu vláken ◾ výběrem varianty ve výrazech select ◾ chování chráněných objektů 50/83 Ada Podpora paralelismu Systémy real-time Omezující profily Dynamické priority Base priority – základní priorita přiřazená vláknu ◾ lze měnit pomocí Ada.Dynamic_Priorities package Ada.Dynamic_Priorities is 2 procedure Set_Priority 4 (Priority : System.Any_Priority; T : Ada.Task_Identification.Task_Id := 6 Ada.Task_Identification.Current_Task); 8 function Get_Priority (T : Ada.Task_Identification.Task_Id := 10 Ada.Task_Identification.Current_Task) return System.Any_Priority; 12 end Ada.Dynamic_Priorities; Active priority – skutečná priorita v daném okamžiku (ovlivněná děděním) Dynamic ceiling priority – lze měnit pomocí atributu ’Priority ◾ potenciál vyhazování Program_Error výjimek (bounded error) – pořadí: snížení ceiling priority musí být až po snížení priority vlákna 51/83 Ada Podpora paralelismu Systémy real-time Omezující profily Preemptive Fixed Priority Dispatching pragma Task_Dispatching_Policy(FIFO_Within_Priorities); Priorita ◾ definuje fronty, z nichž se odebírají úlohy v případě výběru ◾ vybírá se ze začátku nejprioritnější neprázdné fronty ◾ systém musí podporovat: minimálně 30 úrovní System.Priority minimálně 1 úroveň System.Interrupt Priority Dispatching points specificky pro Preemptive Fixed Priority Dispatching ◾ kdykoli se objeví spustitelné (runnable) vlákno s vyšší prioritou ⇒ preemtpivita ◾ kdykoli se v kódu objeví delay, který už vypršel delay 0.0; Podpora i před Ada 2005 ◾ velmi dobře prostudované chování: ∼ 30 let výzkumu a používání 52/83 Ada Podpora paralelismu Systémy real-time Omezující profily Preemptive Fixed Priority Dispatching preempce, ztráta zděděné priority delay, blokování změna základní priority Hlava Konec změna základní/aktivní priority 53/83 Ada Podpora paralelismu Systémy real-time Omezující profily Round-Robin Dispatching pragma Task_Dispatching_Policy(Round_Robin_Within_Priorities); Běh vlákna je omezen kvantem Oproti Preemptive Fixed Priority Dispatching přidává task dispatching do kódu kdykoli dojde k využití kvanta vláknem (execution time budget = kvantum) ◾ přerušené vlákno je zařazeno na konec fronty své priority Mapuje poměrně dobře na SCHED_RR politiku POSIXu ◾ musí se ošetřit, aby kvantum neexpirovalo během aktivace a rendezvous 54/83 Ada Podpora paralelismu Systémy real-time Omezující profily Round-Robin Dispatching package Ada.Dispatching.Round_Robin is 2 pragma Unimplemented_Unit; 4 Default_Quantum : constant Ada.Real_Time.Time_Span := 6 Ada.Real_Time.Milliseconds (10); 8 procedure Set_Quantum (Pri : System.Priority; 10 Quantum : Ada.Real_Time.Time_Span); 12 procedure Set_Quantum (Low, High : System.Priority; 14 Quantum : Ada.Real_Time.Time_Span); 16 function Actual_Quantum (Pri : System.Priority) return Ada.Real_Time.Time_Span; 18 function Is_Round_Robin (Pri : System.Priority) return Boolean; 20 end Ada.Dispatching.Round_Robin; 55/83 Ada Podpora paralelismu Systémy real-time Omezující profily Non-Preemptive Fixed Priority Dispatching pragma Task_Dispatching_Policy (Non_Preemptive_FIFO_Within_Priorities); Vlákno nemůže být přerušeno vláknem vyšší priority kdykoli. ◾ může však být přerušeno vláknem ošetřujícím interrupt (vč. časovače), ale pak je řízení vráceno původnímu vláknu, i když je k dispozici vlákno s vyšší prioritou 56/83 Ada Podpora paralelismu Systémy real-time Omezující profily Non-Preemptive Fixed Priority Dispatching Lze udělat kooperativní preempci delay 0.0 ◾ jazyk definuje tzv. bounded error pokud se z akce chráněného objektu volá potenciálně blokující operace select accept entry call delay vytváření nebo aktivace vlákna (task) volání podprogramu, jehož tělo obsahuje potenciálně blokující operaci ◾ bounded error – specifikace jazyka vyjmenovává seznam následků chyby, mimálně obsahuje vyhození výjímky Program_Error ◾ výjimku tvoří chráněné objekty implementující interrupt handlery – lze snadno identifikovat, protože používají pragma Interrupt Handler a/nebo pragma Attach Handler ⇒ vlákno se nemůže uspat/přerušit uvnitř chráněného objektu ⇒ není třeba dělat ceiling priority ⇒ jednodušší implementace 57/83 Ada Podpora paralelismu Systémy real-time Omezující profily Earliest Deadline First Dispatching pragma Task_Dispatching_Policy(EDF_Across_Priorities); musí být použito dohromady s pragma Locking_Policy(Ceiling_Locking) Je-li systém naplánovatelný, pak jej lze naplánovat pomocí EDF. Každá úloha ma přiřazený termín dokončení – deadline ◾ ve frontě jsou úlohy seřazeny podle termínu dokončení ◾ z fronty se odebírá úloha s nejbližším termínem Kombinace s prioritami ◾ více front, odebírá se z nejprioritnější neprázdné ◾ aktivní priorita vlákna/úlohy není už přímo odvozena od základní priority 58/83 Ada Podpora paralelismu Systémy real-time Omezující profily Earliest Deadline First Dispatching Komplikovanější koncept aktivní priority ◾ pokud nějaké vlákno B pracuje v chráněném objektu (tedy s ceiling prioriton P) a vlákno A má dřívější termín, je vlákno A zařazeno do fronty s prioritou větší než P (existuje-li taková fronta) ◾ pokud nikdo nepracuje s chráněnými objekty, je vlákno A zařazeno do fronty s prioritou Priority’First ◾ vlákno A podědí aktivní prioritu fronty Dispatching points pro vlákno A při použití EDF ◾ změna termínu A ◾ zkrácení termínu pro úlohu B ve frontě s prioritou A, pokud nový termín B je nastane dříve jako termín A ◾ pokud se objeví úloha ve frontě s prioritou vyšší než A Problém s implementovatelností na běžných OS (poznámka ve specifikaci balíku v GNATu) ◾ implementováno např. pro MARTE OS (http://marte.unican.es/) 59/83 Ada Podpora paralelismu Systémy real-time Omezující profily Earliest Deadline First Dispatching package Ada.Dispatching.EDF is 2 subtype Deadline is Ada.Real_Time.Time; 4 Default_Deadline : constant Deadline := Ada.Real_Time.Time_Last; 6 procedure Set_Deadline 8 (D : Deadline; T : Ada.Task_Identification.Task_Id := 10 Ada.Task_Identification.Current_Task); 12 procedure Delay_Until_And_Set_Deadline (Delay_Until_Time : Ada.Real_Time.Time; 14 Deadline_Offset : Ada.Real_Time.Time_Span); 16 function Get_Deadline (T : Ada.Task_Identification.Task_Id := 18 Ada.Task_Identification.Current_Task) return Deadline; 20 end Ada.Dispatching.EDF; 60/83 Ada Podpora paralelismu Systémy real-time Omezující profily Srovnání metod FIFO ◾ dobře předpověditelné chování EDF ◾ nejlepší využití zdrojů ◾ pokud jsou dané termíny splnitelné, EDF je dokáže naplánovat Round-robin ◾ férové rozdělené zdrojů 61/83 Ada Podpora paralelismu Systémy real-time Omezující profily Řazení do front chráněných objektů Problém blokování prioritních vláken méně duležitými při čekání na chráněném objektu. Problém, pokud je současně otevřených (povolených) více variant v rámci select ... accept ... ◾ jazyk nespecifikuje pořadí pragma Queuing_Policy(Priority_Queuing); Uspořádání z pohledu volání jednoho entry: priority + FIFO ◾ vybírá se z neprázdné fronty s nejvyšší prioritou ◾ mezi vlákny stejné priority se vybírá FIFO podle pořadí volání Uspořádání z pohledu soutěže mezi různými entries a/nebo otevřenými cestami select: textové pořadí + family entry index ◾ pokud je otevřeno více volání a volající mají stejné priority, volí se podle uspořádání (textu) v definici (týká se i pokud ve stejnou dobu vyexpirují select ... delay ...) – kvůli jednoduchosti a zajištění determinismu ◾ v případě soutěže mezi volánímí stejné family entry má nižší index prioritu 62/83 Ada Podpora paralelismu Systémy real-time Omezující profily Zpoždění vzbuzení Vzbuzení po použití delay a delay until je nejdříve se specifikovaném okamžiku, ale může nastat i později ◾ zpoždění se označuje jako lateness Použití delay a delay until má nějakou režii i v případě, že se fakticky nečeká (tj. parametry vyustí v delay 0.0) ◾ režie se promítá do kódu v případě specifikace dispatching points pomocí delay 0.0 63/83 Ada Podpora paralelismu Systémy real-time Omezující profily Zpoždění vzbuzení Příklad pro GNATforLEON http://polaris.dit.upm.es/ ~ork/download/opm-2.1.0.pdf The implementation shall document the following metrics (only those metrics that are significant in the context of the Ravenscar profile are cited): ◾ An upper bound on the execution time, in processor clock cycles, of a delay until statement whose requested value of the delay expression is less than or equal to the value of Real Time.Clock at the time of executing the statement. The measured value is equal to 740 processor clock cycles. 64/83 Ada Podpora paralelismu Systémy real-time Omezující profily Zpoždění vzbuzení Příklad pro GNATforLEON http://polaris.dit.upm.es/ ~ork/download/opm-2.1.0.pdf The implementation shall document the following metrics (only those metrics that are significant in the context of the Ravenscar profile are cited): ◾ An upper bound on the lateness of a delay until statement, in a situation where the value of the requested expiration time is after the time the task begins executing the statement, the task has sufficient priority to preempt the processor as soon as it becomes ready, and it does not need to wait for any other execution resources. The upper bound is expressed as a function of the difference between the requested expiration time and the clock value at the time the statement begins execution. The lateness of a delay until statement is obtained by subtracting the requested expiration time from the real time that the task resumes execution following this statement. The following measurements have been performed: One task + background task The delay until lateness upper bound for a call to a delay until statement is 8051 clock cycles (161 µs), using a 50 MHz system clock. This lateness occurs when the time of the delay until coincides with a second boundary. It must be noted that the clock interrupt occurs every second in the kernel tested. If the time of the delay until statement does not coincide with a clock interrupt, the lateness upper bound for the execution of a delay until statement is 7061 clock cycles (141.2 µs). 65/83 Ada Podpora paralelismu Systémy real-time Omezující profily Zpoždění vzbuzení Příklad pro GNATforLEON http://polaris.dit.upm.es/ ~ork/download/opm-2.1.0.pdf The implementation shall document the following metrics (only those metrics that are significant in the context of the Ravenscar profile are cited): ◾ An upper bound on the lateness of a delay until statement, in a situation where the value of the requested expiration time is after the time the task begins executing the statement, the task has sufficient priority to preempt the processor as soon as it becomes ready, and it does not need to wait for any other execution resources. The upper bound is expressed as a function of the difference between the requested expiration time and the clock value at the time the statement begins execution. The lateness of a delay until statement is obtained by subtracting the requested expiration time from the real time that the task resumes execution following this statement. The following measurements have been performed: N tasks + background task The lateness of delay until for N tasks is 294825.84+7×N µs when the time of the delay until coincides with a clock interrupt. Otherwise, it is 201.8 + 7 N× µs. 66/83 Ada Podpora paralelismu Systémy real-time Omezující profily Hodiny reálného času Ada.Real_Time – monotónní hodiny s vysokým rozlišením ◾ Time – vyjádření časového okamžiku ◾ Time_Span – vyjádření rozsahu trvání/intevalu ◾ srovnání (minimálních) požadavků na hodiny v Adě Calendar Real_Time rozsah času 500 let 50 let rozsah intervalu 1 den ± 1 hodina přesnost 20 ms 20 µs Rozsah Real_Time může být menší na platformách se slovem kratším jak 32 b. with Ada.Real_Time; use Ada.Real_Time; 2 begin 4 T_One : Time := Clock; TS : Time_Span := To_Time_Span(1.0); 6 T_Two : Time := T_One + TS; delay until T_Two; 8 delay To_Duration (TS); end; 67/83 Ada Podpora paralelismu Systémy real-time Omezující profily Časovače událostí Ada.Real_Time.Timing_Events Využití pro událostmi řízené programování bez vláken a komplikace kódu pomocí delay package Ada.Real_Time.Timing_Events is 2 type Timing_Event is tagged limited private; 4 type Timing_Event_Handler 6 is access protected procedure (Event : in out Timing_Event); 8 procedure Set_Handler (Event : in out Timing_Event; 10 At_Time : Time; Handler : Timing_Event_Handler); 12 procedure Set_Handler 14 (Event : in out Timing_Event; In_Time : Time_Span; 16 Handler : Timing_Event_Handler); 18 function Current_Handler (Event : Timing_Event) return Timing_Event_Handler; 20 procedure Cancel_Handler 22 (Event : in out Timing_Event; Cancelled : out Boolean); 24 function Time_Of_Event (Event : Timing_Event) return Time; 68/83 Ada Podpora paralelismu Systémy real-time Omezující profily Časovače událostí Timing_Event ◾ tagovaný typ – možnost rozšíření o vlastní data ◾ privátní ne-abstraktní typ – nepotřebuje run-time dispatching Timing_Event_Handler ◾ obdoba obsluhy přerušení ◾ ukazatel na access protected procedure Set_Handler ◾ varianta s absolutním časem ◾ varianta s relativním časem ◾ null místo ukazatele na proceduru vymaže časovač (ekvivalent Cancel_Handler) ◾ opakované volání přepisuje budoucí událost Spuštění události ◾ co nejdříve poté, co uplyne specifikovaný čas ◾ z důvodů efektivity se obvykle pověsí na přerušení hodin ≤ 10 ms (obdobně jako ošetřování delay ve vláknech) Nevýhoda: kód běží s prioritou Interrupt_Priority ◾ pro složitější a déle běžící úlohy je lépe používat vlákna ◾ míněno jako lightweight mechanismus pro omezené platformy 69/83 Ada Podpora paralelismu Systémy real-time Omezující profily Časovače událostí protected Watchdog is 2 pragma Interrupt_Priority (Interrupt_Priority’Last); 4 entry Alarm_Control; procedure Call_In; 6 private 8 procedure Timer(Event : in out Timing_Event); Alarm : Boolean := False; 10 end Watchdog; 12 Fifty_Mil_Event : aliased Timing_Event; TS : Time_Span := Milliseconds(50); 14 Set_Handler(Fifty_Mil_Event, TS, Timer’Access); Aplikace musí volat Call_In nejpozději 1× za 50 ms Alarm_Control umožňuje reagovat na vzniknuvší alarm Zdroj: Burns & Wellings: Concurrent and Real-Time Programming in Ada 70/83 Ada Podpora paralelismu Systémy real-time Omezující profily Časovače událostí protected body Watchdog is 2 entry Alarm_Control when Alarm is begin 4 Alarm := False; end Alarm_Control; 6 procedure Timer(Event : in out Timing_Event) is 8 begin Alarm := True; 10 -- Note no use is made of the parameter in this example end Timer; 12 procedure Call_in is 14 begin Set_Handler(Fifty_Mil_Event, TS, Timer’Access); 16 -- This call to Set_Handler cancels the previous call end Call_in; 18 end Watchdog; Zdroj: Burns & Wellings: Concurrent and Real-Time Programming in Ada 71/83 Ada Podpora paralelismu Systémy real-time Omezující profily Odlehčená komunikace mezi vlákny Definice efektivnějších komunikačních nástrojů než jsou rendezvous ◾ nízkoúrovňovější nástroje umožňuje efektivnější implementaci ◾ problém Ady 83: vysokoúrovňová abstrakce (rendezvous) se musela používat i pro implementaci nízkoúroňových primitiv (typu semaforů) ⇒ inverze abstrakce ◾ řešení v Adě 95: chráněné objekty synchronní řízení vláken asynchronní řízení vláken 72/83 Ada Podpora paralelismu Systémy real-time Omezující profily Odlehčená komunikace mezi vlákny Synchronní komunikace mezi vlákny package Ada.Synchronous_Task_Control is 2 type Suspension_Object is limited private; 4 procedure Set_True (S : in out Suspension_Object); procedure Set_False (S : in out Suspension_Object); 6 function Current_State (S : Suspension_Object) return Boolean; procedure Suspend_Until_True (S : in out Suspension_Object); ◾ ekvivalent wait/notify ◾ Set_True, Set_False, Current_Stat jsou vzájemně atomické a neblokující ◾ Suspend_Until_True překlopí suspension object zpět na False 73/83 Ada Podpora paralelismu Systémy real-time Omezující profily Odlehčená komunikace mezi vlákny Asynchronní komunikace mezi vlákny package Ada.Asynchronous_Task_Control is 2 pragma Unimplemented_Unit; 4 procedure Hold (T : Ada.Task_Identification.Task_Id); procedure Continue (T : Ada.Task_Identification.Task_Id); 6 function Is_Held (T : Ada.Task_Identification.Task_Id) return Boolean; 8 end Ada.Asynchronous_Task_Control; ◾ umožňuje zasuspendovat jiné vlákno – potenciálně nebezpečné ◾ koncept idle task priority ◾ suspendování se provádí pomocí snížení priority pod idle task priority volání Hold na vlákno řízené EDF jej dočasně vyloučí z EDF dispatching points odpovídají plánovači, kterým jsou vlákna v daném okamžiku řízena řeší problém, aby se vlákno nezasuspednovalo uvnitř chráněného objektu (nejsou v něm dispatching points) pokud je zavolán accept zasuspendovaného vlákna, je vykonán, protože podědí prioritu volajícího pokud je vlákno blokováno uvnitř chráněného objektu v čekání na otevření stráže entry, je uvolněno, pokud je se stráž otevře a vlákno je jediné ve frontě 74/83 Ada Podpora paralelismu Systémy real-time Omezující profily Možnosti omezení pragma Restrictions – kontrolované před během programu No_Task_Hierarchy All (non-environment) tasks only depend directly on the environment task. No_Nested_Finalization Objects with controlled parts, and access types that designate such objects, are declared only at library level. No_Abort_Statement There are no abort statements. No_Terminate_Alternatives There are no select statements with terminate alternatives. No_Task_Allocators There are no allocators for task types or types containing task subcomponents. No_Implicit_Heap_Allocation There are no operations that implicitly require heap storage allocation to be performed by the implementation. For example, the concatenation of two strings usually requires space to be allocated on the heap to contain the result. 75/83 Ada Podpora paralelismu Systémy real-time Omezující profily Možnosti omezení pragma Restrictions – kontrolované před během programu No_Dynamic_Priorities There is no use of dynamic priorities. No_Dynamic_Attachments There are no calls to any of the operations defined in package Interrupts, e.g. Attach Handler. No_Local_Protected_Objects Protected objects are only declared at the library level. No_Local_Timing_Events Timing events are only declared at the library level. No_Protected_Type_Allocators There are no allocators for protected types or types containing protected subcomponents. No_Relative_Delay There are no relative delay statements (i.e. delay). No_Requeue_Statements There are no requeue statements. No_Select_Statements There are no select statements. No_Specific_Termination_Handlers There are no calls to the specific handler routines in the task termination package. Simple_Barriers The boolean expression in an entry barrier is either a static boolean expression or a boolean component of the enclosing protected object (e.g. a simple boolean variable). 76/83 Ada Podpora paralelismu Systémy real-time Omezující profily Možnosti omezení pragma Restrictions – nedefinované místo kontroly Max_Select_Alternatives Specifies the maximum number of alternatives in a select statement. Max_Task_Entries Specifies the maximum number of entries per task. The maximum number of entries for each task type (including those with entry families) must be determinable at compile-time. A value of zero indicates that no rendezvous is possible. Max_Protected_Entries Specifies the maximum number of entries per protected type. The maximum number of entries for each protected type (including those with entry families) must be determinable at compile-time. 77/83 Ada Podpora paralelismu Systémy real-time Omezující profily Možnosti omezení pragma Restrictions – kontrola za běhu No_Task_Termination All tasks are non-terminating. It is implementation defined what happens if a task terminates – but any fall-back handler must be executed as the first task terminates. Max_Storage_At_Blocking Specifies the maximum portion (in storage elements) of a task’s storage size that can be retained by a blocked task. If a check fails, Storage Error is raised at the point where the respective construct is elaborated. Max_Asynchronous_Select_Nesting Specifies the maximum dynamic nesting level of asynchronous select statements. A value of zero prevents the use of any such statement. If a check fails, Storage Error is raised as above. Max_Tasks Specifies the maximum number of tasks, excluding the environment task, that are allowed to exist over the lifetime of a partition. A zero value prevents tasks from being created. If a check fails, Storage Error is raised as above. Max_Entry_Queue_Length This defines the maximum number of calls queued on an entry. Violation will cause Program Error to be raised at the point of call. 78/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ravenscar pragma Profile(Ravenscar); pragma Task_Dispatching_Policy (FIFO_Within_Priorities); 2 pragma Locking_Policy(Ceiling_Locking); pragma Detect_Blocking; 4 pragma Restrictions( No_Abort_Statements, 6 No_Dynamic_Attachment, No_Dynamic_Priorities, 8 No_Implicit_Heap_Allocations, No_Local_Protected_Objects, 10 No_Local_Timing_Events, No_Protected_Type_Allocators, 12 No_Relative_Delay, No_Requeue_Statements, 14 No_Select_Statements, No_Specific_Termination_Handlers, 16 No_Task_Allocators, No_Task_Hierarchy, 18 No_Task_Termination, Simple_Barriers, 20 Max_Entry_Queue_Length => 1, Max_Protected_Entries => 1, 22 Max_Task_Entries => 0, No_Dependence => Ada.Asynchronous_Task_Control, 24 No_Dependence => Ada.Calendar, No_Dependence => Ada.Execution_Time.Group_Budget, 26 No_Dependence => Ada.Execution_Time.Timers, No_Dependence => Ada.Task_Attributes); 79/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ravenscar Nesmí být hierarchie vláken ◾ vlákna se musí být deklarována na úrovni knihoven, nikoli z hlavního vlákna Zákaz rendezvous ◾ vlákna se musí synchronizovat přes chráněné objekty Předávání dat ◾ atomické proměnné ◾ chráněné objekty ◾ využítí suspension objects Ada.Synchronous_Task_Control.Suspend_Until_True(S); Ada.Synchronous_Task_Control.Set_True(Periodic.S); Omezení na nejvýše jedno entry per chráněný objekt/typ ◾ kombinace protected type a suspension object Pouze jedno vlákno smí čekat ve vnitřní slupce entry ◾ separátní entries pro různá vlákna 80/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ravenscar – příklady Periodická úloha task type Periodicka (Prio : System.Priority; Cyklus : Positive) is 2 pragma Priority (Prio); end Periodicka; 4 task body Periodicka is 6 Dalsi_Cas : Ada.Real_Time.Time; Interval : constant Ada.Real_Time.Time_Span := 8 Ada.Real_Time.Microseconds(Cyklus); begin 10 Dalsi_Cas := Ada.Real_Time.Clock + Interval; loop 12 -- neco delay until Dalsi_Cas; 14 Dalsi_Cas := Dalsi_Cas + Interval; end loop; 16 end Periodicka; 81/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ravenscar – příklady Transformace více entries – 2 vlákna sbírají informace ze dvou sond, jedno vlákno je čte protected Probe_Protector is 2 entry Write (D : in Data_Type; Probe_ID : in Natural) when not Data_Ready; 4 entry Read (DA : out Data_Type_Array) when Data_Ready; 6 end Probe_Protector; ◾ více entries per chráněný objekt ◾ ne-jednoduchá podmínka ve stráži lze spravit snadno druhým příznakem s opačným významem ◾ potenciálně 2 vlákna čekající ve Write entry Zdroj: M. Ben-Ari, Ada for Software Engieneers, 2nd ed. for Ada 2005 82/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ravenscar – příklady Ravenscar verze ◾ použijeme kombinaci chráněného objektu a suspension objektu pro každou sondu protected Probe_Protector_Ravenscar is 2 type Data_Type_Array is array(0..1) of Data_Type; type SO_Type is 4 array(Data_Type_Array’Range) of Ada.Synchronous_Task_Control.Suspension_Object; 6 procedure Write (D : in Data_Type; Probe_ID : in Natural); entry Read (DA : out Data_Type_Array) 8 when Data_Ready; end Probe_Protector_Ravenscar; 10 protected body Probe_Protector_Ravenscar is 12 ... entry Read (Data : out Data_Type_Array) 14 when Data_Ready is begin 16 DA := ... for I in SO_Type’Range loop 18 Ada.Synchronous_Task_Control.Set_True(S(I)); end loop; 20 end Read; ... 22 end Probe_Protector_Ravenscar; Zdroj: M. Ben-Ari, Ada for Software Engieneers, 2nd ed. for Ada 2005 83/83 Ada Podpora paralelismu Systémy real-time Omezující profily Ravenscar – příklady Ravenscar verze ◾ zapisující vlákna se zastavují na suspension objektu task body Probe_Collector (ID: Probe_ID) is 2 begin Ada.Synchronous_Task_Control.Set_True(S(ID)); 4 loop Ada.Synchronous_Task_Control.Suspend_Until_True(S(ID)); 6 delay until Next; ... 8 Probe_Protector_Ravenscar.Write(D, ID); Next := Next + Interval; 10 end loop; end Probe_Collector; Zdroj: M. Ben-Ari, Ada for Software Engieneers, 2nd ed. for Ada 2005