Programowanie systemów
czasu rzeczywistego
Tomasz Szmuc, Katedra Automatyki AGH
tsz@ia.agh.edu.pl
Kraków, 2003
Tomasz Szmuc’03
1
Pojęcia wstępne
systemy czasu rzeczywistego
Tomasz Szmuc’03
2
otoczenie
system
1
e
2
e
1
s
2
s
System czasu rzeczywistego i jego otoczenie
Tomasz Szmuc’03
3
Definicja IEEE/ANSI
System czasu rzeczywistego jest to system komputerowy,
w którym obliczenia są wykonywane współbieżnie z procesem
zewnętrznym (otoczenie) w celu sterowania, nadzorowania lub
terminowego reagowania na zdarzenia występujące w tym
procesie (otoczeniu).
Tomasz Szmuc’03
4
1. Ciągłość działania. System czasu rzeczywistego winien
pracować bez przerw.
h
óre dostarczają usług.
h wymagań.
wych.
2. Zależność od otoczenia. Obliczenia systemu są uzależnione
od zdarzeń i danych generowanych przez proces zewnętrzny
(otoczenie). Struktura otoczenia jest zazwyczaj
skomplikowana, lecz przeważnie statyczna, co istotnie
ogranicza konieczność stosowania struktur dynamicznyc
(rekurencja).
3. Współbieżność. Otoczenie systemu składa się z wielu
obiektów (podsystemów), które działają współbieżnie,
generując odpowiednie zdarzenia lub dane wymagające
obsługi przez system czasu rzeczywistego. Wymagania
jednoczesnej obsługi narzucają współbieżną strukturę
systemu. System składa się z szeregu współbieżnych
procesów, kt
4. Przewidywalność.. Współbieżna struktura systemu indukuje
niedeterministyczne zachowanie, lecz z drugiej strony
wymaga się ścisłego powiązania między zdarzeniami a
odpowiadającymi im obsługami, realizowanymi przez
system. Stąd system mimo że złożony jest zazwyczaj z
szeregu procesów współbieżnych (struktura wewnętrzna), na
zewnątrz musi zachowywać się deterministycznie, tzn.
reagować na zdarzenia wg założonyc
5. Punktualność. Odpowiedzi systemu (reakcje na zdarzenia)
winny być obliczane zgodnie z zaprojektowanymi
algorytmami i dostarczane do otoczenia w odpowiednich
momentach czaso
Tomasz Szmuc’03
5
Definicja
Systemem nazywamy zorganizowany zbiór obiektów
(podsystemów), które są od siebie zależne i stanowią pewną
częściowo zamkniętą (względem relacji zależności) jednostkę.
Tomasz Szmuc’03
6
Definicja
Czasem nazywamy niezależny proces opisany przez
uporządkowany zbiór (T, <), gdzie T jest nieskończonym
zbiorem momentów czasowych, natomiast < jest relacj nad
ą
T, (<
⊆
T x T) oraz spełnione są warunki:
1. (
∀
): (
3
2
1
,
,
t
t
t
2
1
t
t
<
∧
t
)
→
t
3
2
t
<
3
1
t
< - przechodniość;
2. (
∀t): ¬(t < t) -- antyzwrotność;
3. (
∀
):
t
∨
t
∨
2
1
,t
t
2
1
t
<
2
1
t
>
2
1
t
t
= - liniowość;
4. (
∀ ) (∃
t
):
1
t
2
2
1
t
t
< - nieograniczoność z prawej strony;
5. (
∀
):
→ (∃
t
):
t
2
1
,t
t
t
t
1
<
2
3
3
1
t
<
∧
2
3
t
t
< - ciągłość.
Tomasz Szmuc’03
7
1. Systemy o twardych wymaganiach czasowych (Hard
Real-Time Systems) – wymagania czasowe muszą być
dokładnie spełnione.
2. Systemy o miękkich wymaganiach czasowych (Soft Real-
Time Systems) –żąda się spełnienia średniego czasu
odpowiedzi.
3. Systemy o solidnych wymaganiach czasowych (Firm
Real-Time Systems) – wymagania czasowe są kombinacją
twardych i miękkich. Definiuje się pewien krótszy czas
reakcji, który winien być „miękko” spełniany oraz dłuższy,
wobec którego żąda się „twardego” dotrzymania.
Tomasz Szmuc’03
8
Definicja
Procesem nazywamy czwórkę
)
,
,
,
(
T
F
B
S
P
=
, gdzie S jest
przeliczalnym zbiorem stanów,
S
B
⊆
zbiorem stanów
początkowych,
S
F
⊆
zbiorem stanów końcowych, natomiast
S
S
T
×
⊆
jest relacją przejścia i spełnione są następujące
warunki:
T
Dom
B
⊆
oraz
∅
=
∩
T
Dom
F
.
Tomasz Szmuc’03
9
Definicja
Obliczeniem w procesie
)
,
,
,
(
T
F
B
S
P
=
nazywamy dowolny
ciąg stanów:
, taki że jest stanem początkowym
L
,
,
2
1
s
s
1
s
(
), dowolne kolejne elementy ciągu
są kolejnymi
B
s
∈
1
1
,
+
i
i
s
s
stanami procesu (
(
) oraz ciąg jest nieskończony, lub
T
∈
s
s
i
i
+
,
)
1
jeśli jest skończony, to ostatni jego element jest stanem
k
s
końcowym procesu (
).
F
s
k
∈
Tomasz Szmuc’03
10
Cykl życia i modele budowania systemów oprogramowania
A. Model kaskadowy (Waterfall model)
Projektowanie
Wymagania
i specyfikacja
Programo-
wanie
Testowanie
Integracja
Tomasz Szmuc’03
11
Model V
Analiza
wymagań
Dekompoz.
systemu
Specyfikacja
oprogram.
Projektowanie
wstępne
Projektowanie
szczegółowe
Programo-
wanie
Testy
modułów
Testy
integracyjne
Testy
oprogram.
Integracja
systemu
Testy
operacyjne
POTRZEBY
PRODUKT
Tomasz Szmuc’03
12
Wyma-
gania
Projekt Konstru-
kcja
Test
Specy-
fikacja
Proje-
ktowa-
nie
Progra-
mowa-
nie
Testo-
wanie
Inte-
gracja
Budowanie prototypu
Budowanie systemu
Tomasz Szmuc’03
13
Wyma-
gania
Wyma-
gania
Wyma-
gania
Specy-
fikacja
Specy-
fikacja
Specy-
fikacja
Proje-
ktowa-
nie
Proje-
ktowa-
nie
Proje-
ktowa-
nie
Progra-
mowa-
nie
Progra-
mowa-
nie
Testo-
wanie
Testo-
wanie
Testo-
wanie
Inte-
gracja
Inte-
gracja
Inte-
gracja
Użyt-
kowa-
nie
Użyt-
kowa-
nie
Użyt-
kowa-
nie
Progra-
mowa-
nie
Tomasz Szmuc’03
14
Określenie celów
wariantów i ograniczeń
Ocena wariantów,
oszacowanie ryzyka
kumulowany koszt
Planowanie
następnej fazy
Konstrukcja
i weryfikacja
Tomasz Szmuc’03
15
Definicja
Produkt (oprogramowanie) jest poprawny w danym etapie
wytwarzania, jeśli jest zgodny
z
wymaganiami
zdefiniowanymi w poprzednim etapie.
Tomasz Szmuc’03
16
weryfikacja (verification) dotycząca wytwarzania- Czy
konstruuję program poprawnie?
ocena (validation) dotycząca produktu - Czy buduję
poprawny program?
i-ty krok
konstrukcji
i+1 krok
konstrukcji
we
ryfika
cj
a
ocena
Tomasz Szmuc’03
17
Język Ada 95
Tomasz Szmuc’03
18
Historia języka Ada
• Opracowanie języka do tworzenia systemów głównie o
przeznaczeniu wojskowym – Departament Obrony USA –
początek 1974;
ań 1990);
• Zatwierdzenie przez ANSI (American National Standards
Institute) – 1983
→ Ada83;
• Zatwierdzenie przez ISO – 8652 (International Standards
Organization) – 1987;
• Rozpoczęcie prac nad nową wersją języka - Departament
Obrony USA – początek 1988 – projekt Ada 9X
(specyfikacja wymag
• Standaryzacja nowej wersji przez ISO – luty 1995 → Ada
95.
Tomasz Szmuc’03
19
Adres zawierający w miarę kompletne infornmacje o jezyku Ada – w tym
porównanie z innymi:
http://sw-eng.falls-church.va.us/AdaIC/
sponsorowany przez Departament obrony USA.
Inny interesujący adres:
http://www.acm.org/sigada/
w szczególności katalog /education/, który zawiera interesujące narzędzia i
środki do nauki języka.
Jeszcze jeden adres:
http://www.adahome.com/
w szczególności zawierający Reference Manual (/rm95/) i odpowiedzi na
Frequently Asked Questions
(/FAQ/).
Ostatni adres – europejski :
http://www.epfl.ch/Ada/
Lausanne Polytechnique University.
Kompilatory
Kompilator Ada GNAT (darmowy):
http://www.gnat.com/
Firma Rational (komercyjna) :
http://www.rational.com/
Aonix proponuje kompilatory pierwotnie rozwijane przez Alsys-Thomson.
Specjalne zniżki dla uniwersytetów i studentów:
http://www.aonix.com/
Tomasz Szmuc’03
20
Cechy języka Ada
1.
Czytelność. Bardzo ważna cecha, gdyż profesjonalne
programy są częściej czytane niż pisane.
2.
Ścisła typizacja. Każdy element musi mieć ściśle
określony zbiór wartości. Pozwala to wykryć wiele
błędów na etapie analizy syntaktycznej.
tekami.
implementacyjnej.
ch,
polimorfizm.
e
zadań.
owania.
3.
Wspomaganie pisania dużych programów: mechanizm
enkapsulacji, oddzielna kompilacja, efektywne
zarządzanie biblio
4.
Abstrakcja danych. Możliwość ukrycia szczegółów
opisu – oddzielenie specyfikacji i części
5.
Mechanizmy programowania obiektowego:
dziedziczenie w definiowaniu typów pochodny
6.
Jednostki rodzajowe. Możliwość pisania fragmentów
programów niezależnych od typów danych – mechanizm
szczególnie przydatny przy tworzeniu bibliotek.
7.
Zadania. Bogate i efektywne mechanizmy zarządzania
procesami współbieżnymi, komunikacją między
procesami (wiadomości, pamięć dzielona), szeregowani
8.
Mechanizmy uwzględniające upływ czasu – istotne dla
systemów czasu rzeczywistego.
9.
Obsługa wyjątków. Możliwość budowania własnych
procedur obsługi błędów i sytuacji wyjątkowych.
10. Standardowy interfejs do innych języków
program
Tomasz Szmuc’03
21
Konstrukcje języka
Tekst programu zawiera dwa rodzaje jednostek językowych:
• deklaracje używanych jednostek (typy, stałe, zmienne,
wyjątki, podprogramy itp.);
nych jednostek.
• instrukcje – określające operacje wykonywane na
zadeklarowanych jednostkach.
Opracowanie deklaracji jest fazą przygotowawczą do
wykonania instrukcji. Efektem jest utworzenie
zadeklarowanych jednostek i ewentualne wykonanie dalszych
akcji, charakterystycznych dla da
Wykonanie pojedynczej instrukcji – krok obliczeniowy.
Tomasz Szmuc’03
22
Jednostki programowe
1. Podprogramy: funkcje i procedury.
2. Pakiety.
3. Jednostki rodzajowe (Generics).
4. Zadania (tasks).
5. Obiekty chronione (Protected Objects).
Każda jednostka programowa składa się z dwóch części:
• specyfikacji definiującej interfejs między jednostką a jej
otoczeniem;
• treści (body) – implementującej usługi danej jednostki.
Tomasz Szmuc’03
23
Przykład wstępny
-- znaki “--“ oznaczają komentarz
with
Text_IO;
--
pakiet
dołączony
procedure Print_Text is
-- nagłówek procedury
use Text_IO;
ch:
Character;
begin
Put(“Druk wprowadzanych znakow”);
--drukowanie tekstu
New_Line(2); --
opuść 2 linie
loop -- początek pętli
Get(ch); --pobranie
znaku
exit when ch = ‘?’;
--opuszczenie pętli
Put(ch); --
drukowanie
znaku
end loop;
--
koniec
(tekstowy)
pętli
New_Line;
--
przejście do nowej linii
Put(“Koniec programu”);
-- druk tekstu
end Print_Text;
Tomasz Szmuc’03
24
Elementy składni
Notacja Backusa-Naura (BNF)
::=
„”jest definiowany jako”;
[ ]
element opcjonalny;
{ }
iteracja elementu zawartego wewnątrz nawiasu;
|
identyfikator
::= litera_identyfikator{[_] litera_lub_cyfra}
litera_lub_cyfra ::= litera | cyfra
Tomasz Szmuc’03
25
Typy
Typem nazywamy pewien zbiór wartości wraz ze zbiorem operacji, których wyniki są również
elementami tego zbioru (wartości).
Deklaracja (definicja) typu
deklaracja typu
::= type Identyfikator_typu is Definicja_typu
Definicja_typu: zbiór wszystkich wartości (wyliczeniowe), zakres wartości (numeryczne), opis
struktury (tablice, rekordy), opis zadania itp.
Tomasz Szmuc’03
26
Przykład
type Colour is (Red,Black,Green,White,Yellow,Blue);
C: Colour;
-- deklaracja zmiennej C typu Colour
C: Colour:=Red;
-- deklaracja zmiennej j.w. z wart. początkową
Istnieją typy predefiniowane:
Boolean, Character, Integer, Float, Natural, Positive, String,
Wide_Character, Wide_String, Duration
Typy predefiniowane są zawarte w pakiecie Standard i nie muszą być definiowane przez
użytkownika.
Tomasz Szmuc’03
27
Podtyp
Najprostszy schemat deklaracji:
Deklaracja_Podtypu ::= subtype Identyfikator_Podtypu is Identyfikator_Typu [Zawężenie]
Zawężenie ma postać (jeśli występuje) zależną od typu bazowego i może być zawężeniem zakresu,
zawężeniem indeksu lub wyróżnika.
Przykłady
subtype Day_Number is Integer range 1..31;
subtype Feb_Day is Day_Number range 1..29;
subtype RBG is Colour range Red..Green;
Tomasz Szmuc’03
28
Typy skalarne
Wartości typów skalarnych są uporządkowane liniowo.
Typ dyskretny jest typem skalarnym, w którym wartości mają przypisany numer pozycji.
Tomasz Szmuc’03
29
Typ całkowity resztowy
Typ całkowity resztowy jest typem całkowitym bez znaku, w którym jest stosowana arytmetyka
resztowa.
Oznacza to, że dla operacji arytmetycznych nie występuje Constraint_Error.
Definicja typu
Typ całkowity resztowy ::= mod Wyrażenie_Statyczne;
Wyrażenie_Statyczne jest statyczną dodatnią wartością dowolnego typu całkowitego.
Przykłady
type unsigned_byte is mod 8;
-- zakres: 0..7
type word is mod 16; --
zakres:
0..15
Tomasz Szmuc’03
30
Typ
prosty
złożony
wskaźni-
kowy
skalarny
tablica
rekord
zadanie
obiekt
chroniony
dyskretny
rzeczy-
wisty
wylicze-
niowy
całkowity
ze znakiem
resztowy
zmienno-
pozycyjny
stało-
pozycyjny
dziesiętny
zwykły
Tomasz Szmuc’03
31
Typy zmiennopozycyjne
Typ_zmiennopozycyjny ::= digits Wyrażenie_Statyczne
[range Proste_Wyrażenie_Statyczne_1 .. Proste_Wyrażenie_Statyczne_1]
Wyrażenie_Statyczne - dokładność dziesiętna – minimalna ilość cyfr dziesiętnych znaczących do
reprezentacji wartości tego typu;
Proste_Wyrażenie_Statyczne_i (i=1,2) – przyjmuje wartość rzeczywistą i oznacza zakres
Przykład
type Pomiar is digits 6 range 17.5 .. 32.7 ;
-- wartości tego typu będą mieścić się w podanym zakresie
-- i będą opisywane przez 6 cyfr dziesiętnych
type Real is digits 8; --
wartości tego typu będą reprezentowane przez 8 cyfr
Predefiniowany typ Float w pakiecie Standard.
Tomasz Szmuc’03
32
Typy stałopozycyjne
W przeciwieństwie do zmiennopozycyjnych mają stałą dokładność reprezentacji liczby.
Typ_Stałopozycyjny_Zwykły ::= delta Wyrażenie_Statyczne
[range Proste_Wyrażenie_Statyczne_1 .. Proste_Wyrażenie_Statyczne_2]
Typ_Stałopozycyjny_Dziesiętny ::= delta Wyrażenie_Statyczne digits Wyrażenie_Statyczne_0
[range Proste_Wyrażenie_Statyczne_1 .. Proste_Wyrażenie_Statyczne_2]
Wyrażenie_Statyczne – jest typu rzeczywistego i określa ziarno (skok) typu
Wyrażenie_Statyczne_0 – oznacza liczbę znaczących cyfr dziesiętnych w pierwszym podtypie typu
Przykłady
type Odczyt is delta 0.1 range 0.0..150 ;
type Konto is delta 0.01 digits 9;
Tomasz Szmuc’03
33
Typy tablicowe
Typ_Tablicowy_Zawężony ::= type Nazwa_Typu_Tablicowego is
array
(Wskazanie_Podtypu_Dyskretnego | Zakres
{,
Wskazanie_Podtypu_Dyskretnego | Zakres} )
of Wskazanie_Typu_Elementu
Typ tablicowy niezawężony – granice indeksów nie są określone
Typ_Tablicowy_Niezawężony ::= type Nazwa_Typu_Tablicowego is
array
(Wskazanie_Podtypu_Dyskretnego range <>
{,
Wskazanie_Podtypu_Dyskretnego range <> } )
of Wskazanie_Typu_Elementu
Tomasz Szmuc’03
34
Przykłady
type AA array (Integer range 1..10) of Float; -- w przypadku indeksu
type AA: array (1..10) of Float;
-- Integer można podać tylko zakres
type A2Dim: array (0..5, 0..10) of Boolean;
A2: A2Dim;
A2: array (0..5, 0..10) of Boolean; -- deklaracja z anonimowym typem
type Vector is array (Integer range <>) of Float;
Ustalenie rozmiarów jest dokonywane w momencie deklaracji obiektów tego typu:
Subtype Vector_5 is Vector(1..5); -- deklaracja podtypu
V:
Vector_5;
--
deklaracja
zmiennej
V: Vector(1..5);
-- skrócona forma z powyższych linijek
Tomasz Szmuc’03
35
Instrukcje
Instrukcja przypisania
Instrukcja_Przypisania ::=
Nazwa_Zmiennej := Wyrażenie ;
Wykonanie:
• Obliczenie wartości wyrażenia;
• Dokonanie konwersji obliczonej wartości do typu zmiennej po prawej stronie – niemożność wykonania
konwersji powoduje zgłoszenie Constraint_Error lub Program_Error.
• Przypisanie obliczonej wartości do zmiennej.
Tomasz Szmuc’03
36
Instrukcja warunkowa
Instrukcja_If ::=
if Warunek_1 then
Ciąg_Instrukcji_1
elsif Warunek_2 then
Ciąg_Instrukcji_2
...
[ else
Ciąg_Instrukcji_0 ]
end if;
Tomasz Szmuc’03
37
Przykłady
if X<0.0 then X:=-X; end if;
if Order=Left then
Turn_Left;
elsif Order=Right then
Turn_Right;
elsif Order=Back then
Turn_Back;
end if;
Tomasz Szmuc’03
38
Instrukcja wyboru
Instrukcja_Case ::=
case Wyrażenie_Wyboru is
when Lista_Wyborów_1 => Ciąg_Instrukcji_1
...
when Lista_Wyborów_N => Ciąg_Instrukcji_N
[when others => Ciąg_Instrukcji_0]
end case;
Lista_Wyborów:
1. Lista elementów oddzielonych |, np. 1|3|5|7|9
2. Zakres wartości dyskretnych, np. wyrażenie_proste .. wyrażenie_proste – (J+K) .. 25
Tomasz Szmuc’03
39
Przykład
case Order is
when Left => Turn_Left;
when Right => Turn_Right;
when Back => Turn_Back;
when others => null;
end case;
Tomasz Szmuc’03
40
Instrukcja pętli
Pętla_Loop ::=
[Identyfikator_Pętli :]
loop
Ciąg_Instrukcji
end loop [Identyfikator_Pętli]
Tomasz Szmuc’03
41
Pętla_For ::=
[Identyfikator_Pętli :]
for Identyfikator in [reverse] Definicja_Podtypu_Dyskretnego
loop
Ciąg_Instrukcji
end loop [Identyfikator_Pętli]
Pętla_While ::=
[Identyfikator_Pętli :]
while Wyrażenie_Logiczne
loop
Ciąg_Instrukcji
end loop [Identyfikator_Pętli]
Tomasz Szmuc’03
42
Przykłady
A: array (Integer range <>) of Float :=
(0.5, 1.7, 2.4, 0.9, 3.2); -- inicjowanie 5 elementowej tablicy
S: Float := 0.0;
for I in reverse Integer range 1..5 loop
S:=S+A(I);
end loop;
Tomasz Szmuc’03
43
Pakiety
Specyfikacja_Pakietu ::=
package Nazwa is
[Deklaracje_Stałych]
[Deklaracje_Typów]
[Deklaracje_Zmiennych]
[Specyfikacje_Podprogramów]
[private
[Deklaracje_Stałych]
[Deklaracje_Typów]
]
end Nazwa;
Treść_Pakietu ::=
package body Nazwa is
[Wewnętrzne_Deklaracje]
begin
[Instrukcje_Inicjalizujące_Pakiet]
end Nazwa;
Tomasz Szmuc’03
44
package Stack is
procedure Push(A:Integer);
function Pop return Integer;
end Stack;
package body Stack is
Size: constant := 100;
A:array(1..Size) of Integer;
Top: Integer range 0..Size;
procedure Push(X:Integer) is
begin
if Top = Size then
end if;
Top := Top +1;
A(Top):=X;
end Push;
function Pop return Integer is
begin
if Top = 0 then
end if;
Top := Top – 1;
return A(Top+1);
end Pop;
begin
Top := 0; -- nadanie wartości
-- początkowej
end Stack;
Tomasz Szmuc’03
45
Jednostki rodzajowe
generic
Maximal: Positive; -- rozmiar stosu
type Item is private; -- rodzaj
-- elementu stosu
package Stack is
..procedure Push(A:Item);
function Pop return Item;
end Stack;
package body Stack is
A:array(1..Maximal) of Item;
Top: Integer range 0..Maximal;
-- ... pozostałe części jak na rys.
-- poprzedni
end Stack;
Tomasz Szmuc’03
46
Postać parametrów formalnych może przybierać formy:
type Nazwa is (<>); -- par. dyskretny
type Nazwa is range <>; -- par. Integer
type Nazwa is mod <>; -- par. resztowy
type Nazwa is digits <>;
--par.zmiennoprzecinkowy
type Nazwa is delta <>;
-- par.stałoprzecinkowy
type Nazwa is delta <> digits <>;
--par.dziesiętny
Tomasz Szmuc’03
47
non-existing
created
ready
running
suspended
abort
terminated
Stany procesu (zadania)
Tomasz Szmuc’03
49
non-existing
created
initializing
executable
terminated
Fazy zadania z punktu widzenia programowania
Tomasz Szmuc’03
50
Standard POSIX przewiduje również tworzenie procesów
wielowątkowych. Proces wielowątkowy odpowiada w języku Ada
zadaniu (składającemu się wielu zadań). Poszczególne wątki
charakteryzują się atrybutami. Zarządzanie tymi atrybutami wymaga
utworzenia obiektu atrybutowego typu pthread_attr_t, wyposażonego
w funkcje pobierania i wpisywania wartości atrybutów. Każdy
utworzony wątek ma unikatowy identyfikator (typu pthread_t), który
jest dostępny przez wywołanie funkcji pthread_self.
).
a.
Wątek jest tworzony wskutek wywołania funkcji pthread_create o
czterech parametrach:
1. identyfikator wątku (zwracany po wywołaniu),
2. zbiór atrybutów,
3. funkcję zawierającą kod wątku
4. zbiór parametrów przekazywanych do tej funkcji (wątku).
Normalne zakończenie jest realizowane przez funkcję pthread_exit
lub odebranie sygnału. Zakończenie awaryjne jest realizowane przez
wywołanie pthread_cancel. Możliwe jest również oczekiwanie na
zakończenie innego wątku, przez wykonanie pthread_join (jak w
mechanizmie fork-join
Standard POSIX dotyczy systemu operacyjnego, zatem zawiera
również mechanizmy niższego poziomu, w tym możliwość wskazania
kodu gotowego do usunięcia (detach). Wyróżnia się trzy sposoby
realizacji tego mechanizmu: wykorzystanie pthread_join (usunięcie
po zakończeniu wątku), albo przez ustawienie atrybutu detach w
trakcie powoływania, lub dynamicznie, przez wywołanie funkcji
pthread_detach. Jeśli parametr ten jest ustawiony, wówczas wątek nie
może być przyłączony i zajmowana przez niego pamięć może być
automatycznie zwolnion
Tomasz Szmuc’03
51
SEMAPHORE
ACCESS
FREE
Specyfikacja typu task
task type SEMAPHORE is
entry ACCESS_TO;
entry FREE;
end SEMAPHORE;
Tomasz Szmuc’03
52
-- Specyfikacja typu zadaniowego
task type SEMAPHORE is
entry ACCESS_TO;
entry FREE;
end SEMAPHORE;
-- Część implementacyjna
task body SEMAPHORE is
begin
loop
accept ACCESS_TO;
accept FREE;
end loop;
end SEMAPHORE;
Deklaracja typu zadaniowego Semaphore
Tomasz Szmuc’03
53
procedure OPERATING_SYSTEM is
task type SEMAPHORE is
entry ACCESS_TO;
entry FREE;
end SEMAPHORE;
task body SEMAPHORE is
...
end SEMAPHORE;
task type COMMAND_MANAGER;
task body COMMAND_MANAGER is
...
end COMMAND_MANAGER;
-- deklaracje zmiennych typu SEMAPHORE
PRINTER_SEMAPHORE,FILE_SEMAPHORE:
SEMAPHORE;
-- tablica o elementach typu COMMAND_MANAGER
USER: array(1..10) of COMMAND_MANAGER;
begin
....
end OPERATING_SYSTEM;
Przykład deklarowania zadań w „szkieletowej” konstrukcji systemu
operacyjnego
Tomasz Szmuc’03
54
Server.En
accept En
wait for
call En
wait for
end accept
executing
accept
Client
Server
Synchronizacja spotkania
Tomasz Szmuc’03
55
Deklaracja zadań
procedure OPERATING_SYSTEM is
task type SEMAPHORE is
entry ACCESS_TO;
entry FREE;
end SEMAPHORE;
task body SEMAPHORE is
...
end SEMAPHORE;
task type COMMAND_MANAGER;
task body COMMAND_MANAGER is
...
end COMMAND_MANAGER;
PRINTER_SEMAPHORE, FILE_SEMAPHORE: SEMAPHORE;
USER: array(1..10) of COMMAND_MANAGER;
begin
....
end OPERATING_SYSTEM;
Tomasz Szmuc’03
56
Wykonanie zadania składa się z trzech faz:
1. Aktywacja (Activation) wykonywana w trakcie tzw.
opracowywania (eleboration) części deklaracyjnej zadania; w
wyniku aktywacji zadanie wraz z danymi lokalnymi zostają
utworzone (created) oraz zadanie jest inicjalizowane.
.
rmination).
2. Wykonywanie (Execution) wykonywanie poszczególnych
instrukcji zapisanych we wnętrzu (body) zadania
3. Zakończenie (Finalisation) wykonanie odpowiedniego kodu
związanego z zakończeniem, tzn. osiągnięcie ostatniej instrukcji
(end) zadania, zgłoszenie wyjątku, który nie może być
obsłużony, lub wykonanie instrukcji terminate w rozgałęzieniu
select, lub wykonanie na tym zadaniu instrukcji abort
(AbnORmal Te
Tomasz Szmuc’03
57
Zdania dynamiczne
Type ACCESS_ON_SEMAPHORE is access SEMAPHORE;
NEW_RESOURCE: ACCESS_ON_SEMAPHORE;
...
begin
...
if REQUIRED then NEW_RESOURCE := new SEMAPHORE;
-- dynamiczne kreowanie i inicjacja zadania
...
Tomasz Szmuc’03
58
Zakończenie zadań
.
...
task body Rodzic is
...
VARIABLE: T;
...
task CHILD is
...
end CHILD;
task body CHILD is
...
begin
...
XXX;
... := VARIABLE;
...
end CHILD;
begin
...
VARIABLE := ...;
...
end FATHER;
Tomasz Szmuc’03
59
procedure Main is
task type TT is ...
T1: TT;
T2: TT;
begin
...
loop
null;
end loop;
end Main;
Tomasz Szmuc’03
60
Aspekty czasowe
ASPEKTY CZASOWE
Predefiniowane typy:
• TIME
• DURATION
Instrukcje
• delay D;
• delay until T;
Tomasz Szmuc’03
61
T1 - moment rozpoczęcia wykonywania instrukcji delay
T2 - rozpoczęcie wykonywania następnej instrukcji
T1
T2
D
delay D
T
T1
delay until T
T1 - moment rozpoczęcia wykonywania instrukcji delay until
T - rozpoczęcie wykonywania następnej instrukcji
Tomasz Szmuc’03
62
task type Semi_Periodic;
task body Semi_Periodic is
Period: constant DURATION := 0.05;
begin
loop
..... -- Periodic treatment
delay Period;
end loop;
end Semi_Periodic;
Tomasz Szmuc’03
63
task type Periodic;
with CALENDAR;
task body Periodic is
Seconds: constant DURATION := 1.0;
Period: constant DURATION := 0.05 * Seconds;
Next_Time: CALENDAR.TIME := First_Time;
begin
loop
delay unil Next_Time - CALENDAR.CLOCK;
..... -- Periodic treatment
Next_Time := Next_Time + Period;
end loop;
end Periodic;
Tomasz Szmuc’03
64
type Time is private;
function Clock return Time;
function Year(Date: Time) return Year_Number;
function Month(Date: Time) return Month_Number;
function Day(Date: Time) return Day_Number;
function Second(Date: Time) return Day_Duration;
procedure Split( Date: in Time;
Year:
out Year_Number;
Month:
out Month_Number;
Day:
out Day_Number;
Seconds:
out Day_Duration);
function "+" (Date: in Time;Interval: in Duration)
return Time;
function "+" (Interval: in Duration; Date: in
Time) return Time;
function "-" (Date: in Time; Interval: in
Duration) return Time;
function "-" (Date_1, Date_2: in Time) return
Duration;
Tomasz Szmuc’03
65
Server.En
accept En
wait for
call En
wait for
accept
executing
accept
Client
Server
wait for
end accept
end accept
Synchronizacja z uwzględnieniem przesłania danych
Tomasz Szmuc’03
66
task type BUFFER is
entry READ(X: out ITEM);
entry WRITE(X: in ITEM);
end BUFFER;
task body BUFFER is
SIZE: constant POSITIVE := 100;
subtype BUFFER_RANGE is integer range 1..SIZE;
INDEX_FIRST_ITEM, INDEX_LAST_ITEM: BUFFER_RANGE :=1;
BUFFER_MEMORY: array(BUFFER_RANGE) of ITEM;
NUMBER_OF_ITEM: integer range 0..SIZE := 0;
begin
loop
select
when NUMBER_OF_ITEM /= SIZE =>
-- buffer not full
accept WRITE(X: in ITEM) do
BUFFER_MEMORY(INDEX_LAST_ITEM)
:=
X;
end WRITE;
INDEX_LAST_ITEM:=(INDEX_LAST_ITEM mod SIZE) + 1;
NUMBER_OF_ITEM := NUMBER_OF_ITEM +1;
or
when NUMBER_OF_ITEM /= 0 => -- buffer not empty
accept READ(X: out ITEM) do
X
:=
BUFFER_MEMORY(INDEX_FIRST_ITEM);
end READ;
INDEX_FIRST_ITEM:=(INDEX_FIRST_ITEM
mod
SIZE)+1;
NUMBER_OF_ITEM := NUMBER_OF_ITEM - 1;
end select;
end loop;
end BUFFER;
Tomasz Szmuc’03
67
-- a bounded buffer
Buffer_Size : constant Integer := 10;
type Index is mod Buffer_Size;
subtype Count is Natural range 0 .. Buffer_Size;
type Buffer is array (Index) of Data_Item;
protected type bounded_Buffer is
entry Read (Item: out Data_Item);
entry Write (Item: in Data_Item);
private
First : Index := Index’First ;
Last : Index := Index’Last ;
Number_in_Buffer : Count := 0;
Buff : Buffer ;
end Bounded_Buffer ;
protected body Bounded_Buffer is
entry Read (Item: out Data_Item);
when Number_in_Buffer /= 0 is
begin
Item := Buff(First) ;
First := First + 1;
Number_in_Buffer := Number_in_Buffer - 1 ;
end Read;
entry Write (Item: in Data_Item);
when Number_in_Buffer /= Buffer_Size is
begin
Last := Last + 1;
Buff(Last) := Item;
Number_in_Buffer := Number_in_Buffer - 1 ;
end Write;
end Bounded_Buffer;
Tomasz Szmuc’03
68
package Ada.Synchronous_Task_Control is
type Suspension_Object is limited private;
procedure Set_True(S: in out
Suspension_Object);
procedure Set_False(S: in out
Suspension_Object);
function Current_State(S:
Suspension_Object) return Boolean;
procedure Suspend_Until_True(S: in out
Suspension_Object);
private
-- nie jest specyfikowane w języku
end Ada.Synchronous_Task_Control;
Tomasz Szmuc’03
69
procedure MAIN is
GLOBAL_VARIABLE: Item;
task type TT1;
task body TT1 is
LOCAL_VARIABLE1: Item;
begin
LOCAL_VARIABLE1 := GLOBAL_VARIABLE;
...
end TT1;
task type TT2;
task body TT2 is
LOCAL_VARIABLE2: Item;
begin
GLOBAL_VARIABLE := LOCAL_VARIABLE2;
...
end TT2;
....
Tomasz Szmuc’03
70
...
accept E1;
...
GLOBAL_VARIABLE := V1;
...
-- wartość V1 niewidoczna dla innych zadań
GLOBAL_VARIABLE := V2;
...
T2.E2;
Tomasz Szmuc’03
71
Pragma_Zmiennej_Dzielonej ::=
pragma Nazwa_Pragmy(Nazwa_Zmiennej);
Nazwa_Pragmy ::= Volatil[_Components]
| Atomic[_Components]
Tomasz Szmuc’03
72
task CONSUMER is
entry PROVIDES(X: in ELEMENT);
end CONSUMER;
task PRODUCER;
task body CONSUMER is
Y: ELEMENT;
begin
loop
accept PROVIDES(X: in ELEMENT) do
Y:= X;
end PROVIDES;
Computes(Y);
end loop;
end CONSUMER;
task body PRODUCER is
E: ELEMENT;
begin
loop
PRODUCES(E);
CONSUMER.PROVIDES(E);
end loop;
end PRODUCER;
Tomasz Szmuc’03
73
task type MESSENGER is
entry DELIVERS(E: in ELEMENT);
end MESSENGER;
task body MESSENGER is
MEMORY : ELEMENT;
begin
loop
accept DELIVERS(E: in ELEMENT) do
MEMORY:= E;
end DELIVERS;
CONSUMER.PROVIDES(MEMORY);
end loop;
end MESSENGER;
MY_MESSENGER: MESSENGER;
...
task body PRODUCER is
E: ELEMENT;
begin
loop
PRODUCES(E);
MY_MESSENGER.DELIVERS(E);
end loop;
end PRODUCER;
-- zadanie CONSUMER bez zmian
Tomasz Szmuc’03
74
task type MESSENGER is
entry DELIVERS(E: in ELEMENT);
end MESSENGER;
task body MESSENGER is
MEMORY: ELEMENT;
begin
accept DELIVERS(E: in ELEMENT) do
MEMORY := E;
end DELIVERS;
CONSUMER.PROVIDES(MEMORY);
end MESSENGER;
type ADDRESS_MESSENGER is access MESSENGER;
task body PRODUCER is
E: ELEMENT;
begin
loop
PRODUCES(E);
declare
MY_MESSENGER: ADDRESS_MESSENGER;
begin
MY_MESSENGER:= new MESSENGER;
MY_MESSENGER.DELIVERS(E);
end;
end loop;
end PRODUCER;
Tomasz Szmuc’03
75
task body BUFFER is
SIZE: constant NATURAL:= 100;
type Index is mod SIZE;
INDEX_FIRST, INDEX_LAST: Index :=1;
BUFFER_MEM: array(Index) of ITEM;
COUNTER: POSITIVE range 0..SIZE := 0;
-- licznik elementów w buforze
begin
loop
select
when COUNTER /= SIZE =>
-- Bufor (BUFFER_MEM) nie jest zapełniony
accept WRITE(X: in ITEM) do
BUFFER_MEM(INDEX_LAST):= X;
end WRITE;
INDEX_LAST := INDEX_LAST + 1;
-- typ resztowy - cykliczność uzyskano wprost
COUNTER := COUNTER +1;
or
when COUNTER /= 0 =>
-- Bufor (BUFFER_MEM) nie jest pusty
accept READ(X: out ITEM) do
X:= BUFFER_MEM(INDEX_FIRST);
end READ;
INDEX_FIRST:=INDEX_FIRST + 1;
-- typ resztowy - cykliczność uzyskano wprost
COUNTER := COUNTER - 1;
end select;
end loop;
end BUFFER;
Tomasz Szmuc’03
76
Deklaracja_Typu_Obiektu_Chronionego ::=
protected type Nazwa_Typu_Chronionego [Wyróżnik] is
{Specyfikacja_Podprogramu | Deklaracja_Wejścia}
[private
{Specyfikacja_Podprogramu | Deklaracja_Wejścia | Deklaracja_Danych} ]
end [Nazwa_Typu_Chronionego]
Deklaracja_Wejścia ::=
entry Identyfikator_Wejścia [(Podtyp_Indeksu)] (Lista_Parametrów);
Tomasz Szmuc’03
77
Treść_Obiektu_Chronionego ::=
protected body Nazwa_Typu_Chronionego is
{Specyfikacja_Podprogramu |
Treść_Podprogramu |
Treść_Wejścia }
end [Nazwa_Typu_Chronionego]
Treść_Wejścia ::=
entry Identyfikator_Wejścia [(Deklaracja_Indeksu) (Lista_Parametrów)]
when Warunek_Bariery is
Część_Deklaracyjna
begin
Sekwencja_Instrukcji_Obsługi_Wejścia
end [Nazwa_Typu_Chronionego];
Deklaracja_Indeksu ::=
for Identyfikator_Indeksu in Podtyp_Indeksu
Tomasz Szmuc’03
78
Read
Write
Kolejka
do Read
Kolejka
do Write
Co najwyżej
jedno zadanie
wewnątrz
obiektu chronionego
zadania poza
skorupką
skorupka
Tomasz Szmuc’03
79
protected type Shared_Data(Initial_Value: Item)
is
function Read return Item;
procedure Write(New_Value: Item);
private
Data: Item:=Initial_Value;
end Shared_Data;
protected body Shared_Data is
function Read return Item is
begin
return
Data;
end Shared_Data;
procedure Write(New_Value: Item) is
begin
Data:= New_Value;
end Write;
end Shared_Data;
-- deklaracja zmiennej z wartością początkową
My_Data: Shared_Data(Current_Initial_Value);
Tomasz Szmuc’03
80
protected type Shared_Data is
function Read return Item;
procedure Write(New_Value: Item);
private
Data: Item:=Initial_Value;
end Shared_Data;
Tomasz Szmuc’03
81
protected Event is
entry Wait;
procedure Signal;
private
Arised: Boolean := False;
end Event;
protected body Event is
entry Wait when Arised is
begin
Arised:=False;
-- wystąpienie zdarzenia jest „skonsumowane”
end Wait;
procedure Signal is
begin
Arised:=True;
end Signal;
end Event;
Tomasz Szmuc’03
82
protected Event is
entry Wait;
entry Signal;
private
entry Reset;
Arised: Boolean := False;
end Event;
protected body Event is
entry Wait when Arised is
begin
null;
--wnętrze wejścia jest puste
end Wait;
entry Signal when True is
begin
if Wait’Count>0 then
Arised:=True;
requeue Reset;
-- Reset realizuje zakończenie rozgłaszania
end if;
end Signal;
entry Reset when Wait’Count=0 is
begin
Arised:=False;
end Reset;
end Event;
Tomasz Szmuc’03
83
with Resource_Set; use Resource_Set;
-- Resource_Set definiuje typ Set i jego operatory
protected Allocator is
entry Request(S:Set);
procedure Release(S:Set);
private
entry Repeat(S:Set);
function Allocated(S:Set) return Boolean;
Available: Set:=Full; -- stała Full w Resource_Set
..Waiting: Positive:=0;
end Allocator;
protected body Allocator is
function Allocated(S:Set) return Boolean is
begin
if S<=Available then
Available:= Available-S;
return True;
else return False;
end if;
end Allocated;
procedure Release(S:Set) is
begin
Available:=
Available+S;
Waiting:=Repeat’Count;
end Release;
entry Request(S:Set) when True is
begin
if not Allocated(S) then requeue Repeat;
end if;
end Request;
entry Repeat(S:Set) when Waiting>0 is
begin
Waiting:=
Waiting-1;
If not Allocated(S) then requeue Repeat;
end if;
end Repeat;
end Allocator;
Tomasz Szmuc’03
84
protected type Persistent_Signal is
procedure Signal;
entry Wait;
private
Signal_Received: Boolean:= False;
end;
proteced body Persistent_Signal is
procedure Signal is
begin
Signal_Received:= True;
end Send;
entry Wait when Signal_Received is
begin
Signal_Received:=
False;
end Wait;
end Persistent_Signal;
Tomasz Szmuc’03
85
generic
type Message is private;
package Broadcasting is
protected type Broadcast is
procedure Send(The_Message: Message);
entry Receive(A_Message: out Message);
private
Message_Arrived: Boolean:= False;
W_Message:
Message;
end Broadcast;
end Broadcasting;
package body Broadcasting is
protected body Broadcast is
procedure Send(The_Message: Message) is
begin
if Receive’Count > 0 then
Message_Arrived:=
True;
W_Message:=
The_Message;
end if;
end Send;
entry Receive(A_Message: out Message)
when Message_Arrived is
begin
if Receive’Count = 0 then
Message_Arrived:= False;
end if;
A_Message:=
W_Message;
end Receive;
end Broadcast;
end Broadcasting;
Tomasz Szmuc’03
86
with Ada.Task_Identification;
package Ada.Asynchronous_Task_Control is
procedure Hold(T: in
Ada.Task_Identification.Task_ID);
procedure Continue(T: in
Ada.Task_Identification.Task_ID);
function Is_Held(T:
Ada.Task_Identification.Task_ID)
return Boolean;
end Ada.Asynchronous_Task_Control;
Tomasz Szmuc’03
87
non-existing
created
terminated
finalising
completed
activating
executing
waiting child
activation
wait dependent
termination
delayed
waiting on
entry call
waiting on
accept
waiting on
select
waiting
for end
rendezvous
wait for
protected
entry call
w
yw
oła
nie
ob
ie
ktu
bariera
timeout
wyjątek
Tomasz Szmuc’03
88
Obsługa wyjątków
Wstawić standard – poniżej zaawansowane.
Tomasz Szmuc’03
89
Wyjątki w różnych fazach programu
1. Wyjątki w trakcie opracowywania deklaracji. Jeśli w trakcie
opracowywania deklaracji zostanie zgłoszony wyjątek, to obiekt
ten nie będzie utworzony, jak również żadne zadanie, które
ewentualnie zostało utworzone w tej części deklaracyjnej nie
będzie aktywizowane. Zadania te przejdą do fazy zakończenia
lub usuwania.
e.
2. Wyjątki w czasie aktywacji zadania. Jeśli w trakcie aktywacji
zadania wystąpi zgłoszenie wyjątku, to zadanie przechodzi do
fazy zakończenia. W rezultacie powoduje to zgłaszenie wyjątku
Tasking_Error w zadaniu rodzica po zakończeniu aktywacji
wszystkich zadań potomnych. Jeśli w tym trybie, w trakcie
aktywacji, zakończonych jest kilka zadań, to w zadaniu rodzica
tylko raz zgłaszany jest wyjątek Tasking_Error.
3. Wyjątki w trakcie zakończenia zadania. Wyjątki zgłaszane
w fazie zakończenia zadania nie mają wpływu na przebieg
procedury zakończenia i wyjątki te są tracon
Tomasz Szmuc’03
90
4. Wyjątki w trakcie realizacji spotkania. Ogólna zasada polega
w tym przypadku na nieobsługiwaniu wyjątków zgłaszanych
w trakcie spotkania, zarówno dla zadania serwera, jak i klienta.
Ponadto następujące wyjątki mogą być zgłaszane, jeśli zadanie
przystępuje do spotkania.
• Wyjątek Tasking_Error, jeśli klient wywołuje zadanie
serwera, które znajduje się w trakcie zakończenia, usuwania,
lub jest argumentem wykonywanej instrukcji abort, jak
również, jeśli wspomniane wyżej fazy zakończyły się przed
wywołaniem serwera. Wyjątek ten (Tasking_Error) jest
również zgłaszany w zadaniu klienta, jeśli zadanie serwera
znajdzie się w fazie awaryjnego usuwania (abort) w trakcie
realizacji spotkania.
zakresem.
.
• Wyjątek Constraint_Error jest zgłaszany, jeśli klient
wywołuje element rodziny wejść i aktualny indeks tego
wejścia jest poza
• Wyjątek Program_Error jest zgłaszany, jeśli serwer wykonuje
instrukcję select i wszystkie rozgałęzienia tej instrukcji są
zamknięte, a instrukcja nie ma części else
Tomasz Szmuc’03
91
5. Wyjątki w trakcie użycia obiektów chronionych. Wyjątek
Program_Error jest zgłaszany przy interakcji zadania z obiek-
tem chronionym w następujących przypadkach:
• obliczanie warunków barier prowadzi do zgłoszenia wyjątku,
który jest zgłaszany we wszystkich zadaniach oczekujących
w kolejce do danego wejścia;
• w obiekcie chronionym wykonywana jest operacja
potencjalnie blokująca;
ończone.
.
i.
• zadanie umieszczone w kolejce do wejścia obiektu
chronionego jest zak
Podobnie jak w przypadku zadań, wyjątek Constraint_Error
jest zgłaszany, jeśli aktualna wartość indeksu wejścia jest poza
zakresem.
6. Wyjątki w trakcie obsługi przerwań. Wyjątki propagowane
z jednostek obsługujących przerwania (procedura chroniona,
zadanie) nie powodują żadnego efektu
7. Wyjątki względem odroczonych operacji abort – zostaną
opisane w dalszej częśc
8. Wyjątki w trakcie asynchronicznej instrukcji select – zostaną
opisane w dalszej części.
Tomasz Szmuc’03
92
Instrukcja abort
Zadanie będące argumentem instrukcji abort uzyskuje statut
abnormal, również wszystkie inne zależne od niego niezakończone
zadania uzyskują ten statut. Zadanie, które uzyskało statut abnormal
jest usuwane, jeśli tylko nie było zaangażowane w wykonywanie
operacji odroczonych względem abort (abort-deferred operation).
Wykonanie operacji odroczonych winno być dokończone, po czym
wykonywane jest zakończenie i usunięcie zadania. Jeśli konstrukcja
usuwana awaryjnie znajduje się na zewnątrz operacji odroczonej,
innej niż wołanie wejścia, wówczas jest natychmiast usuwana. Inne
konstrukcje muszą być zakończone nie później, niż po osiągnięciu
następnego tzw. punktu zakończenia abort (abort completion point),
występującego na zewnątrz operacji odroczonych:
ort;
zakończenie aktywacji zadania;
rozpoczęcie aktywacji innego zadania;
początek lub zakończenie wołania wejścia, instrukcji select,
opóźnienia lub ab
początek wykonywania instrukcji select lub sekwencji instrukcji
obsługi wyjątku.
Tomasz Szmuc’03
93
Natychmiastowe usunięcie zadania może w pewnych warunkach
spowodować utratę spójności programu, a więc prowadzić do
niekorzystnej sytuacji. Jeśli zadanie znajduje się wewnątrz obiektu
chronionego i przetwarza dane dzielone, to operacje takie należy
zakończyć, gdyż bezwarunkowe zakończenie zadania może
spowodować utratę spójności tych danych. Stąd wybrano tzw.
operacje odroczone względem abort (abort deferred operations):
dań.
operacje chronione;
oczekiwanie na zakończenie wołanego wejścia;
oczekiwanie na zakończenie zadań zależnych;
wykonywanie procedur inicjalizacji lub zakończenia, lub instrukcji
przypisania obiektu z częścią sterowaną.
Bezwarunkowe usunięcie zadań wykonujących wymienione operacje
jest odroczone do momentu ich zakończenia. Pozwala to zapewniać
spójność aplikacji (programu), po bezwarunkowym usunięciu
specyfikowanych za
Tomasz Szmuc’03
94
Asynchroniczna zmiana wątku sterowania
Odtwarzanie po błędzie
Wystąpienie błędu w sprzęcie może prowadzić do sytuacji, w której
pewne obliczenia nigdy się nie zakończą i zadanie nie dojdzie do
punktu oczekiwania – nie osiągnie gotowości wykonania obsługi.
Tomasz Szmuc’03
95
with Broadcasting; -- pakiet zdefiniowany
type Error_Id is (Error1,Error2,Error3);
-- typ określający wiadomość
-- i uściśla pakiet rodzajowy
package Err_Broadcast is new
Broadcasting(Error_Id);
Error_Raised: Err_Broadcast.Broadcast;
-- typ obiektu chronionego już zdefiniowany
task Err_Monitor;
-- zadania z rekonstrukcją po błędzie
Tomasz Szmuc’03
96
task type Recovery_Task;
task body Recovery_Task is
Reason: Error_Id;
begin
loop
select
Error_Raised.Receive(Reason);
case Reason is
when Error1 =>
... –– odtwarzanie po błędzie Error1
when Error2 =>
... –– odtwarzanie po błędzie Error2
when Error3 =>
... –– odtwarzanie po błędzie Error3
end case;
then abort;
loop
... –– obliczenia
end loop;
end select;
...
end loop;
end Recovery_Task;
Tomasz Szmuc’03
97
...
task body Err_Monitor is
Error: Error_Id;
begin
...
-- wykrycie wystąpienia błędu typu Error_Id
Error_Raised.Send(Error);
...
end Err_Monitor;
Rys. Struktura zadania z odtwarzaniem po błędach
Tomasz Szmuc’03
98
Zmiana trybu zadania
Zmiana trybu wykonywania zadania jest zazwyczaj powodowana
przez wystąpienie pewnego zdarzenia. Przykładowo zadanie
cykliczne, w którym przewidziano dwa tryby: normalny, wykonujący
obliczenia cykliczne co 1s oraz awaryjny - okres obliczeń wynosi
.2s.
0
Tomasz Szmuc’03
99
type Mode is (Critical,Normal);
Change: Persisten_Signal;
-- typ określony wcześniej
task Two_Modes_Task;
task body Two_Modes_Task is
Current_Mode: Mode:= Normal;
Next_Time: Time:= Clock;
Critical_Period: constant Duration:= 0.2;
Normal_Period: constant Duration: 1.0;
Current_Period: Duration:= Normal_Period;
Tomasz Szmuc’03
100
begin
loop
select
Change.Wait;
if Current_Mode=Critical then
Current_Mode:=
Normal;
Current_Period:=
Normal_Period;
else
Current_Mode:=
Critical;
Current_Period:=
Critical_Period;
end if;
then abort
loop
... –– obliczenia cykliczne
Next_Time:=
Next_Time+Current_Period;
delay until Next_Time;
end loop;
end select;
end loop;
end Two_Modes_Task;
Rys. Implementacja zadania cyklicznego o dwóch okresach
Tomasz Szmuc’03
101
Obliczenia nieprecyzyjne – przeterminowanie obliczeń
with Ada.Real_Time; use Ada.Real_Time;
task Comp_Timeout;
task body Comp_Timeout is;
Timeout: Duration:= 0.5;
begin
...
select
delay Timeout;
... -- obsługa po przeterminowaniu
then abort
... –– blok krytyczny czasowo
end select;
...
end Comp_Timeout;
Rys. Konstrukcja z przeterminowaniem obliczeń
Tomasz Szmuc’03
102
Obsługa przerwań
protected Treat_Interrupt is
procedure Reaction;
pragma Interrupt_Handler(Reaction);
end Treat_Interrupt;
Tomasz Szmuc’03
103
protected Treat_Interrupt is
procedure Reaction;
pragma Interrupt_Handler(Reaction);
pragma Attach_Handler(Reaction, ...);
end Treat_Interrupt;
Tomasz Szmuc’03
104
with System;
package Ada.Interrupts is
type Interrupt_ID is implementation-defined;
type Parameterless_Handler is
access protected procedure;
function Is_Reserved (Interrupt : Interrupt_ID)
return Boolean;
function Is_Attached (Interrupt : Interrupt_ID)
return Boolean;
function Current_Handler(Interrupt: Interrupt_ID)
return Parameterless_Handler;
procedure Attach_Handler
(New_Handler
:
in Parameterless_Handler;
Interrupt
:
in Interrupt_ID);
procedure Exchange_Handler
(Old_Handler
:
out Parameterless_Handler;
New_Handler
:
in Parameterless_Handler;
Interrupt
:
in Interrupt_ID);
procedure Detach_Handler
(Interrupt
:
in Interrupt_ID);
function Reference(Interrupt : Interrupt_ID)
return System.Address;
private
... -- not specified by the language
end Ada.Interrupts;
Tomasz Szmuc’03
105
task INTERRUPT_HANDLER is
entry INTERRUPT;
for INTERRUPT use at ADDRESS;
pragma PRIORITY(HIGH);
end INTERRUPT_HANDLER;
task body INTERRUPT_HANDLER is
begin
loop
accept INTERRUPT do
...
-- interrupt code
end INTERRUPT;
...
-- immediate code
end loop;
end INTERRUPT_HANDLER;
Tomasz Szmuc’03
106
task INTERRUPT1_HANDLER is
entry INTERRUPT1;
for INTERRUPT1 use at ADDRESS2;
pragma PRIORITY(P1);
end INTERRUPT1_HANDLER;
task body INTERRUPT1_HANDLER is
begin
loop
accept INTERRUPT1 do
...
-- interrupt1 code
end INTERRUPT1;
...
-- immediate1 code
end loop;
end INTERRUPT1_HANDLER;
-- -----------------------------------
task INTERRUPT2_HANDLER is
entry INTERRUPT2;
for INTERRUPT2 use at ADDRESS2;
pragma PRIORITY(P2);
end INTERRUPT2_HANDLER;
task body INTERRUPT2_HANDLER is
begin
loop
accept INTERRUPT2 do
...
-- interrupt2 code
end INTERRUPT2;
...
-- immediate2 code
end loop;
end INTERRUPT2_HANDLER;
Tomasz Szmuc’03
107
task INTERRUPT_HANDLER is
entry INTERRUPT1;
for INTERRUPT1 use at ADDRESS1;
pragma PRIORITY(P1);
entry INTERRUPT2;
for INTERRUPT2 use at ADDRESS2;
pragma PRIORITY(P2);
end INTERRUPT_HANDLER;
task body INTERRUPT_HANDLER is
begin
loop
select
accept INTERRUPT1 do
...
-- interrupt1 code
end INTERRUPT1;
...
-- immediate1 code
or
accept INTERRUPT2 do
...
-- interrupt2 code
end INTERRUPT2;
...
-- immediate2 code
end loop;
end INTERRUPT_HANDLER;
Tomasz Szmuc’03
108
task INTERRUPT_HANDLER is
entry INTERRUPT1;
for INTERRUPT1 use at ADDRESS1;
pragma PRIORITY(P1);
entry INTERRUPT2;
for INTERRUPT2 use at ADDRESS2;
pragma PRIORITY(P2);
end INTERRUPT_HANDLER;
task body INTERRUPT_HANDLER is
begin
loop
select
when C1 =>
accept INTERRUPT1
do
...
-- interrupt1 code
end INTERRUPT1;
...
-- immediate1 code
or
accept INTERRUPT2 do
...
-- interrupt2 code
end INTERRUPT2;
...
-- immediate2 code
end loop;
end INTERRUPT_HANDLER;
Tomasz Szmuc’03
109