TimeServer

Overview

The TimeServer uses a hardware timer and gives its clients access to one or more timers based on this hardware timer.

Implementation

The TimeServer uses the platform-specific timer modules from the seL4 platform support library. This component allows multiple clients to share a hardware timer for common functions such as sleep, periodic notifications or getting a timestamp. Each client component can have up to four timers, which can be used for one purpose at a time only.

The TimeServer offers the if_OS_Timer CAmkES interface, but for ease of use it also supports a client library which wraps a subset of the CAmkES interface’s functionality.

Usage

This is how the component can be instantiated in the system.

Declaration of the Component in CMake

The TimeServer can be declared via a simple macro in the CMakeLists.txt file:

TimeServer_DeclareCAmkESComponent(
    <NameOfComponent>
)

If a component wants to use the client interface of the TimeServer, the component needs to add <NameOfComponent>_client to its LIBS parameter; it can then include TimeServer.h and use the simplified client API instead of accessing the RPC interface directly.

DeclareCAmkESComponent(
    <Client>
    SOURCES
        ...
    C_FLAGS
        ...
    LIBS
        ...
        <NameOfComponent>_client
)

Instantiation and Configuration in CAmkES

In order to wire the TimeServer to a set of clients, it has to be declared, instantiated, connected and configured in the main CAmkES composition of the system.

Declaring the Component

The component is simply declared in the main CAmkES file by using its respective macro:

#include "TimeServer/camkes/TimeServer.camkes"
TimeServer_COMPONENT_DEFINE(
    <NameOfComponent>
)

This declares a component type (i.e., a server), which can be instantiated multiple times later. The <NameOfComponent> must correspond to the name chosen in the CMakeLists.txt file, where the source code of the server is defined.

Instantiating and Connecting the Component

The following macro allows creating an instance of the TimeServer component (i.e., the server) and connects it to one (or more) clients. These clients have to use the if_OS_Timer interface (see <nameOfInterface>) and a signal sink (see <nameOfEvent>) to interact with the TimeServer instance.

component <NameOfComponent> <nameOfInstance>;

TimeServer_INSTANCE_CONNECT_CLIENTS(
    <nameOfInstance>,
    <client1>.<nameOfInterface>, <client1>.<nameOfEvent>,
    <client2>.<nameOfInterface>, <client2>.<nameOfEvent>,
    ...
)

Please note that up to 8 clients can be connected like this.

Configuring the Instance

The TimeServer is configured to allow up to four timers per client. To change this value, the following parameter can be set:

  • timers: an integer indicating the number of timers a single client can use

The full macro looks like this:

TimeServer_INSTANCE_CONFIGURE(
    <nameOfInstance>,
    <timers>
)

Assigning Clients’ Badges

The TimeServer uses the “badge” assigned by seL4 to each client’s RPC endpoint to manage client-specific states (e.g., timers). Badges can be assigned via this macro:

TimeServer_CLIENT_ASSIGN_BADGES(
    <client1>.<nameOfInterface>,
    <client2>.<nameOfInterface>,
    ...
)

Please note that the order of clients needs to correspond to the order TimeServer_INSTANCE_CONNECT_CLIENTS() macros. The TimeServer can handle up to 8 clients.

Example

In the following example, we have one instance of the TimeServer and one client using it to sleep for a certain time.

Instantiation of the Component in CMake

The component is added to the system as MyTimeServer:

TimeServer_DeclareCAmkESComponent(
    MyTimeServer
)

Additionally, we would like to use the simplified interface so we add the specific client library to the component that wants to use the TimeServer instance:

DeclareCAmkESComponent(
    Client
    SOURCES
        ...
    C_FLAGS
        ...
    LIBS
        ...
        MyTimeServer_client
)

Instantiation and Configuration in CAmkES

The component needs to be declared and connected to its respective clients.

Declaring the Component

The component is declared as MyTimeServer in the main CAmkES file. The name must correspond to the name used above in the CMakeLists.txt file:

#include "TimeServer/camkes/TimeServer.camkes"
TimeServer_INSTANCE_CONFIGURE(
    MyTimeServer
)

Instantiating and Connecting the Component

The following code fragment instantiates the TimeServer and connects it to the clients:

// Instantiate TimeServer component
component MyTimeServer      myTimeServer;
// Instantiate two clients
component Client            client1;
component Client            client2;

// Connect interfaces PROVIDED by the TimeServer
TimeServer_INSTANCE_CONNECT_CLIENTS(
    myTimeServer,
    client1.timer_rpc, client1.timer_notify
    client2.timer_rpc, client2.timer_notify
)

In this example, the clients are using names timer_rpc for its local RPC endpoint and timer_notify for the respective signal sink.

Assigning Clients’ Badges

We assign the badges to the clients’ RPC endpoints via this macro:

TimeServer_CLIENT_ASSIGN_BADGES(
    client1.timer_rpc,
    client2.timer_rpc
)

Using the Component’s Interfaces in C

If the component that wants to use the TimeServer has included the respective client library, we can use the simplified interface in the C code, instead of calling the CAmkES RPC interface directly.

Please note how the endpoint name and signal sink are referred when assigning the CAmkES interface via IF_OS_TIMER_ASSIGN().

// For TimeServer client wrapper
#include "TimeServer.h"

// For the CAmkES generated interface
#include <camkes.h>

// Assign the RPC endpoint based on the names used by this client
static const if_OS_Timer_t timer =
    IF_OS_TIMER_ASSIGN(
        timer_rpc,
        timer_notify);

...

int run() {
    ...
    // Sleep for one second
    TimeServer_sleep(&timer, TimeServer_PRECISION_SEC, 1);
    ...
}