HARTIK is a hard real-time kernel designed to help the development of real-time applications, ranging from critical control systems to soft multimedia, distributed systems.
It was developed at the RETIS Lab as a research project to explore the applicability of real-time theory to real world applications.
For more specific details about the HARTIK kernel, read below or take a look to the following topics:
Hard real-time systems are used to control physical processes in which tasks must execute under precise timing constraints (deadlines). This means that in order to guarantee the correct behavior of the controlled system, all time critical tasks must complete within their deadlines. Conventional real-time kernels are not suitable for time critical applications, since they do not manage time directly, and cannot guarantee the meet of timing constraints. This is because they are based on time sharing schedulers, which minimize the average response time of the activities, but do not guarantee the maximum response time in all anticipated operating conditions.
The main goals of HARTIK are determinism and programming flexibility. Based on a number of timing constraints specified by the user when a process is created, the kernel is able to analyze task schedulability and verify its feasibility in all anticipated operating conditions. Programming flexibility is obtained by implementing the whole kernel as a set of 'C' library functions, which extend the language introducing concurrency and hard real-time characteristics.
HARTIK code is written in C language, except for a small hardware-dependent portion of assembly code. A Virtual Machine (VM) layer provides the services of an abstract machine (context switching, interrupt handling, exception handling, and memory management) while hiding the hardware details of the architecture. To achieve portability, the VM layer is organized to separate task management (which is demanded to the scheduling policy) from context switching (which is strictly hardware dependent).
HARTIK handles different types of tasks, such as periodic and
aperiodic processes with critical deadline, periodic and aperiodic
processes with non critical time constraints, as well as non
real-time tasks, for which a static priority can be defined.
In particular, the following types of tasks can be created by
|Hard Deadline||Soft Deadline||No Deadline|
In HARTIK, all real-time processes are scheduled based on the Earliest Deadline First (EDF) scheduling policy, according to which, at any instant, the CPU is assigned to the task whose absolute deadline is the earliest. The scheduling mechanism is based on explicit deadline declaration and has been specifically designed to maximize processor utilization. The CPU executes tasks with hard deadline in EDF order. If no hard task is active, the CPU is assigned to those tasks having non critical deadline. Non Real-Time (NRT) tasks are executed in background, when no real-time tasks are active.
A guarantee algorithm provides predictable timing behavior, by dynamically checking the scheduling feasibility at every task creation. The feasibility test is based on an estimation of the tasks worst-case computation times.
HARTIK allows hard tasks to use shared resources in a predictable fashion through the Stack Resource Policy (SRP), a concurrency control protocol which bounds blocking time on critical sections, preventing deadlock and chained blocking. Under the SRP, each task can be blocked for at most the duration of one critical section, and blocking occurs at the time the task attempts to preempt, rather than at the time it makes a resource request. This early blocking saves unnecessary context switches and simplifies the implementation of the protocol (in fact, semaphores queues are no longer needed).
HARTIK also provides standard semaphores for classical mutual exclusion, but they should not be used by real-time tasks, since they are prone to unbounded priority inversion.
A STREAM port is a port for one-to-one communication. Sending messages to a STREAM port is non blocking, unless the port buffer is full. In this case, the send procedure blocks with a timeout. The timeout argument can be used as an upper bound for estimating the time required in the communication.
A MAILBOX port provides a many-to-one communication channel, particularly suited for client-server programming paradigms.
A STICK port is a shared buffer used with overwrite semantics and readmany capability. When a process receives a message from a STICK port, the port does not consume the message but leaves it stuck until it is overwritten by another incoming message. For this reason, communication through STICK ports is always asynchronous. Hence, this port is strongly recommended for exchanging state information among HARD periodic tasks.
Asynchronous communication is supported by the Cyclic Asynchronous Buffer (CAB) mechanism, purposely designed for the cooperation among periodic activities with different activation rate, such as sensory acquisition and control loops.
A CAB provides a one-to-many communication channel which contains, at any instant, the latest message or data inserted in its structure. A message is not consumed by a receiving task but it is maintained into the CAB until a new message is overwritten. In this way, a receiving task will always find data in a CAB, so that unpredictable delays due to synchronization can be eliminated. It is important to point out that CABs do not use semaphores to protect their internal data structures (as done in the ports), so they are not subject to priority inversion.
CAB messages are always accessed through a pointer, so that the overhead of CAB primitives is small and independent of the message size. The kernel also allows tasks to perform simultaneous read and write operations to a CAB, through the use of multiple memory buffers. For example, if a task wants to write a new message in a CAB that is being used by another task (which is reading the current message), a new buffer is assigned to the writer, so that no memory conflict occurs. As the writing operation is completed, the written message becomes the most recent information in that CAB and it will be available to any other task. The minimum number of buffers needed for a CAB to avoid conflicts must be equal to the number of tasks which share the CAB plus one.
In HARTIK, the interrupt mechanism is integrated in the general scheduling mechanism of the kernel. Each interrupt handler consists of two parts: a safe handler and a fast handler.
When the interrupt is triggered by an I/O device, the fast handler is executed in the context of the currently running task to avoid the overhead due to a context switch. It typically performs some basic input/output operations and acknowledges the peripheral. Then, the kernel automatically activates the safe handler, which is subject to the scheduling algorithm as any other aperiodic task in the system.
A safe handler can be declared as a soft or sporadic task depending on the characteristics of the device. The safe handler is in charge of doing any remaining computation on the device, for example data multiplexing among user tasks. This approach is quite flexible, since it allows to nicely combine two different service techniques: the event-driven approach (obtained by the fast handler) and the time-driven approach (obtained by the safe handler).
At present, the kernel supports 16-bit and 32-bit Intel 80x86 processors and the DEC Alpha AXP-PCI-33. An early version of the kernel has also been tested on a Motorola 68030 system with VME bus.
Due to its modular design, HARTIK can easily be ported to other hardware architectures, such as microcontrollers and embedded systems.