The microkernel is the heart of the ChorusOS operating system and contains
the minimum elements required to make a functioning system. In addition to
the optional components you can configure into your ChorusOS operating system,
the microkernel contains the kern
, private data manager (pd
), persistent memory
manager (pmm
), and core executive components. The kern
, pmm
, and pd
provide a minimum set of interfaces that are used by the remainder of the
operating system:
The kern
must be included in your
system image. It implements the microkernel interface and contains the KERN
actor, the mk library and associated
header files.
The pd
implements the per-thread
data interface between the microkernel subsystems, such as the UNIX subsystem.
The pmm
implements the persistent
memory interface. The pmm
is included automatically
in the system image when the HOT-RESTART feature is activated
(see "Hot Restart and Persistent Memory").
The services provided by the core executive are explained below.
The essential services required to support real-time applications are provided by the core executive. The core executive can support multiple, multithreaded applications running in both user and supervisor memory space.
The core executive implements the basic ChorusOS execution model and provides the framework for all other configurable features. Every system image must include the core executive.
The core executive provides the following functionality:
Support for multiple, independent applications
Support for user and system (trusted) applications
The unit of application modularization (actor)
The unit of execution (thread)
Thread control operations
Local Access Point (LAP) management
Exception management services
A minimal interrupt management service
No synchronization, scheduling, time, communication or memory management policies are wired into the core executive. These policies and services are provided by additional features, that the user selects depending on the particular hardware and software requirements.
This section provides an introduction to actors in the ChorusOS operating system. For further information regarding topics such as loading actors, spawning actors, and their execution environment and communications, see the ChorusOS 5.0 Application Developer's Guide.
An actor is the unit of loading for an application. It serves also as the encapsulation unit to associate all system resources used by the application and the threads running within the actor. Threads, memory regions and communication end points are some examples of these resources. These are covered in detail in the ChorusOS 5.0 Application Developer's Guide. All system resources used by an actor are freed upon actor termination.
Some resources, known as anonymous resources, are not bound to a given actor. These must be freed explicitly when they are no longer required. Examples of anonymous resources are physical memory, reserved ranges of virtual memory, and interrupt vectors.
The ChorusOS operating system is dedicated to the development and execution of applications in a host-target environment where applications are developed, compiled, linked, and stored on a host system and then executed on a reference target board where the ChorusOS operating system is running. When configured correctly, the ChorusOS operating system offers convenient support for writing and running distributed applications.
Within the ChorusOS operating system environment, an application is a program or a set of programs, usually written in C or C++. In order to run, an application must be loaded on the ChorusOS runtime system. The normal unit of loading is called an actor and is loaded from a binary file located on the host machine. As with any program written in C or C++, an actor has a standard entry point:
int main() { /* A rather familiar starting point, isn't it? */ }
The code of this type of application will be executed by a main thread that is created automatically by the system at load time. The ChorusOS operating system provides means to create and run more than one thread dynamically in an actor. It also offers services that enable these actors, whether single-threaded or multi-threaded, to cooperate, synchronize, locally or remotely exchange data, or get control of hardware events, for example. These topics are covered step-by-step in the ChorusOS 5.0 Application Developer's Guide.
An actor can be of two types: either a supervisor actor or a user actor. These types define the nature of the actor address space. User actors have separate and protected address spaces so that they cannot overwrite each other's address spaces. Supervisor actors use a common but partitioned address space. Depending on the underlying hardware, a supervisor actor can execute privileged hardware instructions, such as initiating an I/O, while a user actor cannot. See "User and Supervisor Actors".
In flat memory, supervisor and user actors share the same address space and there is no address protection mechanism.
Binary files from which actors are loaded can also be of two types: either absolute or relocatable. An absolute binary is a binary where all addresses have been resolved and computed from a well-known and fixed basis that cannot be changed. A relocatable file is a binary that can be loaded or relocated at any address.
Both user and supervisor actors can be loaded either from absolute or relocatable binary files. However, common practice is to load them from relocatable files to avoid a static partitioning of the common supervisor address space, and to allow the loading of user actors into this space in the flat memory model. This is covered in detail in "User and Supervisor Actors".
Every actor, whether it is a boot actor or a dynamically-loaded actor, is uniquely identified by an actor capability. When several ChorusOS operating systems are cooperating together over a network in a distributed system, these capabilities are always unique through space and time. An actor may identify itself with a predefined capability, for example:
K_MYACTOR
.
In addition, an actor created from the POSIX personality is identified by a local process identifier.
host% rsh target hello Started pid = 13 host% |
Where target is the name of your target.
There are two main kinds of actor run within the ChorusOS operating system environment: user actors and supervisor actors.
A user actor runs in its own private address space so that if it attempts to reference a memory address that is not valid in its address space, it encounters a fault and, by default, is automatically deleted by the ChorusOS operating system.
Supervisor actors do not have their own fully-contained private address space. Instead, they share a common supervisor address space, which means that an ill-behaved supervisor actor can access, and potentially corrupt, memory belonging to another supervisor actor. The common supervisor address space is partitioned between the ChorusOS operating system components and all supervisor actors.
As supervisor actors reside in the same address space, there is no memory context switch to perform when execution switches from one supervisor actor to another. Thus, supervisor actors provide a trade-off between protection and performance. Moreover, they allow execution of privileged hardware instructions and so enable device drivers, for example, to be loaded and run as supervisor actors.
On most platforms, the address space is split into two ranges: one reserved for user actors and one for supervisor actors (see Figure 2-3). As user actor address spaces are independent and overlap each other, the address where these actors run is usually the same, even if the actors are loaded from relocatable binaries. On the other hand, available address ranges in supervisor address space may vary depending on how many and which supervisor actors are currently running. Since the ChorusOS operating system is able to find a slot dynamically within the supervisor address space to load an actor, the user does not need to be aware of the partitioning of the supervisor address space: using relocatable binary files is sufficient.
In addition to being either a user or supervisor actor, an actor can be trusted, which gives it the right to call certain privileged system services. Trusted actors are also referred to as system actors. A supervisor actor is by definition trusted.
The ChorusOS operating system offers a set of services for communicating between actors. Two actors can be made to communicate by sharing memory. Other communication mechanisms can be split into two categories:
Mechanisms that are local, that is, they do not allow actors running on different machines to communicate. The shared memory mechanism is one of these. You can use the system features in order to implement distributed shared memory. Message queues and local access points are other local communication mechanisms.
Mechanisms that can be used transparently in a distributed way. The IPC service enables actors to exchange messages transparently whether they are running on the same machine or not.
This section provides an overview of the use of threads in the ChorusOS operating system. For further information regarding threads, thread handling, thread synchronization, thread scheduling, per-thread data, and threads and libraries, see the ChorusOS 5.0 Application Developer's Guide.
Within an actor, whether user or supervisor, one or more threads may execute concurrently. A thread is the unit of execution in a ChorusOS operating system and represents a single flow of sequential execution of a program. A thread is characterized by a context corresponding to the state of the processor (registers, program counter, stack pointer or privilege level, for example). See Figure 2-4.
Threads can be created and deleted dynamically. A thread may be created in an actor other than the one to which the creator thread belongs, provided they are both running on the same machine. The actor in which the thread was created is called the home actor or the owning actor. The home actor of a thread is constant during the life of the thread.
The system assigns decreasing priorities to boot actor threads, so that boot actor main threads are started in the order in which they were loaded into the system image. If a boot actor's main thread sleeps or is blocked, the next boot actor threads will be scheduled for running.
Although there are no relationships maintained by the ChorusOS operating system between the creator thread and the created thread, the creator thread is commonly called the parent thread, and the created thread is commonly called the child thread.
A thread is named by a local identifier referred to as a thread identifier. The scope of this type of identifier is the home actor. In order to name a thread of another actor, you must provide the actor capability and the thread identifier. It is possible for a thread to refer to itself by using the predefined constant: K_MYSELF.
All threads belonging to the same home actor share all the resources of that actor. In particular, they may access its memory regions, such as the code and data regions, freely. In order to facilitate this access, the ChorusOS operating system provides synchronization tools, covered in "Synchronization" in this book.
Threads are scheduled by the microkernel as independent entities The scheduling policy used depends on the scheduling module configured within the system. In a first approach, assume that a thread may be either active or waiting. A waiting thread is blocked until the arrival of an event. An active thread may be running or ready to run.