Title: Concurrent Programming using Ada Tasking
1Concurrent Programming using Ada Tasking
- CS 472 Operating Systems
- Indiana University Purdue University Fort Wayne
- Mark Temte
2Quick introduction to Ada tasking
- Ada program units Java equivalentprocedure void
methodfunction non-void methodpackage class
task subclass of Thread classgeneric
unit type parameters (J2SE, version 1.5)
3Most Ada units are separated into a specification
and a body
- Specifications are not always required for
procedures and functions - When needed, these specifications consist of the
procedure or function signature followed by a
- The corresponding body consists of the signature
followed by is followed by declarations and a
begin-end section
4Generic unitsÂ
- An Ada generic unit is a parameterized template
for an actual procedure, function, or package - Java and generic classes
- Prior to J2SE, Version 1.5, Java had no direct
equivalent, except possibly for inheritance and
interfaces - J2SE, Version 1.5, supports type parameters
- Type parameters permit implementation of generic
classes - E is a type parameter in the following example
public class LinkedListlt E gt implements
Collectionlt E gt ? ? ? LinkedListltEmployeegt
empList new LinkedListltEmployeegt( )
5Â Example of an Ada procedure
- with Ada.Text_IO -- makes library
package Text_IO visible - -- procedures Get
and Put are now available - procedure Fibonacci is
- type Fib_Num_Type is range 0..10_000 --
declares a type - Fib Fib_Num_Type 1 --
declares three variables - Prev_Fib Fib_Num_Type 0 --
and initializes the - Next_Prev_Fib Fib_Num_Type --
first two - -- The following instantiates a gereric
package to perform I/O with - -- values of type Fib_Num_Type.
- package Fib_IO is new Ada.Text_IO.Integer_IO(
Fib_Num_Type ) - begin -- Fibonacci
- Ada.Text_IO.Put( "Fibonacci numbers follow"
) -- output by procedures in - Ada.Text_IO.New_Line( Spacing gt 2 )
-- Text_IO package - --
- Fib_IO.Put( Prev_Fib ) --
output by procedure in Fib_IO - Ada.Text_IO.New_Line
- Fib_IO.Put( Fib ) --
output by procedure in Fib_IO - Ada.Text_IO.New_Line
- --
6An Ada task
- is a thread within an Ada application
- It may not stand alone
- It must be nested within a master
- The master is typically a procedure
- starts executing automatically when master begins
- consists of a specification and a body
- communicates and synchronizes with other tasks
using a simple high-level rendezvous
7An Ada task
- is relatively easy to demonstrate to be correct
- has task states
- Running
- Ready unblocked waiting for a processor
- Blocked delayed or waiting to rendezvous
- Completed at end
- Terminated no longer active
8Example of nesting tasks in a procedure
- procedure Master is task A --
specification for A task B --
specification for B task body A is --
body of A task body B is -- body of
B begin -- Master null -- tasks A and
B begin execution end Master
9Â Format of a task body (similar to the body of
a procedure)
- task body A is ltdeclarationsgt begin -- A
ltactivitygt exception -- this section is
optional lthandlersgt end A
10Â Task type
- A task type is a template for an actual task
- Many actual tasks may be created from the
template.  task type TypeT -- specification
of task typetask body TypeT is -- body - T1 TypeT -- declaration of an actual task
T1 - T2 TypeT -- declaration of another actual
task T2
11A task type may be parameterized
- with Ada.Text_IO
- procedure Two_Tasks is
- task type SimpleTask (Message Character
HowMany Positive) - Â --
- task body SimpleTask is
- begin -- SimpleTask
- for Count in 1..HowMany loop
- Ada.Text_IO.Put("Hello from Task "
Message) - Ada.Text_IO.New_Line
- end loop
- end SimpleTask
- Â --
- Task_A SimpleTask(Message gt 'A', HowMany gt
5) - Task_B SimpleTask(Message gt 'B', HowMany gt
7) - Â --
- begin -- Two_Tasks
- -- Task_A and Task_B will both start executing
as soon as control - -- reaches this point, before any of the main
program's - -- statements are executed. The Ada standard
does not specify
12Rendezvous basics
- Tasks communicate using a rendezvous
- Exactly two tasks may rendezvous a a time
- a caller
- a server
- The server must have an entry declared in its
specification - An entry resembles a procedure specification
- An entry may be called whenever a procedure may
be called - An entry call resembles a procedure call
13Rendezvous basics
- Entries (and calls) may involve parameters for
communication - As in the case of procedures, parameters may have
modes in, out and in out - No parameters are needed just for synchronization
- A server task accepts a call to its entry using
an accept statement - The caller must know the names of the servers
entries, but the server does not know the caller
14Rendezvous basics
caller task
server task
call
accept
accept
call
15Example - An entry is used just for
synchronization
- with Ada.Text_IO
- procedure Start_Buttons is
- task type SimpleTask (Message Character
HowMany Positive) is - entry StartRunning
- end SimpleTask
- Â --
- task body SimpleTask is
- begin -- SimpleTask
- accept StartRunning
- for Count in 1..HowMany loop
- Ada.Text_IO.Put(Item gt "Hello from Task "
Message) - Ada.Text_IO.New_Line
- delay 0.1 -- lets another task have the
CPU - -- Note delay is NOT a good way
to do this! - end loop
- end SimpleTask
- Â --
- Task_A SimpleTask(Message gt 'A', HowMany gt
5) - Task_B SimpleTask(Message gt 'B', HowMany gt
7)
16Rendezvous semantics
- If one task gets to the rendezvous point (either
a call or an accept) in its code before the
other, it waits until the other task arrives - During execution of an accept statement within a
server task (the actual rendezvous), the caller
waits - At the conclusion, both tasks may resume
17Rendezvous semantics
- Execution of an accept statement serves a single
call - This insures access to the servers data under
mutual exclusion - Callers to an entry must wait in a FIFO queue
- Attribute NameCount gives the number of callers
waiting on entry Name
18Example of a task used to represent a stack
- Â This involves a task specification with entries
and parameters -
- task Stack is entry Push( Value in
Integer) entry Pop( Value out
Integer) end Stack A call to Push within
some caller task looks like - Â ? ? ? Stack.Push( 23) ? ? ?
19Format of accept statement within Stack task
- accept Push( Value in Integer ) do
- ltactivity done under mutual exclusiongtend
Push - Activity done under mutual exclusion should be
kept to a minimum
20Â The body of Stack task
- task body Stack is type ArrayType is array(
1 .. 100 ) of Integer S ArrayType
Top Natural 0begin Stack loop
? ? ? accept Push( Value in
Integer ) Top Top 1
S( Top ) Value end Push
? ? ? end loopend Stack
21Â Selective wait statementÂ
- The selective wait statement allows the server to
control the acceptance of entry calls - It may appear within a server task
22Â Format of selective wait statement
- select when ltcondition1gt gt -- a
guard accept A( ? ? ? ) do ? ? ? end
Aor -- no guard alternative always open
accept B( ? ? ? ) do ? ? ? end Bor - when ltcondition2gt gt -- another guard
accept C( ? ? ? ) do ? ? ? end C-- the
boxed items are optional choices - else or or ltseq. of stmtsgt delay
10.0 terminate - ltseq. of stmtsgt
- end select
23Selective wait semantics
- Guard conditions are evaluated at the top of the
select statement - A select alternative is open if a guard is true
or if there is no guard - An optional else-part is evaluated only if no
pending calls exist to any open alternatives - If there is no else-part and there are no pending
calls to open alternatives, the server waits
24Selective wait semantics
- If pending calls exist to several open
alternatives, a fair selection is made - With a delay alternative, the sequence of
statements is executed only if no rendezvous has
occurred by the delay time - A terminate alternative takes effect only if all
other tasks (and parent task) are waiting at end
or terminate - In this case all terminate together
- No else-part is permitted with delay or terminate
alternatives
25Example involving the Stack task
- loop select accept Push( ? ? ? ) do
? ? ? end Push or accept Pop( ?
? ? ) do ? ? ? end Pop or
terminate end selectend loop
26More on delay and select
- Another use of the delay statement is for a task
to preempt itself with delay 0.1 - This can be useful when the Ada run-time system
does not use pre-emption (i.e., no time slicing)
and allows each task to run until it blocks - The select statement is also used for conditional
and timed entry calls on the part of the caller
27Format for conditional and timed entry calls
- select Stack.Pop( Item ) ltother
statememtsgt - -- one choice required below
- else or ltseq. of stmtsgt
delay 10.0 ltseq. of stmtsgt - end selectÂ
28Conditional and timed entry call semantics
- A conditional entry call uses the reserved word
else and a timed entry call uses the reserved
words or delay - The else-part of a conditional entry call is
executed if an entry call is not accepted by the
server immediately
29Conditional and timed entry call semantics
- For a timed entry call, the delay alternative is
executed if an entry call is not accepted by the
delay time - If either an else-part or a delay alternative is
executed, the associated entry call is cancelled
and the caller may continue - Also, the Count attribute is decremented
30Example involving the Stack task
- select Stack.Push( 23)else nullend
loop
31Common output problem
- Suppose several tasks need to call procedure
Write - Want to prevent separate output sequences from
being mixed together - Want to allow each call to Write to finish before
next call is accepted - A simple solution is desirable
- Want to avoid creating another task
32Protected type
- Use a protected type to enclose the Write
procedure - The protected type implements a simple monitor
for mutual exclusion - Prevents the race condition
33Example
-
- protected type Manager is
- procedure Write()
- end Manager
- --
- protected body Manager is
- procedure Write(? ? ? ) is
- ? ? ?
- end Write
- end Manager
- --
- PrintManager Manager
- -- declares a protected object managing access
to the Write procedure
34Example (continued)
- Now tasks TaskA and TaskB do not interleave
their output - TaskA TaskB
- ? ? ? ? ? ?
- PrintManager.Write(? ? ? )
PrintManager.Write(? ? ? ) - ? ? ? ? ? ?
35Protected type semantics
- The protected type guarantees that each call to a
protected procedure will complete before another
call can be started - If there are several procedures within the same
protected object, a call to any of them must
complete before a call to any other is allowed to
start