Rev 929 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/**
\mainpage FSF reference
This reference manual contains the description of the API provided
by the FSF library.
\section intro Introduction to FSF
The First Scheduling Framework (FSF) is the result of a joint
effort from four european research groups to propose an API for
flexible real-time scheduling in Real Time operating systems. See
the FIRST web page <a
href="http://130.243.76.81:8080/salsart/first/">
(http://130.243.76.81:8080/salsart/first/)</a> for more details in
the project.
\section lib Objectives
Scheduling theory generally assumes that real-time systems are mostly
composed of activities with hard real-time requirements.
Many systems are built today by composing different application or
components in the same system, leading to a mixture of many different
kinds of requirements with small parts of the system having hard
real-time requirements and other larger parts with requirements for
more flexible scheduling, taking into account quality of service. Hard
real-time scheduling techniques are extremely pessimistic for the
latter part of the application, and consequently it is necessary to
use techniques that let the system resources be fully utilized to
achieve the highest possible quality.
The FIRST project aims at developing a framework for a scheduling
architecture that provides the ability to compose several applications
or components into the system, and to flexibly schedule the available
resources while guaranteeing hard real-time requirements. The FIRST
Scheduling Framework (FSF) is independent of the underlying
implementation, and can run on different underlying scheduling
strategies. It is based on establishing service contracts that
represent the complex and flexible requirements of the application,
and which are managed by the underlying system to provide the required
level of service.
FSF provides a generalized architecture framework that combines
different kinds of requirements:
- co-operation and coexistence of standard real-time scheduling
schemes, time triggered and event triggered, dynamic and fixed
priority based, as well as off-line based through a common
architecture that is independent on the underlying scheduling
mechanism
- integration of different timing requirements such as hard and soft,
and more flexible notions
- temporal encapsulation of subsystems in order to support the
composability and reusability of available components including
legacy subsystems.
FSF has been implemented in two POSIX compliant real-time operating
systems, <a href="http://marte.unican.es">MaRTE</a> and <a
href="http://shark.sssup.it/">SHARK</a>, which are based on FP and EDF
scheduling schemes, respectively, thus illustrating the platform
independence of the presented approach.
\section Service Contracts
The service contract is the mechanism that we have chosen for the
application to dynamically specify its own set of complex and flexible
execution requirements. From the application's perspective, the
requirements of an application or application component are written as
a set of service contracts, which are negotiated with the underlying
implementation. To accept a set of contracts, the system has to check
as part of the negotiation if it has enough resources to guarantee all
the minimum requirements specified, while keeping guarantees on all
the previously accepted contracts negotiated by other application
components. If as a result of this negotiation the set of contracts is
accepted, the system will reserve enough capacity to guarantee the
minimum requested resources, and will adapt any spare capacity
available to share it among the different contracts that have
specified their desire or ability for using additional capacity.
As a result of the negotiation process, if a contract is accepted, a
server is created for it. The server is a software object that is the
run-time representation of the contract; it stores all the information
related to the resources currently reserved for that contract, the
resources already consumed, and the resources required to handle the
budget consumption and replenishment events in the particular
operating system being used.
Because there are various application requirements specified in the
contract, they are divided into several groups, also allowing the
underlying implementation to give different levels of support trading
them against implementation complexity. This gives way to a modular
implementation of the framework, with each module addressing specific
application requirements. The minimum resources required by the
application to be reserved by the system are specified in the core
module. The requirements for mutual exclusive synchronization among
parts of the application being scheduled by different servers or among
different applications are specified in the shared objects
module. Flexible resource usage is associated with the spare capacity
and dynamic reclamation modules. The ability to compose applications
or application components with several threads of control, thus
requiring hierarchical scheduling of several threads inside the same
server are supported by the hierarchical scheduling module. Finally,
the requirements of distributed applications are supported by the
distributed and the distributed spare capacity modules. We will now
explain these modules together with their associated application
requirements.
*/
/**
\defgroup coremodule Core module
The core module contains the service contract information related to
the application minimum resource requirements, the operations required
to create contracts and negotiate them, and the underlying
implementation of the servers with a resource reservation mechanism
that allows the system to guarantee the resources granted to each
server.
This module includes the basic functions and services that are
provided by any FSF implementation. This module includes basic type
definitions, and functions to
- create a contract and initialize it
- set/get the basic parameters of a contract
- negotiate a service contract, obtaining a server id
- create and bind threads to servers
- create/destroy a synchronization object
- manage bounded workloads
A round-robin background scheduling policy is available for those
threads that do not have real-time requirements. Because some of
these threads may require sharing information with other threads
run by regular servers, special background contracts may be created
for specifying the synchronization requirements.
The way of specifying a background contract is by setting
budget_min = period_max = 0. Negotiation may fail if the contract
uses shared_objects. If the contract has no shared_objects the
returned server id represents the background and may be used to
bind more than one thread. If the contract has shared objects a
server is created to keep track of them, but the associated threads
are executed in the background, together with the other background
threads.
An abstract synchronization object is defined by the application.
This object can be used by an application to wait for an event to
arrive by invoking the fsf_schedule_triggered_job() operation. It
can also be used to signal the event either causing a waiting
server to wake up, or the event to be queued if no server is
waiting for it.
These objects are used to synchronize threads belonging to bounded
workload servers.
In the future we may add a broadcast operation that would signal a
group of synchronization objects. We have not included a broadcast
service in this version because it can be easily created by the
user by signalling individual synchronization objects inside a
loop.
Notice that for synchronization objects there is no naming service
like in shared objects because tasks that use synchronization are
not developed independently, as they are closely coupled.
*/
/**
\defgroup sparemodule Spare capacity sharing module
Many applications have requirements for flexibility regarding the
amount of resources that can be used. The spare capacity module allows
the system to share the spare capacity that may be left over from the
negotiation of the service contracts, in a static way. During the
negotiation, the minimum requested resources are granted to each
server, if possible. Then, if there is any extra capacity left, it is
distributed among those applications that have expressed their ability
to take advantage of it.
This module includes functions for sharing the spare capacity in the
system between the servers. It allows to mainly to specify
additional contract parameters to allow the sharing of the spare
capacity.
The features provided by this module are different from the
services provided by the Dynamic reclamation module. This module
influences the negotiation procedure (see the \ref coremodule
module).
*/
/**
\defgroup hiermodule Hierarchical scheduling module
One of the application requirements that FSF addresses is the ability
to compose different applications, possibly using different scheduling
policies, into the same system. This can be addressed with support in
the system for hierarchical scheduling. The lower level is the
scheduler that takes care of the service contracts, using an
unspecified scheduling policy (for instance, a CBS on top of EDF, or a
sporadic server on top of fixed priorities). The top level is a
scheduler running inside one particular FSF server, and scheduling the
application threads with whatever scheduling policy they were
designed. In this way, it is possible to have in the same system one
application with, for example, fixed priorities, and another one
running concurrently with an EDF scheduler.
We are currently providing three top-level schedulers: fixed
priorities, EDF, and table-driven.
*/
/**
\defgroup shobjmodule Shared Objects module
The shared objects module of FSF allows the application to specify in
the contract attributes all the information related to the mutually
exclusive use of shared resources that is required to do the
schedulability analysis.
The set of shared objects present in the system together with the
lists of critical sections specified for each contract are used for
schedulability analysis purposes only. A run-time mechanism for mutual
exclusion is not provided in FSF for two important reasons. One of
them is upward compatibility of previous code using regular primitives
such as mutexes or protected objects (in Ada); this is a key issue if
we want to persuade application developers to switch their systems to
the FSF environment. The second reason is that enforcing worst case
execution time for critical sections is expensive. The number of
critical sections in real pieces of code may be very high, in the tens
or in the hundreds per task, and monitoring all of them would require
a large amount of system resources.
The FSF application does not depend on any particular synchronization
protocol, but there is a requirement that a budget expiration cannot
occur inside a critical section, because otherwise the blocking delays
could be extremely large. This implies that the application is allowed
to overrun its budget for the duration, at most, of the critical
section, and this extra budget is taken into account in the
schedulability analysis.
Because shared objects are meant to be used by independent
applications, there needs to be a way of identifying them through
some global name. We use the type fsf_shared_object_id_t to
represent these identifiers. To avoid potential name or identity
conflicts between different independent applications we use a
null-character-terminated string.
For efficiency purposes, the contracts have smaller identifiers for
the shared objects, that can be implemented with a pointer or an
index to an array element. Therefore conversion functions are
necessary to convert a long identifier of type
fsf_shared_object_id_t into a short handle to the object, of the
type fsf_shared_obj_handle_t. This conversion is done at the
creation of the object (with fsf_init_shared_object), and there is
also a function to obtain the handle after the object has been
created (fsf_get_shared_object_handle).
To make the use of shared objects in FSF independent of the
underlying synchronization protocol, the function that initializes
a shared object (fsf_init_shared_object) also initializes the mutex
specified by the user with the appropriate, implementation-defined,
attributes. Therefore, the application should not initialize the
mutex itself, but should pass the mutex to this function call, and
then use it with the regular POSIX interfaces to enter and leave
critical sections. It is possible to obtain a pointer to the mutex
from the shared object with the function
fsf_get_shared_object_mutex.
*/
/**
\defgroup distjmodule Distributed module
FSF is designed to support applications with requirements for
distribution. The first step towards distribution is the ability to
support service contracts for the network or networks used to
interconnect the different processing nodes in the system. Similar
to the core FSF module, the contracts on the network allow the
application to specify its minimum utilization (bandwidth)
requirements, so that the implementation can make guarantees or
reservations for that minimum utilization. We use the same contract
that is used for processing nodes, and thus the core attributes for
distribution are the same as for the core FSF with the addition of
the network id attribute, that identifies the contract as a network
contract for the specified network. The default value for the
network id is null, which means that the contract applies to the
processing node where the contact is negotiated.
For the FSF implementation to keep track of consumed network
resources and to enforce the budget guarantees it is necessary that
the information is sent and received through specific FSF
services. To provide communication in this context we need to
create objects similar to the sockets used in most operating
systems to provide message communication services. We call these
objects communication endpoints, and we distinguish send and
receive endpoints.
A send endpoint contains information about the network to use, the
destination node, and the port that identifies a reception
endpoint. It is bound to a network server that specifies the
scheduling parameters of the messages sent through that endpoint,
keeps track of the resources consumed, and limits the bandwidth to
the amount reserved for it by the system. It provides message
buffering for storing messages that need to be sent.
A receive endpoint contains information about the network and port
number to use. It provides message buffering for storing the
received messages until they are retrieved by the application. A
receive endpoint may get messages sent from different send
endpoints, possibly located in different processing nodes.
This module provides communication and negotiation services to
support the negotiation of independent servers on networks, as well
as to offer the simple communications primitives that allow for
accounting and limiting the network bandwidth used.
The concrete protocol and communications hardware and software
interfaces to use and whether the communication strategy over the
real-time network is connection-oriented or not, are implementation
dependent. The creation of endpoints will set them as
appropriate.
A node may negotiate contracts to reserve bandwidth for the sending
of messages through the networks to which it is connected. It does
not have to reserve bandwidth for incoming messages, just for
outgoing messages. A node cannot reserve bandwidth in networks to
which it has no direct connection.
As mentioned above, specific send and receive communication
primitives are included to transfer messages while managing the
bandwidth budget consumption. The send operation is non-blocking:
it just copies the message into an internal buffer and returns
immediately. The FSF network scheduler of the sender processor
takes responsibility on accounting the bandwidth fraction used
through each send endpoint, using the bandwidth reservation made by
the network server that is bound to it.
Considering that bandwidth reservations should be done in the form
of number of bytes per time unit, that the speed of the network is
quite variable from one platform to another, and that the regular
FSF contract negotiation operations work with budgets expressed as
CPU time, a function is added to convert the size of messages to
the amount of time that is necessary to be used as the budget in
the FSF contract.
*/
/**
\defgroup distsparemodule Distributed spare capacity module
In the distributed FSF we have chosen to give a minimum support for
spare capacity distribution inside FSF, and leave the consensus
problem related to the negotiation of end-to-end transactions to
some higher-level manager that would make the negotiations for the
application.
There is a new attribute in the service contract called the granted
capacity flag which, when set, has the implication that the period
or budget of the server can only change if a renegotiation or a
change of quality and importance is requested for it; it may not
change automatically, for instance because of negotiations for
other servers. This provides a stable framework while performing
the distributed negotiation.
For a server with the granted capacity flag set, there is an
operation to return spare capacity that cannot be used due to
restrictions in other servers of a distributed transaction.
*/