Entry calls and barriers

Một phần của tài liệu Burns, wellings concurrent and real time programming in ada (Trang 151 - 155)

To issue a call to a protected object, a task simply names the object and the required subprogram or entry. For example, to place some data into the above bounded buffer requires the calling task to do

My_Buffer.Put(Some_Item);

As with task entry calls, the caller can use the select statement to issue atimedor conditionalentry call.

Important note:

At any instant in time, a protected entry is either open or closed. It is open if, when checked, the boolean expression evaluates to true;

otherwise it is closed. Generally, the protected entry barriers of a protected object are evaluated when:

a task calls one of its protected entries and the associated barrier references a variable or an attribute that might have changed since the barrier was last evaluated; or

a task executes and leaves a protected procedure or protected en- try and there are tasks queued on entries that have barriers which reference variables or attributes that might have changed since the barriers were last evaluated.

Barriers are not evaluated as a result of a protected function call.

Warning: A program should not use shared variables in barriers and should not rely on the exact circumstances in which barriers are re-evaluated (that is, an implementation may evaluate them more often than is strictly necessary). However, note that it is safe to use the Count attribute in a barrier (compared with the use of this attribute as part of a guard within the select statement – see Section 6.5). This is because adding and subtracting a task to and from an entry queue is a protected action (see below).

When a task calls a protected entry or a protected subprogram, the protected ob- ject may already be locked: if one or more tasks are executing protected functions inside the protected object, the object is said to have an activeread lock; if a task is executing a protected procedure or a protected entry, the object is said to have an activeread/write lock. The following actions take place when a task attempts to enter a protected object (in the order given):

(1) If the protected object has an active read lock and the call is a function call, the function is executed and step (14) is executed afterwards.

(2) If the protected object has an active read lock and the call is an entry or a procedure call, the call is delayed while there are tasks active in the pro- tected object.

(3) If the protected object has an active read/write lock, the call is delayed whilst there are tasks with conflicting access requirements active in the pro- tected object.

(4) If the protected object has no active lock and the call is a function call, the protected object read lock becomes active and step (5) is executed.

(5) The function is executed; step (14) is then executed.

(6) If the protected object has no active lock and the call is a procedure or entry call, the protected object read/write lock becomes active and step (7) is executed.

(7) If the call is a procedure call, the procedure is executed and step (10) is then executed.

(8) If the call is an entry call, its associated barrier is evaluated (if necessary) and if true the entry body is executed; step (10) is then executed.

(9) If the barrier is false, the call is placed on a queue associated with the barrier (any timed or conditional entry calls are considered now) and step (10) is executed.

(10) Any entry barriers with tasks queued whose barriers reference variables or attributes which might have changed since they were last evaluated are re-evaluated, and step (11) is executed.

(11) If there are any open entries, one is chosen (the core language does not define which one, although selection policies can be defined by the pro- grammer if the Real-Time Systems Annex is supported, see Chapter 13), the associated entry body is executed, and step (10) is executed.

(12) If no barriers with queued tasks are open, then step (13) is executed.

(13) If one or more tasks are delayed awaiting access to the protected object then either a single task that requires the read/write lock is allowed to enter, or all tasks that require the read lock are allowed to enter and step (5), (7) or (8) is executed (by the associated task); otherwise the access protocol is finished.

(14) If no tasks are active in the protected object, step (13) is executed; otherwise the access protocol is finished.

Note that the semantics do not require the task to be queued or the run-time scheduler to be called. There is no suspended state associated with attempting to gain access to a protected object. Although this at first may seem strange, the Real-Time Systems Annex defines an implementation model which guarantees that the task can never be delayed when attempting to enter a protected object (see Section 13.3).

7.4 Entry calls and barriers 137

Important note:

The main point to note about the actions performed above is that when a protected procedure or entry is executed (or when a task queues on an entry), entry barriers are re-evaluated and, potentially, entry bodies are executed.It is not defined which task executes these entry bodies; it may be the task that issues the associated entry call, or the current task that caused the entry to become open.

This issue will be discussed further in Chapter 13 when the Real-Time Systems An- nex is considered. Furthermore, timed and conditional entry calls are not consid- ered until the task is placed on an entry queue; any delay in accessing the protected object is not considered to be a suspension.

A task that is already active in a protected object can call a subprogram in the same protected object; this is considered to be an internal call and therefore exe- cutes immediately.

TheCountattribute

Protected object entries, like task entries, have aCountattribute defined that gives the current number of tasks queued on the specified entry.

Important note:

Even if a task is destined to end up on an entry queue (due to the barrier being closed), it requires the read/write lock to be placed on the queue. Moreover, having been put on the queue, the Count attribute will have changed (for that queue) and hence any barriers that have made reference to that attribute will need to be re-evaluated.

Similarly, removal of a task from an entry queue (as a result of a timed entry call or because the caller has been aborted) requires the read/write lock.

This is reflected in step (10) above. To give an example of the use of theCount attribute consider a protected object that blocks calling tasks until five are queued;

they are then all released:

protected Blocker is entry Proceed;

private

Release : Boolean := False;

end Blocker;

protected body Blocker is

entry Proceed when Proceed’Count = 5 or Release is begin

if Proceed’Count = 0 then

Release := False;

else

Release := True;

end if;

end Proceed;

end Blocker;

When the fifth task callsBlocker.Proceed, it will find that the barrier eval- uates to false and hence it will be blocked. But the barrier will then be re-evaluated (as’Counthas changed). It now evaluates to true and the first task in the queue will execute the entry. TheReleaseboolean variable ensures that all the other four tasks will then pass through the barrier. The last one, however, ensures that the barrier is set to false again. Note that whilst releasing the five tasks, it is not possible for another task to become queued on the entry. This is because queuing a task on an entry requires the read/write lock, and this is not released until the fifth task has left the protected object.

To give a more concrete example of the use of protected objects consider the telephone example used in previous chapters. Some receiver has decided to make use of an answering phone; if a caller cannot make a direct connection (rendezvous) within a specified time interval, then a message is left on the answering phone.

This phone has a finite capacity and hence may become full. The telephone is represented by a package:

with Message_Type; use Message_Type;

package Telephone is

procedure Call(M : Message);

-- for some appropriate message type Not_Operational : exception;

end Telephone;

The body of this package contains the taskClientrepresenting the receiver, a protected object (Answering Machine) and the implementation of the proce- dureCall:

package body Telephone is

Timeout_On_Client : constant Duration := 15.0;

Timeout_On_Answering_Machine : constant Duration := 2.0;

Max_Messages : constant Positive := 64;

type Message_Set is ...;

task Client is

entry Call(M : Message);

end Client;

protected Answering_Machine is entry Call(M : Message);

procedure Replay(MS : out Message_Set);

private

Một phần của tài liệu Burns, wellings concurrent and real time programming in ada (Trang 151 - 155)

Tải bản đầy đủ (PDF)

(477 trang)