**8.1 Modularity and memory footprint**

20 Will-be-set-by-IN-TECH

task belonging to that server. This approach allows to implement different global and local schedulers, and also different schedulers in each server. Our fixed-priority global scheduler is

The *currentServer* is a global variable referring to the currently active server. Initially

The scheduler first determines the highest priority ready server. Then, if the server is different

1. If there is a currently active server, then it is switched out, using *ServerSwitchOut()*

2. If there is a ready server, then it is switched in, using *ServerSwitchIn()* described in Section

Finally the highest priority task in the currently active server is selected, using the current server's local scheduler *HighestReadyTask()*. If no server is active, then the idle task is returned.

When a server becomes depleted during the execution of one of its tasks (i.e. if a depletion event expires), the task will be preempted and the server will be switched out. This is possible,

In this section we evaluate the modularity, memory footprint and performance of the HSF extension for RELTEQ. We chose a linked-list as the data structure underlying our RELTEQ

from the currently active server, a server switch is performed, composed of 3 steps:

shown in Figure 11.

**end if**

**end if**

**end if**

**else**

**end if**

6.4.

**7.4 Enforcement**

**8. Evalulation**

*highestServer* := *HighestReadyServer*(); **if** *highestServer currentServer* **then if** *currentServer* ∅ **then**

*ServerSwitchOut*(*currentServer*);

*ServerSwitchIn*(*highestServer*);

**return** *currentServer*.*HighestReadyTask*();

Fig. 11. Pseudocode for the hierarchical scheduler.

*currentServer* = ∅, where ∅ refers to a null pointer.

since we assume preemptive and independent tasks.

queues and implemented the proposed design within *μ*C/OS-II.

*currentServer* := *highestServer*;

**if** *highestServer* ∅ **then**

**if** *currentServer* ∅ **then**

described in Section 6.4.

3. The *currentServer* is updated.

**return** *idleTask*;

The design of RELTEQ and the HSF extension is modular, allowing to enable or disable the support for HSF and different server types during compilation with a single compiler directive for each extension.

The complete RELTEQ implementation including the HSF extension is 1610 lines of code (excluding comments and blank lines), compared to 8330 lines of the original *μ*C/OS-II. 105 lines of code were inserted into the original *μ*C/OS-II code, out of which 60 were conditional compilation directives allowing to easily enable and disable our extensions. No original code was deleted or modified. Note that the RELTEQ+HSF code can replace the existing timing mechanisms in *μ*C/OS-II, and that it provides a framework for easy implementation of other scheduler and servers types.

The 105 lines of code represent the effort required to port RELTEQ+HSF to another operating system. Such porting requires (i) redirecting the tick handler to the RELTEQ handler, (ii) redirecting the method responsible for selecting the the highest priority task to the HSF scheduler, and (iii) identifying when tasks become ready or blocked.

The code memory footprint of RELTEQ+HSF is 8KB, compared to 32KB of the original *μ*C/OS-II. The additional data memory foot print for an application consisting of 6 servers with 6 tasks each is 5KB, compared to 47KB for an application consisting of 36 tasks (with a stack of 128B each) in the original *μ*C/OS-II.

## **8.2 Performance analysis**

In this section we evaluate the system overheads of our extensions, in particular the overheads of the scheduler and the tick handler. We express the overhead in terms of the maximum number of events inside the queues which need to be handled in a single invocation of the scheduler or the tick handler, times the maximum overhead for handling a single event.

### **8.2.1 Handling a single event**

Handling different events will result in different overheads.


The system queue contains only replenishment and wakeup events. Its size is therefore

An Efficient Hierarchical Scheduling Framework for the Automotive Domain 89

inside the global system queue. *tg* is the longest time interval between any two events inside

The size of *σi*.*sq* is linear in the number of tasks assigned to the server. Similarly, since *σi*.*vq* contains one depletion event and at most one virtual timer for each task, its size is linear in

Therefore, when server *σ<sup>i</sup>* is active at the time the tick handler is invoked, the tick handler will need to handle *tt*(*σi*) = |Σ| + *dg* + *m*(*σi*) + *dl*(*σi*) events. The complexity of the tick handler is therefore *O*(max*σi*∈<sup>Σ</sup> *m*(*σi*)*tt*(*σi*)). Note that the tick handler overhead depends only on tasks belonging to the server *σ<sup>i</sup>* which is active at the time of the tick. It does not depend on tasks

In Section 6.2 we introduced wakeup events in order to limit the interference due to inactive servers. In order to validate this approach we have also implemented a variant of the HSF scheduler which avoids using wakeup events and instead, whenever a deferrable server *σ<sup>i</sup>* is switched out, it keeps the server queue *σi*.*sq* active. Consequently, the scheduler does not need to synchronize the server queue when switching in a server. However, this overhead is shifted to the tick handler, which needs to handle the expired events in all the server queues from inactive deferrable servers. In the following discussion we refer to this approach as *without limited interference*, as opposed to *with limited interference* based on wakeup events.

Figures 12.a to 12.e compare the two variants. We have varied the number of deferrable servers and the number of tasks assigned to each server (all servers had the same number of tasks). The server replenishment periods and the task periods were all set to the same value (100ms), to exhibit the maximum overhead by having all tasks arrive at the same time. Each task had a computation time of 1ms and each server had a capacity of 7ms. We have run the setup within the cycle-accurate hardware simulator for the OpenRISC 1000 architecture OpenCores (2010). We have set the processor clock to 345MHz and the tick to 1KHz, which is inline with the platform used by our industrial partner. Each experiment was run for an

Figures 12.a and 12.b show the maximum measured overheads of the scheduler and the tick handler, while Figures 12.c and 12.d show the total overhead of the scheduler and the tick handler in terms of processor utilization. The figures demonstrate that wakeup events reduce the tick overhead, at the cost of increasing the scheduler overhead, by effectively shifting the overhead of handling server's local events from the tick handler to the scheduler. Since the scheduler overhead is accounted to the server which is switched in, as the number of servers and tasks per server increase, so does the advantage of the limited interference approach. Figure 12.e combines Figures 12.c and 12.d and verifies that the additional overhead due to

Figure 12.f compares the system overheads of our HSF extension to the standard *μ*C/OS-II implementation. As the standard *μ*C/OS-II does not implement hierarchical scheduling, we have implemented a flat system containing the same number of tasks with the same parameters as in Figures 12.a and 12.b. The results demonstrate the temporal isolation and

the wakeup events in the limited interference approach is negligible.

is the maximum number of dummy events

 *tg* 2*<sup>n</sup>*−1 

proportional to |Σ| + *dg*, where *dg* =

the number of tasks assigned to the server.

belonging to other servers.

**8.2.4 Experimental results**

integral number of task periods.

the global system queue (i.e. the longest server period).


### **8.2.2 Scheduler**

Our HSF supports different global and local schedulers. For the sake of a fair comparison with the *μ*C/OS-II which implements a fixed-priority scheduler, we also assume fixed-priority global and local schedulers in this section. For both global and local scheduling we can reuse the bitmap-based approach implemented by *μ*C/OS-II, which has a constant time overhead for selecting the highest priority ready task as well as indicating that a task is ready or not (Labrosse, 2002). Consequently, in our HSF we can select the highest priority server and task within a server in constant time.

Once a highest priority server *σ<sup>i</sup>* is selected, the overhead of switching in the server depends on the number of events inside the stopwatch queue and *σi*'s server queue (which needs to be synchronized with the stopwatch), and the overhead of selecting the highest priority task.

The stopwatch queue contains one stopwatch event for each inactive server. The length of the stopwatch queue is therefore bounded by |Σ| + *ds*, where |Σ| is the number of servers, and *ds* = max*σi*∈<sup>Σ</sup> *ts*(*σi*) 2*<sup>n</sup>*−1 is the maximum number of dummy events inside the stopwatch queue. *ts*(*σi*) is the longest time interval that a server can be switched out, and 2*<sup>n</sup>* <sup>−</sup> 1 is the largest relative time which can be represented with *n* bits.

The only local events are a task delay and the arrival of a periodic task. Also, each task can wait for at most one timed event at a time. The number of events inside the server queue is therefore bounded by *m*(*σi*) + *dl*(*σi*), where *m*(*σi*) is the maximum number of tasks assigned to server *<sup>σ</sup>i*, and *dl*(*σi*) = *tl*(*σi*) 2*<sup>n</sup>*−1 is the maximum number of dummy events local to the server queue *σi*.*sq*. *tl*(*σi*) is the longest time interval between any two events inside of *σi*.*sq* (e.g. the longest task period or the longest task delay).

The complexity of the scheduler is therefore *O*(|Σ| + *ds* + *m*(*σi*) + *dl*(*σi*)). Note that the maximum numbers of dummy events *ds* and *dl*(*σi*)) can be determined at design time.

#### **8.2.3 Tick handler**

The tick handler synchronizes all active queues with the current time, and (in case an event was handled) calls the scheduler. The active queues are comprised of the system queue and two queues for the server *σ<sup>i</sup>* which is active at the time the tick handler is invoked (its server queue *σi*.*sq* and virtual server queue *σi*.*vq*).

<sup>4</sup> Inserting the next replenishment event could be deferred until the server is depleted, at a similar cost and benefit to deferring the insertion of the task period event.

The system queue contains only replenishment and wakeup events. Its size is therefore proportional to |Σ| + *dg*, where *dg* = *tg* 2*<sup>n</sup>*−1 is the maximum number of dummy events inside the global system queue. *tg* is the longest time interval between any two events inside the global system queue (i.e. the longest server period).

The size of *σi*.*sq* is linear in the number of tasks assigned to the server. Similarly, since *σi*.*vq* contains one depletion event and at most one virtual timer for each task, its size is linear in the number of tasks assigned to the server.

Therefore, when server *σ<sup>i</sup>* is active at the time the tick handler is invoked, the tick handler will need to handle *tt*(*σi*) = |Σ| + *dg* + *m*(*σi*) + *dl*(*σi*) events. The complexity of the tick handler is therefore *O*(max*σi*∈<sup>Σ</sup> *m*(*σi*)*tt*(*σi*)). Note that the tick handler overhead depends only on tasks belonging to the server *σ<sup>i</sup>* which is active at the time of the tick. It does not depend on tasks belonging to other servers.
