TOC PREV NEXT INDEX DOC LIST MASTER INDEX



Ada Kernel Layer

The Ada Kernel Layer is a runtime nucleus with concurrency and synchronization services. It satisfies all the runtime requirements of Ada tasking and the Rational Exec extensions. For more information, refer to these topics:

The Ada Kernel Layer defines and provides operations for the following concurrency and synchronization objects. For more information, refer to these topics:

For each object there are type definitions and a collection of services. Most objects have a set of user-definable attributes that are used to initialize them. Type and attribute definitions for each object are in package Ada_Krn_Defs. Package Ada_Krn_I contains the interface to all the object services. Both packages are located in the rational.ss subsystem.


Mutex and Condition Variable Object Types Definition

The mutex and condition variable object types are used to implement mutual exclusion between tasks and task suspension. The definition of these objects is extracted from the POSIX 1003.1c standard, (IEEE Threads Extension for Portable Operating Systems). Refer to this standard for more details about POSIX.

Mutex

A mutex is a synchronization object used to allow multiple threads to serialize their access to shared data. The name derives from the capability it provides: mutual exclusion.

The thread that has locked a mutex becomes its owner and remains the owner until the same thread unlocks the mutex. Other threads that attempt to lock the mutex during this period suspend execution until the original thread unlocks it. The act of suspending the execution of a thread awaiting a mutex does not prevent other threads from making progress in their computations.

In the Ada tasking layer, an Abort_Safe option has been added to mutexes. A task that has locked an Abort_Safe mutex is inhibited from being completed by an Ada abort until it unlocks the mutex.

Condition Variable

A condition variable is a synchronization object that allows a thread to suspend execution until some condition is true. Typically, a thread holding a mutex determines that it cannot proceed by examining the shared data guarded by the mutex. The thread then waits on a condition variable associated with some state of the shared data. Waiting on the condition variable atomically releases the mutex. If another thread modifies the shared data to make the condition true, that thread signals threads waiting on the condition variable. This wakes up one or more waiting threads, which then contend for the mutex and check the condition on which they have been waiting. This is typically done using a loop structure:

Ideally, if multiple threads are waiting on CV, a call to cond_signal(CV) will wake up only one of them. This is the case with the current implementation of Rational Exec Microkernel, but it is not required by the POSIX standard, and may not be the case with other threads implementations over which the Apex Kernel Layer is implemented.

In the Ada tasking layer, an Abort_Safe option has been added to condition variables. A task locking an Abort_Safe mutex is inhibited from being completed by an Ada abort until it unlocks the mutex. However, if a task is aborted while waiting at a condition variable (after an implicit mutex unlock), it is allowed to complete.


Ada Kernel Layer Implementation

The Ada Kernel Layer can be layered on numerous target kernels. So far it has been ported to Rational Software Corporation's Rational Exec Microkernel, Windows NT Threads, and the POSIX threads implementations of Sun Solaris, Compaq OSF-1, SGI Irix, IBM AIX, HP-UX, and LynxOS. Each Ada Kernel Layer implementation maps the objects, attributes, and services defined in Ada_Krn_Defs and Ada_Krn_I onto the underlying microkernel objects and services. By layering Ada tasks on microkernels, Ada tasks can coexist with and call thread based services written in other languages, such as threaded windows written in C.

In addition, a SUN, Compaq, Alpha and SGI workstations can have multiple CPUs. Their microkernel services have been designed to allow concurrent thread execution from a single program across multiple CPUs. By layering Ada tasks upon threads, we also obtain the multi-CPU capability.

The same Ada_Krn_Defs and Ada_Krn_I interface is provided across all the Ada Kernel Layer implementations. However, each implementation has a different representation for the object and attribute type definitions. Target kernel specific capabilities are made available to the application program through the object attributes.

Object attributes can be used in the following places in an application program:

Ada_Krn_Defs provides a set of subprograms for initializing the object attributes. For example, the following subprograms are provided to initialize mutex attributes:

These subprograms are applicable to all implementations of the Ada Kernel Layer. If an implementation does not support a particular attribute capability, it raises the Program_Error exception. Since these subprograms insulate the application software from the underlying attribute type representation, they should be used instead of explicitly initializing each field of an attribute record.

Even though the Ada Kernel Layer exists primarily to satisfy the requirements of Ada tasking and the Rational Exec extensions, some of its services are of interest to the application programmer. Rational Exec has services for binary semaphores, counting semaphores, mutexes, condition variables, mailboxes, and names. These services are layered on the corresponding services in the Ada Kernel Layer. The application may elect to bypass the additional overhead incurred by the Rational Exec layer and call the Ada Kernel Layer services directly.


Warning: Since the program, master, and task services have complex semantics and implicit dependencies, avoid calling these services directly.

The following sections discuss each of the objects in the Ada Kernel Layer. For each object, the following topics are addressed:

The interface to the services provided in ada_krn_i.1.ada and ada_krn_defs.1.ada contain the rest. Both files are in the rational.ss subsystem.

Ada Program

There is a single Ada program object per executable entity. The Ada program object is automatically created and initialized during program startup.

Types

Attributes

None.

Services

Since the Ada program services should not be called directly, they are only listed here. Consult ada_krn_i.1.ada in rational.ss for more details.

Ada Task

An Ada task object exists for each thread of execution. Most operations on Ada task objects are done implicitly using the tasking semantics of the Ada language.

Types

Attributes

Additional Topics

For additional information, refer to these topics:

Services

There are two services for mapping between the Ada Task_Id and the Krn_Task_Id:

Since the remaining Ada task services should not be called directly, they are listed here. Consult ada_krn_i.1.ada in rational.ss for more details.

Ada Task Support Subprograms

The Task_Attr_T record can be initialized using one of the overloaded Task_Attr_Init subprograms. The task_attr parameter identifies the address of the storage allocated for the task attribute record.

Note: It may be desirable to specify priority ceiling for implicit task mutexes. In extremely rare cases, failure to do this might result in an unbounded priority inversion.

Examples

The following is an example of initializing the Task_Attr_T record.

Ada Task Master

A single task master lock exists to provide mutual exclusion for operations performed across multiple task objects (for example, aborting Ada tasks).

Types

None. There is one master lock and it is implied in the services.

Attributes

None.

Services

Since the Ada task master services should not be called directly, they are only listed here. Consult ada_krn_i.1.ada in rational.ss for more details

Kernel Scheduling

Services are provided to control the kernel scheduling policies.

Types

None. There is one kernel scheduling object and it is implied in the services.

Attributes

None

Services

The Ada Kernel Layer has the following scheduling services:

Callout

Services are provided that allow a subprogram to be called at a program, task, or idle event.

Types

Attributes

None

Services

The following service installs a callout for the specified program, task or idle event. It returns False if the service is not supported or it is unable to do the installation.

V_Xtasking.Install_Callout in Rational Exec is layered directly on the Callout_Install service. Consult the Rational Exec documentation for more details.

Task Storage

Some versions of the Ada Kernel Layer support user-defined storage on a per-task basis (currently supported only over the Rational Exec Microkernel).

Types

Attributes

None.

Services

The following task storage allocation services are currently supported only over Rational Exec Microkernel:

The Rational Exec V_X tasking services (Allocate_Task_Storage, Get_Task_Storage, and Get_Task_Storage2) are layered directly on the above Ada Kernel Layer services.

Interrupts

Services are provided to enable/disable interrupts, get interrupt enabled/disabled status, attach/detach interrupt service routine (ISR), get an attached ISR, and check if it is in an ISR. (On native, interrupts are UNIX signals.)

Types

Constants

Attributes

None.

Services

The Ada Kernel Layer has the following interrupt services:

The Rational Exec V_Interrupts services (Attach_Isr, Detach_Isr, Get.Isr, Get.Ivt, Current_Interrupt_Status, and Set_Interrupt_Status) are layered directly on the Ada Kernel Layer services.


Warning: No Rational Exec service is layered on the Isr_In_Check Ada Kernel Layer service.

Interrupt Support Subprograms

The Intr_Entry_T record can be initialized using one of the overloaded Intr_Entry_Init subprograms:

Examples

Intr_Entry_Init can be used as follows to define an interrupt entry:

To see more about V_Interrupts see the Ada Extended Runtime Services Reference.

Time

The Ada Kernel Layer provides time services for supporting Ada's delay statement: the predefined Calendar package. the predefined Ada.Real_Time package (from the Ada 95 Real-time Annex), and Rational Software Corporation's calendar extensions in the XCalendar package.

The Ada delay statement and the procedure Time_Delay produce a delta delay, whereas the Ada delay until statement and the procedure Time_Delay_Until produce an absolute delay.

If a task used the Ada delay statement or has called Time_Delay, calling Set_Time does not affect how long the task actually delays.

If a task calls Time_Delay_Until, calling Set_Time changes how long the task actually delays by the amount of the adjustment. For example, if a task has called Delay_Until (T + To_Time_Span (100.0)), calling Set_Time (T + To_Time_Span (50.0)) shortens the length of time that the task delays by 50 seconds. Additionally, if the current time is moved past the Delay_Until time for a task, that task is placed on the run queue immediately.

In the current release, all delays initiated by an asynchronous select statement are effected by Set_Time, whether relative or absolute. A future release will make asynchronous delays consistent with synchronous delays.

Types

Attributes

None.

Services

The Ada Kernel Layer has the following time services:

Alarm

An alarm is used to provide asynchronous notification that a specified time has arrived. It is used to implement Ada asynchronous delays.

Notification is provided by calling a procedure with an address argument, both of which are specified when the alarm is set. The profile of this procedure is

Types

Services

Since the Ada alarm services should not be called directly, they are only listed here. Consult ada_krn_i.1.ada in rational.ss for more details.

Mutex

Mutexes can be used explicitly by the user to serialize access to shared data.

The semantics of locking/unlocking a mutex adheres to the POSIX 1003.1c standard. Refer to the latest draft of that standard for more details about POSIX mutexes.

An Abort_Safe version of the mutex services is provided in the V_I_Mutex package found in rational.ss. A task locking an Abort_Safe mutex is inhibited from being completed by an Ada abort until it unlocks the mutex.

Types

Attributes

Services

The Ada Kernel Layer has the following mutex services:

The Ada Kernel Layer has the following services for mutexes that can be locked from an ISR:

Mutex Support Subprograms

The following subprograms are provided to initialize the Mutex_Attr_T record:

If the underlying Target kernel does not support the type of mutex being initialized, the Program_Error exception is raised.

Here are the overloaded subprograms for initializing the Mutex_Attr_T record:

Condition Variable

Condition variables are used to wait until a particular condition is True. A condition variable must be used in conjunction with a mutex.

The semantics of waiting on or signaling a condition variable and its interaction with a mutex adheres to the POSIX 1003.4a standard, IEEE Threads Extension for Portable Operating Systems. Refer to the latest draft of that standard for more details about POSIX condition variables.

An Abort_Safe version of the mutex and condition variable services is provided in package V_I_Mutex found in rational.ss. A task locking an Abort_Safe mutex is inhibited from being completed by an Ada abort until it unlocks the mutex. However, if a task is aborted while waiting at a condition variable (after an implicit mutex unlock), it is allowed to complete. The V_I_Mutex services also address the case where multiple Abort_Safe mutexes are locked. A task is inhibited from being completed until all the mutexes are unlocked or it does a condition variable wait with only one mutex locked.

Types

Attributes

Services

The Ada Kernel Layer has the following condition variable services:

The Ada Kernel Layer has the following service for a condition variable that can be called only from an ISR:

Condition Variable Support Subprograms

The following subprograms are provided to initialize the Cond_Attr_T record:

If the underlying Target kernel does not support the type of condition variable being initialized, the Program_Error exception is raised.

Here are the overloaded subprograms for initializing the Cond_Attr_T record:

Binary Semaphore

A binary semaphore is an object that can be in one of two states, full or empty. If a task waits on a full semaphore, then it makes the semaphore empty and continues executing. If a task waits on an empty semaphore, then it blocks until it is signalled. When a semaphore is signalled, the next available task is unblocked. If no task was blocked on the semaphore, the semaphore becomes full.

Binary semaphores are used by the Rational Exec V_Semaphores services. The overhead added by the Rational Exec layer can be eliminated by directly using the Ada Kernel Layer binary semaphores.

Types

Constants

Attributes

Services

The Ada Kernel Layer has the following binary semaphore services:

Counting Semaphore

A counting semaphore is an object with a non-negative count. If a task waits on a semaphore with a non-zero count, it decrements the count and continues executing. If a task waits on a semaphore with a zero count, then it blocks until it is signalled. When a semaphore is signalled, the next available task is unblocked. If no task was blocked on the semaphore, the semaphore's count is incremented.

Counting semaphores are used by the Rational Exec V_Semaphores services. The overhead added by the Rational Exec layer can be eliminated by directly using the Ada Kernel Layer's counting semaphores.

Types

Attributes

Services

The Ada Kernel Layer has the following counting semaphore services:

Counting Semaphore Support Subprograms

The counting semaphore attributes can be initialized to select the disable interrupts options by using one of the overloaded Count_Intr_Attr_Init subprograms.

Mailbox

A mailbox object is used to queue fixed length messages between tasks or between ISRs and tasks. Any task or ISR can write messages to a mailbox object. Any task can read messages from a mailbox. If no message is in the mailbox, the reader can optionally wait until a message is written, return immediately with no message or wait up to a specified amount of time for a message.

Mailboxes are used by the Rational Exec V_Mailboxes services. The overhead added by the Rational Exec layer can be eliminated by directly using the Ada Kernel Layer mailboxes.

Types

Attributes

Mailbox Support Subprograms

The mailbox attributes can be initialized to select the disable interrupts options by using one of the overloaded Mailbox_Intr_Attr_Init subprograms.

Name

Objects or procedures can be named to allow them to be shared across multiple programs.

Supports the Rational Exec V_Names services and the Bind/Resolve services in the Rational Exec V_Mailboxes, V_Mutexes and V_Semaphores packages.

Types

Services

The Ada Kernel Layer has the following name services:

Protected Records

An Ada protected object provides synchronization without a separate thread of control. All operations on protected objects are done using the tasking semantics of the Ada language.

Types

Attributes

Services

Since the Ada protected object services should not be called directly, they are only listed here. Consult ada_krn_i.1.ada in rational.ss for more details.


Rational Software Corporation 
http://www.rational.com
support@rational.com
techpubs@rational.com
Copyright © 1993-2002, Rational Software Corporation. All rights reserved.
TOC PREV NEXT INDEX DOC LIST MASTER INDEX TECHNOTES APEX TIPS