**6.2.1 Example of the stopwatch behavior**

14 Will-be-set-by-IN-TECH

To support servers, we add an additional *server queue* for *each* server *σi*, denoted by *σi*.*sq*, to keep track of the events local to the server, i.e. delays and periodic arrival of tasks *τ<sup>j</sup>* ∈ *γ*(*σi*). At any time at most one server can be active; all other servers are inactive. The additional server queues make sure that the events local to inactive servers do not interfere with the

When a server *σ<sup>i</sup>* is switched in its server queue is activated by calling *ActivateQueue(σi.sq)*. In

1. the *system queue*, keeping track of system events, i.e. the replenishment of periodic servers, 2. the *server queue* of the *active* server, keeping track of the events local to a particular server,

When the active server is switched out (e.g. a higher priority server is resumed, or the active server gets depleted) then the active server queue is deactivated by calling *DeactivateQueue(σi.sq)*. As a result, the queue of the switched out server will be "paused", and the queue of the switched in server will be "resumed". The system queue is never deactivated. To keep track of the time which has passed since the last server switch, we introduce a *stopwatch*. The stopwatch is basically a counter, which is incremented with every tick. In order to handle time overflows discussed in Section 4.1, we represent the stopwatch as a RELTEQ

During the time when a server is inactive, several other servers may be switched in and out. Therefore, next to keeping track of time since the last server switch, for each server we also need to keep track of how long it was inactive, i.e the time since that particular server was switched out. Rather than storing a separate counter for each server, we multiplex the stopwatches for all servers onto the single stopwatch which we have already introduced, exploiting the RELTEQ approach. We do this by inserting a *stopwatch event*, denoted by *σi*.*se*, at the head of the stopwatch queue using *InsertEvent(stopwatch, σi*.*se)* whenever server *σ<sup>i</sup>* is switched out. The event points to the server and its time is initially set to 0. The behavior of the tick handler with respect to the stopwatch remains unchanged: upon every tick the head

During runtime the stopwatch queue will contain one stopwatch event for every inactive server (the stopwatch event for the currently active server is removed when the server is switched in). The semantics of the stopwatch queue is defined as follows: the accumulated time from the head of the queue until (and including) a stopwatch event *σi*.*se* represents the

When a server *σ<sup>i</sup>* is switched in, its server queue is synchronized with the stopwatch using *SyncQueuesUntilEvent(σi.sq, stopwatch, σi.se)*, which handles all the events in *σi*.*sq* which might have occurred during the time the server was switched out. It accumulates the time in the stopwatch queue until the stopwatch event *σi*.*se* and handles all the events in *σi*.*sq* which have expired during that time. Then *σi*.*se* is removed from the stopwatch queue. When *σ<sup>i</sup>* is

this new configuration the hardware timer drives two event queues:

queue and use *IncrementQueue(stopwatch)* to increment it.

time the server *σ<sup>i</sup>* was switched out.

i.e. the delays and the arrival of periodic tasks belonging to the server.

event in the stopwatch queue is incremented using *IncrementQueue(stopwatch)*.

switched out, *σi*.*se* with time 0 is inserted at the head of the stopwatch queue.

**6.2 Limiting interference of inactive servers**

currently active server.

The stopwatch queue is a great example of RELTEQ's strength. It provides an efficient and concise mechanism for keeping track of the inactive time for *all* servers. Figure 6 demonstrates the behavior of the stopwatch queue for an example system consisting of three servers *A*, *B* and *C*. It illustrates the state of the stopwatch queue at different moments during execution, before the currently running server is switched out and after the next server is switched in.

Fig. 6. Example of the stopwatch queue.

Initially, when server *σ<sup>i</sup>* is created, a stopwatch event *σi*.*se* with time 0 is inserted into the stopwatch queue. At time 0 server *A* is switched in and its stopwatch event is removed. While server *A* is running, the tick handler increments the head of the stopwatch queue, which happens to be the stopwatch event of server *B*. At time 3, when server *A* is switched out and server *B* is switched in, server *B* synchronizes its absolute queue with the stopwatch queue until and including *B*.*se*, *B*.*se* is deleted, and *A*.*se* with time 0 is inserted. Note that when *B*.*se* is deleted, its time is added to *C*.*se*.

At time 7 server *C* is switched in, its absolute queue is synchronized with time 4 + 3 = 7, after which *C*.*se* is deleted, and *B*.*se* with time 0 is inserted.

At time 9, since no server is switched in, no synchronization is taking place and no stopwatch event is deleted. Only stopwatch event *C*.*se* with time 0 is inserted, since server *C* is switched out.

At time 16, when server *B* is switched in and its stopwatch event *B*.*se* is deleted, the time of *B*.*se* is added to *C*.*se*.

**6.4 Switching servers**

*ActivateQueue(σi.sq)*; *ActivateQueue(σi.vq)*; **if** *σi*.*we* ∅ **then**

*σi*.*we* = ∅*;*

**end if**

**end if**

*DeleteEvent(σi.vq, ej)*.

larger than 0.

*DeleteEvent(system, σi.we);*

*DeleteEvent(stopwatch, σi.se)*; *σi.se = NewEvent(stopwatch, 0, σi)*; *InsertEvent(stopwatch, σi*.*se)*; *DeactivateQueue(σi.sq)*; *DeactivateQueue(σi.vq)*; **if** *σi*.*readyTasks* = ∅ **then**

*InsertEvent(system, σi.we);*

Fig. 8. Pseudocode for *ServerSwitchOut(σi)*.

**6.6 RELTEQ tick handler with support for servers**

**6.5 Server replenishment and depletion**

Fig. 7. Pseudocode for *ServerSwitchIn(σi)*.

*σi.we = NewEvent(wakeup, Head(σi.sq).time, σi);*

*SyncQueuesUntilEvent(σi.sq, stopwatch, σi.se)*;

The methods for switching servers in and out are summarized in Figures 7 and 8.

An Efficient Hierarchical Scheduling Framework for the Automotive Domain 83

We introduce two additional RELTEQ event kinds to support servers: *budget replenishment* and *budget depletion*. When a server *σ<sup>i</sup>* is created, a replenishment event *ej* is inserted into the *system queue*, with *ej.data* pointing to *σ<sup>i</sup>* and *ej.time* equal to the server's replenishment period

Upon replenishment, the server's depletion event *ej* is inserted into its *virtual server queue*, with *ej.data* pointing to *σ<sup>i</sup>* and *ej.time* equal to the server's capacity Θ*i*. If the server was not depleted yet, then the old depletion event is removed from the virtual server queue using

An example of the RELTEQ queues managed by the tick handler in the proposed RELTEQ extension with servers is summarized in Figure 9. Conceptually, every tick the stopwatch queue is incremented and the heads of the system queue, the active server queue and the active virtual server queue are decremented. If the head of any queue becomes 0, then their head event is popped and handled until the queue is exhausted or the head event has time

Actually, rather than decrementing the head of each active queue and checking whether it is 0, a *CurrentTime* counter is incremented and compared to the *Earliesttime*, which is set whenever the head of an active queue changes. If they are equal, then (i) the *CurrentTime* is subtracted from the heads of all the active queues, (ii) any head event with time 0 is popped and handled,

Π*i*. When *ej* expires, *ej.time* is updated to Π*<sup>i</sup>* and it is inserted into the system queue.
