5. Predefined GNAT Pro Run-Times
The Standard GNAT Pro Ada run-time supports the full core Ada Language and numerous Appendixes as documented in the GNAT Reference Manual. While suitable for a large range of applications, there are certain applications and targets where the Standard GNAT Pro Ada run-time is not appropriate. This may be due to certification requirements, limitations of the underlying operating environment, or target specific restrictions. To address these needs, GNAT Pro provides additional predefined run-times suitable for applications and targets that can only utilize a subset of the Standard GNAT Pro Ada run-time.
Depending on the capabilities of the target, GNAT Pro offers up to one of four different predefined run-time families: Light, Light-Tasking, Embedded and Standard. If required, these run-times may be customized further to meet your needs. See The GNAT Configurable Run-Time Facility for more details.
This chapter presents the four predefined run-time families. For further details on the run-times supported on a particular target, please refer to the target’s Appendix for more details.
5.1. Standard Run-Time
The Standard run-time supports the core Ada Language and language Appendixes as documented in the GNAT Reference Manual. It is available for Operating System targets that can support the full capabilities of the language, for example: Linux, Windows, VxWorks and RTEMS.
Depending on the target, there may be different variants of the Standard run-time to support different underlying Operating System libraries or execution environments. For example, on VxWorks there are different Standard run-time libraries for the Kernel and RTP execution environments. Please refer to the target specific appendixes for more details on the run-time libraries offered for your target.
5.2. Embedded Run-Time
The Embedded Run-Time provides a subset of the Standard Run-Time suitable for applications running on bare-metal systems and Real-Time Operating Systems that lack file I/O and networking support. It provides most of the functionality of the Standard run-time with the following limitations:
Tasking is restricted to the Jorvik and Ravenscar Profiles.
The only supported I/O is provided in the form of a simplified Ada.Text_IO package (suitable for serial communication).
No networking support.
Ada or GNAT packages that depend on tasking outside of the Jorvik Profile or require file I/O and networking support are not included in the Embedded run-time.
5.3. Light Run-Time
The Light run-time supports a non-tasking subset Ada suitable for certification and space-constrained embedded applications. It is provided on bare-metal, certifiable RTOSes and native targets (allowing embedded code to be tested on native platforms). The run-time provides support for:
Integer and fixed-point:
32-bit targets: up to 64-bit types
64-bit targets: up to 128-bit types
Floating point:
Single (IEEE binary32) and double (IEEE binary64) float support
80-bit extended float support on x86
Support for floating-point attributes
Packed arrays with static bounds whose sizes are:
For 32-bit systems: 64 bits or less
For 64-bit systems: 128 bits or less
Assertions
Character runtime support:
Ada.Characters.Latin_1 and Ada.Characters.Handling
No runtime library support for Wide_Characters and Wide_Wide_Characters.
Ada.Numerics
(hyperbolic functions are excluded)
Ada.Strings
Exception support limited to:
Locally handled exceptions
Last Chance Handler
(exception propagation is not supported)
Library-level tagged types
Simplified versions of Interfaces.C and it’s children
System.Bit_Ops
System.Compare_Array
Exponential operations
Foreign thread support
Support for ‘Image and ‘Value attributes for Scalar types
Type conversion support for Real types
Simplified Text_IO with no file I/O support
Allocators (but not Unchecked_Deallocation)
Secondary stack
The following language restrictions are applied:
pragma Restrictions (No_Exception_Propagation);
pragma Restrictions (No_Exception_Registration);
pragma Restrictions (No_Implicit_Dynamic_Code);
pragma Restrictions (No_Finalization);
pragma Restrictions (No_Tasking);
While the Light Run-Time offers a wide range of functionality, applications will only include in it’s binary the run-time object files corresponding to features used by the application. This allows space-constrained embedded applications to subsets of the light run-time without having to use a customized run-time with unwanted packages removed.
5.3.1. Allocator Support
The Light run-time supports dynamic memory allocation on the heap via Ada’s
allocators. However, deallocation is not supported and is implemented as a
no-op, with the rationale being that with certifiable software dynamic memory
allocation is performed at most once, at startup, so freeing the memory is
unnecessary. A call do Unchecked_Deallocation
will still set the passed
pointer to null
but will not actually free the memory pointed to by that
pointer. This restriction allows a simple, efficient, and predictable
behavior for memory allocation, and is a strategy implemented on certifiable
operating systems.
For bare-metal run-times, the allocation mechanism relies on the
__heap_start
and __heap_end
symbols to delimit the memory area that can
be allocated. These symbols are defined by the linker script used for the
specific board being targeted. For operating-system-based run-times the heap
routines are provided by the underlying operating-system.
If required, the dynamic memory support can be replaced with application specific code (for example, to support memory deallocation). This is done by implementing the following functions in your application in Ada:
type Pointer is access Character;
-- This is really a void pointer type, the result from
-- Gnat_Malloc will always be maximally aligned.
function Gnat_Malloc (size : Interfaces.C.size_t)
return Pointer;
pragma Export (C, Gnat_Malloc, "__gnat_malloc");
procedure Gnat_Free (Ptr : Pointer);
pragma Export (C, Gnat_Free, "__gnat_free");
or in C:
void *__gnat_malloc (size_t size);
void __gnat_free (void *ptr);
5.3.2. Certification
The Light run-time is certifiable and certification evidence can be obtained by contacting AdaCore sales. If a limited number of run-time units are used by your application it is possible to certify these units as part of your application. You can produce a run-time that contains only these run-time units by customizing a Light-based run-time as documented in Customized Bareboard Run-Time Libraries
5.3.3. Excluding the Run-Time Library
In a certification context it may be required that no external library is linked with the final application image. This can be achieved by using the builder switch -nostdlib. GPRBuild will pass this switch to the binder and to the linker, resulting in the application not being linked with the run-time and compiler support libraries libgnat.a and libgcc.a.
By excluding the run-time library, an application may not
Reference entities from run-time packages, for example
Ada.External_Tag
;Use pragma
Assert
;Use the following floating-point attributes:
Adjacent
,Ceiling
,Compose
,Copy_Sign
,Exponent
,Floor
,Fraction
,Leading_Part
,Machine
,Machine_Rounding
,Model
,Pred
,Remainder
,Rounding
,Scaling
,Succ
,Truncation
,Unbiased_Rounding
(with nonstatic arguments), andValid
(with any argument);
Use the secondary stack (this can be enforced by including pragma
Restrictions(No_Secondary_Stack)
); andUse of floating-point or other arithmetic operations that are too complex for inline expansion and that therefore require calls to a support library.
5.3.4. Exceptions and the Last Chance Handler
The No_Exception_Propagation
restriction is applied to applications using
the Light run-time, disallowing the use of exception propagation within the
application. This is done on the Light run-time to simplify run-time
implementation and certification.
While exception propagation is disallowed, language and user-defined exceptions can still be raised and handled locally within subprograms. Unhandled exceptions will result in the Last Chance Handler being called. The Last Chance Handler provides the ability for the application to safely shutdown or reset as a result of an unhandled exception; it is not possible for the application to resume after the Last Chance Handler is called.
The Light run-time provides a default Last Chance Handler implementation that prints the exception name and the line number of the Ada source code that raised the exception. This handler can be replaced in your application by implementing an Ada procedure with the following procedure declaration:
procedure Last_Chance_Handler
(Source_Location : System.Address; Line : Integer);
pragma Export (C, Last_Chance_Handler,
"__gnat_last_chance_handler");
Alternatively, the handler may be implemented in C using the following C function:
void __gnat_last_chance_handler (char *source_location,
int line);
The Source_Location
parameter is a C null-terminated string representing
the source location of the raise
statement, as generated by the
compiler, or a zero-length string if pragma Suppress_Exception_Locations
is used.
The Line
parameter, when nonzero, represents the line number in the
source. When Line
is zero, the line number information is provided
in Source_Location
itself.
See Exceptions for details on providing an application-specific Last Chance Handler.
5.3.5. Foreign Threads
Foreign threads are OS threads created outside the GNAT Ada environment that access Ada code (for example, threads created in C program that call into an Ada library). On targets that provide thread support, the Light run-time support foreign threads.
Foreign threads need to be explicitly registered with the Light run-time using
the System.Threads.Thread_Body_Enter
procedure. As part of the procedure,
a secondary stack is associated to the foreign thread. The secondary stack
assigned to the foreign thread needs to be:
Created on the stack or heap (by creating a new
System.Secondary_Stack.SS_Stack
object) and passed explicitly to theThread_Body_Enter
procedure.Assigned from the default-sized secondary stack pool by passing a
null
secondary stack pointer toThread_Body_Enter
. You will need to increase the size of the pool by the number of foreign threads that will be registered using this approach. This is done by passing gnatbind the-Q
switch with the number of additional secondary stacks needed.
5.4. Light-Tasking Run-Time
The Light-Tasking run-time provides the functionality of the Light profile with additional support for Ravenscar and Jorvik tasking as defined by the Ravenscar and Jorvik profiles respectively. It is offered on all bare-metal and certifiable RTOSes targets.
By default, the Light-Tasking run-time will enforce the Jorvik Profile. The Ravenscar Profile can be specified by adding the following to your application’s configuration pragma file:
pragma Profile (Ravenscar);
Please refer to The Ravenscar Profile and The Jorvik Profile for details about the capabilities offered under each profile.
For the non-tasking aspect of the Light-Tasking run-time the information in Light Run-Time applies, with the exception that the Light-Tasking run-time applies the following restrictions:
pragma Restrictions (No_Exception_Propagation);
pragma Restrictions (No_Exception_Registration);
pragma Restrictions (No_Implicit_Dynamic_Code);
pragma Restrictions (No_Finalization);
pragma Profile (Jorvik);
Please note that the Light-Tasking run-time does not support Foreign Threads.
5.5. Specifying a Run-Time
By default, GNAT Pro tools will use the Standard GNAT Pro run-time if supported on the target. In all other cases you will need to specify the name of the run-time library to gnatbind and other GNAT tools that needs to be aware of the run-time configuration.
You choose a particular run-time through one of two approaches:
With the
Runtime
attribute in a project file (the recommended technique); orWith the
--RTS=
switch.
For predefined run-times shipped with GNAT Pro, the value provided to the
--RTS=
switch or Runtime
attribute is the name of the chosen run-time
library. Non-Standard run-times will include the run-time family in their name
(e.g.: light) and may include a board or target specific identifier.
Customized run-times can be referred to using the same approach if they are installed in the same location as the predefined run-times. Alternatively, you can use the the full or relative path to the folder containing the run-time library.
For example, to use the Light-Tasking run-time for the ST STM32F4, you would add to your project file the following (note the necessary inclusion of the language name as index):
project Demo is
...
for Runtime ("Ada") use "light-tasking-stm32f4";
...
end Demo;