TOC PREV NEXT INDEX DOC LIST MASTER INDEX



Memory Management

This chapter describes the Apex implementation that addresses Ada memory management requirements. Dynamic memory allocation/deallocation support available to application programs is discussed, including:

The Ada language has many explicit and implicit memory requirements. Explicit requirements include object declarations and the new allocator. Implicit requirements include queues and blocks for tasking control and intermediate storage for initializations. This chapter describes how Apex provides services to meet these requirements and shows how these services can be customized for your application.

Memory requirements are met from one of three areas: static data, heap, stacks. Use of static data is restricted to what can be allocated at compile time. Stacks are typically restricted to local usage because stack offsets must be known, and except for the main task's stack, the maximum size of a stack is fixed when the stack is created. The heap is the most flexible, the locations and sizes of objects allocated from the heap do not need to be known until runtime and the heap can be dynamically expanded. It can be used for any memory requirement, but excessive heap usage can degrade performance.


Managing Heap Storage

Historically, a program's dynamically allocated memory was managed with a data structure called a heap. Apex's memory management is multilayered and involves several different data structures, some of these are heaps in the traditional sense, others are not. In this section we describe Apex's memory management:

Memory Management Architecture

The ultimate supplier of the memory used to satisfy an Ada new allocation request is the operating system, however Ada language requirements and performance considerations lead us to the introduction of two additional layers: Collection Callouts and Storage Pools. Consider how Apex might support the new and Unchecked_Deallocation operations in this example:

One possible memory management implementation is to have the compiler emit calls directly to the operating system's heap routines: malloc for the new operation and free for Unchecked_Deallocation. But with such an implementation, the enforcement of the required Ada semantics would be more complex and it would be difficult to optimize allocation policies for different applications. Apex introduces collections and storage pools to address these issues. see Figure 4. Collections provide support for language features such as controlled object finalization and allocation limit enforcement. Storage pools provide a standard interface to the heap management facilities resident in the Apex runtime, operating system, and/or application.

Figure 4 Memory Management Architecture

Every access type is associated with a collection and each collection is associated with a storage pool. These associations are managed by the memory management system, however, as an optimization, the association between an access type and collection is sometimes implied rather than explicitly recorded.

The collections allocator is assigned its own distinct collection, while derived access types are associated with the collection of their base type. Apex provides an optimization for the case where an access type will never be utilized to dynamically allocate an object. Such access types are implicitly associated with a special null collection (and null storage pool). Consider this example:

where Zero is a static expression that evaluates to 0. Since there is no possibility that the access type can ever be used to dynamically allocate an object, Apex can reduce resource usage by suppressing the creation and assignment of a collection. An access type without a collection will raise Storage_Error if an allocation is attempted. This optimization is only possible if the Storage_Size argument (Zero in the example above) is a static expression.

If the Storage_Size argument is non-static, a collection is created for the access type even if the argument evaluates to zero at runtime. Whenever allocations are made from a collection the storage limit is checked. If the specified number of allocated storage elements would be exceeded, Storage_Error is raised.

In addition to enforcing Storage_Size constraints, collections provide support for the automatic reclamation of allocated, but unreachable, objects. When the base access type associated with a collection is no longer visible, any objects remaining in the collection are unreachable and can be deallocated. A typical scenario for this is when a (base) access type is declared within a subprogram; the collection is created when the subprogram is called and can be discarded when the subprogram returns. The automatic reclamation of all memory associated with the collection improves resource utilization while relieving the application of having to explicitly deallocate any objects that are still allocated at subprogram exit. (And, as discussed in Storage Pools, these automatic deallocations can be performed very efficiently).

Note that in instances where unchecked programming is being used there could still be references to allocated objects after the access type has gone out of scope. In such cases the base access type should be declared in a scope that won't be exited, for example, a library package, so that the automatic reclamation will not occur.

Storage Pools

Storage pools, as defined in Ada95 RM 13.11, provide a standard interface to memory management services. Every collection has an associated storage pool and since every access type is, at least implicitly, associated with a collection, each access type is assigned to a storage pool. Multiple collections can be associated with the same storage pool and it is possible that all of the allocations for every access type come from the same storage pool. It is also possible to configure memory management so that different access types use different storage pools. Apex allows you to configure the kind of storage pools that your application will use and to control the assignment of collections to storage pools.

The storage pool associated with an access type can be determined by querying the type's Storage_Pool attribute. For any subtype S, S'Storage_Pool denotes the storage pool to which S has been assigned. The size of the type's storage pool can also be determined with an attribute: S'Storage_Size denotes the size of S's storage pool (in storage elements).

Note: The size reported reflects the total storage available when no allocations have been made from the pool; it does not report the amount of currently unallocated memory available in a non-empty pool. Also, since multiple access types can be assigned to the same storage pool, the memory available is not necessarily dedicated to objects of a particular type.

The Root_Storage_Pool type, defined in System.Storage_Pools, defines operations for allocation, deallocation, and pool size determination. This type can be extended and many implementations are possible. Apex provides storage pool types that are interfaces to external heap management services (for example, malloc/free) as well as storage pools that implement their own, internal, heap management. The Apex supplied storage pool types (as well as the Root_Storage_Pool) can be extended to create custom storage pools that address application specific memory management requirements, see User Defined Storage Pools.

Two predefined storage pool configurations are provided with Apex, each of which defines a different set of standard storage pools. The default configuration, for all products except Apex Embedded for Rational Exec and Apex Embedded for Tornado, is called Externally Managed Heap. It utilizes only one storage pool object for all application allocations/deallocations, the External_Pool, whose default implementation provides an interface to the malloc/free heap services of the operating system. In this configuration all allocation/deallocation requests from the collection layer are serviced by malloc/free.

The Apex compiler generates calls to the Collection layer to implement new allocations and Unchecked_Deallocations. While these calls are present in the compiled application code, the remainder of the storage management implementation is usually built separately from the application. The Collection and External_Pool code is retrieved from Apex supplied runtime archives and linked with the application program. The operating system interface usually consists of additional OS supplied libraries that are linked with the application. The exception to this scenario occurs when the application provides its own External_Pool type.

Figure 5 Externally Managed Heap Architecture

The alternate configuration called Apex Managed Heap (see Figure 6), utilizes a hierarchy of storage pools layered over the External_Pool. This is the default configuration in Apex Embedded for Rational Exec and Apex Embedded for Tornado. In this configuration, a Default_Pool provides the heap support for application allocations/deallocations. The External_Pool is only accessed when more memory needs to be added to the Default_Pool's heap. In addition to the Default_Pool, other storage pools may be created to provide dedicated storage for some collections, see Memory Management Configuration.

Figure 6 Apex Managed Heap Architecture

Memory Management Configuration

Memory management can be configured at the access type, program, and system (multiple program) levels. The configuration is specified with:

and enable a developer to make such decisions as the amount of storage allotted for an access type, where that storage should come from, and how that storage should be managed. Configuration parameters that only apply to a specific access type are set with a storage clause (Storage_Size or Storage_Pool) or a Collection_Policy pragma, program-wide parameters are set with pragma Main, and parameters that might apply to multiple programs are set in the user configuration package V_Usr_Conf.

Storage Clauses

A non-derived access type may have either a Storage_Size or a Storage_Pool specified for it (but not both, see Ada95 RM 13.11). The Storage_Size clause specifies the number of storage elements to be allotted for the designated access type.

If Externally Managed Heap is configured, the specified storage limit is recorded as a collection attribute and that value is checked each time an allocation is requested (with Storage_Error raised if the limit would be exceeded).

If Apex Managed Heap is configured, the runtime will choose a standard storage pool type for the collection and create a pool object, dedicating (reserving) the specified amount of memory exclusively for this storage pool.

If an allocation request cannot be satisfied by the pool, Storage_Error is raised (the amount of memory dedicated to the pool cannot be extended).

A Storage_Pool clause enables a user to designate that a specific storage pool object be used for an access type. The designated storage pool could be an instance of one of the Rational supplied pool types (see User Defined Storage Pools), an instance of an extension of the Root_Storage_Pool (or one of its Rational extensions), or one of the runtime's standard storage pool objects. For example:

would insure that Access_T and Access_T2 shared the same storage pool (in this case a standard storage pool chosen by the runtime for Access_T).

Pragmas

Pragma Collection_Policy controls memory allocation for the collection designated by an access type. The memory management semantics associated with the pragma are a superset of those associated with the Storage_Size clause. The difference between the clause and the pragma is that the use of the clause will result in a fixed size collection while the pragma allows for extensible collections. The use of Collection_Policy pragmas and Storage_Size and Storage_Pool clauses are mutually exclusive.

See pragma Collection_Policy in the Ada Compiler Reference for a more detailed description.

Pragma Main has the following memory management related arguments:

See pragma Main in the Ada Compiler Reference for a more detailed description of this pragma.

The default V_Usr_Conf package that you are using is either:

For native development
For cross development

Note: The meta names used in this path are set when Apex is invoked.The environment variable values can be displayed using Tools > Session > Environment.

Configuration Packages

The package V_Usr_Conf, located in the usr_conf.ss subsystem, contains a number of configuration items related to memory management. The specification of the package provides instructions for customizing memory management and other runtime services. Configuration parameters are set in the package body, the package specification should not be modified.

The Apex Embedded for Rational Exec and Apex for Tornado products provide additional storage management configuration capabilities in their kernel configuration packages, V_Krn_Conf, located in their krn_conf.ss subsystems. Note that these products have separate V_Usr_Conf and V_Krn_Conf packages for each supported target board.

Note: Some of the parameters in the configuration package can be overridden by pragma Main arguments, as well as by storage clauses and Collection_Policy pragmas.

There are four groups of memory management related configuration items in the V_Usr_Conf package body:

Configuration_Table

The Configuration_Table contains many user configurable parameters for controlling the behavior of the Apex runtime. The following parameters are related to memory management:

Mem_Alloc_Conf_Table and Small_Block_Sizes_Table

The Mem_Alloc_Conf_Table contains several parameters that are relevant to both the Externally Managed Heap and the Apex Managed Heap configurations, as well as additional parameters that are only meaningful in the Apex Managed Heap configuration.

Mem_Alloc_Conf_Table Parameters Applicable To All Configurations
Mem_Alloc_Conf_Table Parameters Applicable Only To Apex Managed Heap

The following parameters apply only in the Apex Managed Heap configuration and are only relevant to the configuration of the Default_Pool:

Storage Pool Configuration

Rational's standard storage pool types are:

The Apex runtime creates single instances of the External_Pool, Null_Pool, and Kernel_Pool types. These pool objects are created during the initialization of the runtime. If Apex Managed Heap is configured, a single instance of the Default_Pool is also created during initialization and during the execution of a program multiple instances of Heterogeneous_Pool and Homogeneous_Pool objects could be created and destroyed. The Default_Pool, Heterogeneous_Pool, and Homogeneous_Pool types are not used if Externally Managed Heap is configured.

Figure 8 shows how the Externally Managed Heap Architecture can be configured for your application. Within the V_Usr_Conf package you can change the External_Pool type or you can modify the behavior or the default External_Pool by changing the bodies of the pool's callout routines.

Figure 7 Externally Managed Heap Configuration

The External_Pool and Kernel_Pool objects provide the lowest level memory management interface for the application and the kernel respectively. Usually, these objects are nothing more than interfaces to an external heap management implementation, for example, malloc/free supplied by the operating system.

The exception is Apex Embedded for Rational Exec, where the default configuration is to have the External_Pool be the application's interface to the kernel's storage management services which are provided by the Kernel_Pool.

The Default_Pool object is the default heap manager for the application if Apex Managed Heap is configured. All collections are assigned to this pool except for ones that have a non-default initial size (specified with a Storage_Size clause or Collection_Policy pragma) or have a storage pool explicitly assigned via a Storage_Pool clause. Some reclaimable collections may also be excluded from the Default_Pool if Private_Storage_Pools are enabled. The Default_Pool is layered over the External_Pool. The External_Pool is called when the Default_Pool needs more memory.

The Null_Pool object does not support allocations, that is, any attempt to allocate memory from the pool results in the raising of a Storage_Error exception. A collection with a Storage_Size clause or a Collection_Policy pragma that specifies zero storage elements is assigned to this pool. If the size expression is statically evaluated to zero, the access type is not explicitly assigned a collection or storage pool, however the Storage_Pool attribute would still identify the Null_Pool for the access type.

Heterogeneous_Pool and Homogeneous_Pool objects are created for collections that have a non-default initial size (when Apex Managed Heap is configured). If a Storage_Size clause or Collection_Policy pragma has been specified, the collection is assigned a dedicated storage pool object of the specified initial size (if a Storage_Size clause was given the pool is not extensible). If Private_Storage_Pools are enabled, these pool objects will also be created for reclaimable collections, using the default collection parameters for initial and extension sizes (see Pragmas).

The storage pool objects described above are sufficient for most applications. Usually, the memory management configuration parameters described in this chapter provide all of the flexibility that an application might require. However, if an application's memory management requirements are not met by the pool types supplied with Apex, the application can replace them with its own storage pool types. The standard storage pool objects are replaced by supplying a subprogram to create an alternative object. The list of storage pool object creation routines is specified in the Storage_Pool_Configuration field of the Mem_Alloc_Conf_Table.

Each standard storage pool type has a creation routine specified by a entry in the Storage_Pool_Configuration. Set a table entry to the value Use_Standard_Pool_Routine to utilize the runtime's default, or disable the use of a pool by setting its entry to the value Use_No_Pool_Routine, or alternatively, provide your own storage pool creation routine. See the parameter profiles below.

User defined standard storage pool creation routines must return an object of the following (Ada95) type:

and must have the following parameter profiles:

A simple alternative to completely replacing the Apex provided External_Pool and Kernel_Pool types is to modify their callout routines provided in the configuration packages, see Storage_Management_Callout Routines.

External Pool Callouts

Storage_Management_Callout Routines

External Pool Callouts provide a mechanism for easily customizing the External_Pool's external interface. This interface constitutes the lowest level of the Apex memory management system. It is where the runtime calls the operating system, or in the case of Apex Embedded for Rational Exec, the kernel, to allocate or deallocate memory. These callout subprograms are found in the body of the V_Usr_Conf package in the usr_conf.ss subsystem. An application is free to change the bodies of these subprograms. The following callouts are provided:

V_Extern_Alloc_Callout is called by the (default configured) External_Pool when it needs to allocate memory. The default implementation of this callout calls malloc, except with Apex Embedded for Rational Exec products, where the Rational Exec kernel is called.

V_Extern_Free_Callout is called by the (default configured) External_Pool when it wants to deallocate memory. The default implementation of this callout calls free, except with Apex Embedded for Rational Exec products, where the Rational Exec kernel is called.

V_Extern_Size_Callout is called by the (default configured) External_Pool to determine the maximum amount of memory that could be allocated. The default implementation of this callout returns the value reported by rlimit during runtime initialization. The Apex Embedded for Rational Exec product returns Alloc_T'Last from this callout.

Multitask_Safe Malloc

Multitask_Safe_Malloc is an Apex provided implementation of malloc, free, and several other standard C heap management routines. This implementation is suitable for use in mixed language applications, for example, Ada with C/C++, that are multitasking but non-threaded (threaded applications already have the necessary mutual exclusion support in the operating system provided heap management). The package Multitask_Safe_Malloc is provided in the alloc subdirectory of non-threaded usr_conf.ss views. The use of this package requires that some configuration changes be made to the body of the configuration package V_Usr_Conf. The required changes are marked with the string MULTITASK_SAFE_MALLOC in the package body and principally affect the External Pool Callouts. See the Multitask_Safe_Malloc and V_Usr_Conf packages for additional configuration information, implementation details, and restrictions.

Kernel Pool Callouts

Kernel Pool Callouts provide a mechanism for customizing the Kernel_Pool's internal interface. These subprograms are called by the kernel when it needs to allocate/deallocate memory. Memory management in the kernel is supported by these callouts, where the default implementation of each callout is to make a call to the corresponding Kernel_Pool object routine.

For all products except Apex Embedded for Rational Exec and Apex for Tornado, these callout subprograms are found in the body of the V_Usr_Conf package, in the usr_conf.ss subsystem. In Apex for Tornado, the callout subprograms are located in the body of the package V_Krn_Conf in the krn_conf.ss subsystem.

Note: There are instances of this package for each target board.

The Kernel_Pool callouts (except in Apex Embedded for Rational Exec) have the following profiles:

V_Krn_Alloc_Callout is called by the kernel when it needs to allocate memory. The default implementation of this callout calls the allocate entry of the Kernel_Pool object.

V_Krn_Free_Callout is called by the kernel when it wants to deallocate memory. The default implementation of this callout calls the deallocate entry of the Kernel_Pool object.

V_Krn_Pool_Init_Callout is called by the kernel to initialize its underlying memory management support. The default implementation of this callout calls a routine that creates the Kernel_Pool object.

V_Krn_Pool_Finalize_Callout is called by the kernel to finalize its underlying memory management support. The default implementation of this callout calls the Kernel_Pool object's Finalize routine.

Figure 8 Apex Managed Heap Configuration

The Kernel_Pool callouts in Apex Embedded for Rational Exec are found in the V_Alloc_Support package within the V_Krn_Conf package in the krn_conf.ss subsystem views (each target board has its own instance of this package). Figure 8 shows how the Apex Embedded for Rational Exec version of the Apex Managed Heap Architecture can be configured for your application. You can modify the behavior of the default Kernel_Pool by changing the body of the V_Krn_Conf.V_Alloc_Support package. You can also configure the V_Usr_Conf package. This enables you to change the types of the Default_Pool, External_Pool, and Kernel_Pool and to modify the behavior of the default External_Pool by changing the bodies of its callout routines.

The Kernel_Pool callouts have the following profiles:

Init initializes memory to be used for kernel allocations. Init is called with the bottom and size of the kernel's heap after the kernel has already allocated the kernel, interrupt and main task stacks from the top of the heap area. The Unaligned_Min_Size parameter has been set to the size of the kernel's task control block. Its only a hint at what the minimum size of an allocation should be. It can be ignored.

Alloc_New is called whenever the kernel needs memory for a kernel data structure, such as a task control block, a task stack, or a request for memory from the user program. The Prg parameter indicates which program the request is being made for. Prg is set to V_Krn_Aug.Program_Kernel to indicate memory being requested for a kernel data structure or a stack for a kernel task.

Alloc_Free is called whenever the kernel frees memory previously allocated.

User Defined Storage Pools

Ada 95 applications are not limited to the memory management configured in the Apex runtime. An application can supply its own memory management implementation via storage pools, see Storage Clauses. This mechanism enables an application to individually tailor the memory management policies for each (base) access type.

As an aid to application developers, Apex provides the type definitions for its standard storage pool types in the package System.Storage_Pools.Rational.Storage_Pools in the Ada95 lrm.ss views. These types are extensions of the Root_Storage_Pool type defined in System.Storage_Pools (see Ada95 RM 13.11 and Figure 9). A developer is free to use these extensions, extend these extensions, and/or define their own extensions of the Root_Storage_Pool type.

Figure 9 Storage Pool Types

The runtime's standard storage pool objects are instances of these types: the External_Pool and Kernel_Pool objects are External_Pool types, the Default_Pool is a Heterogeneous_Cached pool object, fixed sized pools are instances of the Homogeneous_Bounded or Heterogeneous_Bounded types, and non-fixed size, reclaimable pools are of the Heterogeneous_Unbounded type.

There are several situations where the application's explicit use of a standard storage pool type offers the best solution to a memory management problem. Two of these are: Stack Based Storage Pools and Storage Pools for Signal and Interrupt Handlers. In cases like these the use of a specific storage pool object, chosen by the application rather than the compiler/runtime, has significant advantages.

Stack Based Storage Pools

When a Storage_Size clause is given for an access type, that access type's collection is given a dedicated storage pool if Apex Managed Heap is configured (or shares the External_Pool if Externally Managed Heap is configured). However,even if the collection is given a dedicated storage pool, the memory managed by the pool (and thus the memory for new allocations) must be allocated from another pool, for example, the Default_Pool.

An alternative that is applicable to reclaimable pools is to allocate the memory for the pool from the stack. For example, if the storage pool is declared in a subprogram, the pool can be created on the subprogram's stack frame when the subprogram is called, and the storage will be automatically reclaimed when the subprogram returns. The advantages of this approach are that no other storage pools need to be used to support the stack based pool and that mutual exclusion support can be excluded from the stack based pool if its not visible to multiple tasks. This can result in significant performance improvements. Of course the downside to this approach is that the application must be able to insure that the stack will have sufficient space for the worst case pool size that could be configured (see Managing Stack Storage). Below is a simple example of a stack based storage pool:

Storage Pools for Signal and Interrupt Handlers

The storage pool is declared in a library-level package so that it will be visible to the handler. We use a Bounded Pool because any attempt to extend an Unbounded Pool from within the handler would invoke an illegal mutex lock in the underlying pool..

Note: The pool object in the example is declared in a library package and that its a fixed size pool. By locating the object in a library package we insure that the handler will have the appropriate visibility. The pool is non-extensible so that we will not encounter problems caused by insufficient mutual exclusion support if an attempt was made to extend the pool from a handler (since the underlying pool that would supply the memory for the extension is probably not signal/interrupt handler safe).

Memory Management Instrumentation

The optimal management of a resource such as memory requires careful planning, and one of the key elements of this process is the gathering of statistics about what is getting allocated/deallocated when and by whom. Much of the same data that's used for these statistics is also useful for investigating memory related errors. Rational provides several tools to assist with these analysis and debug efforts:

Apex Trace (Apex embedded only)

The Apex Tasking Logic Analyzer can provide a wealth of information about various aspects of your application's behavior, including memory usage. Allocations can be tracked at both the collection and External_Pool (malloc/free) levels. The tool can be used stand-alone or from with the Apex debugger. It is also possible to instrument application defined storage pool types so that their usage can be analyzed.

See the Using the Tasking Logic Analyzer for more information. Note that this manual is only available if you have an Apex embedded product installed.

Configuration Package Callouts

The callout routines provided in the V_Usr_Conf and V_Krn_Conf configuration packages (see Storage_Management_Callout Routines) can be easily modified to provide instrumentation and/or debugging support for the External_Pool and Kernel_Pool objects. These callouts expose the interface of the kernel to the Apex memory management system and the interface of the Apex memory management system to the external (to Apex) memory management (for example, malloc/free).

Collection Callouts

Instrumentation support for collections is provided via the package V_I_Collection_Callout which is found in the alloc subdirectory of usr_conf.ss views. Every access type in an Ada program has a collection associated with it. Instances of new allocations and unchecked_deallocations are implemented via compiler generated calls to this collection layer.

The subprograms in this package provide a mechanism for registering callout procedures. A user supplied procedure is registered by supplying its address. When an event occurs for which there is a registered callout, the user procedure is called. To unregister a callout, the registry procedure is called with a System.Null_Address parameter. Multiple callouts for the same event are not supported; the last registered procedure is the one that will be called.

Note: The use of the collection callouts requires that a usr_conf.ss view be imported. The importing of this view will have the side effect of inclusion, at link time, of the V_Usr_Conf package from the imported view rather than the default V_Usr_Conf in the runtime archive library.

User supplied callout procedures should not raise exceptions or perform any operations that might re-enter the storage management system, for example, a new allocation, and should not perform any operation that might block the currently executing task. This callout interface is intended to provide data collection services that support the analysis of memory usage in the application. With respect to the storage management system, these callouts provide a read-only interface.

The Collection_Id type used in the following declarations is an address-sized parameter.

A procedure with this profile will be called when a collection is created:

To register such a procedure use:

A procedure with this profile will be called when a collection is destroyed:

To register such a procedure use:

A procedure with this profile will be called when an allocation occurs:

To register such a procedure use:

A procedure with this profile will be called when an deallocation occurs:

To register such a procedure use:

A procedure with this profile will be called when a collection for a controlled type is finalized:

To register such a procedure use:


Managing Stack Storage

For applications that do not use tasking, stack usage is very straightforward. The stack is simply the process stack. For applications that use tasking, stack management is more complicated. The main task still uses the process stack, however each additional task gets a stack allocated from the heap. The runtime system keeps track of the current stack pointers and stack limits for each task and unless suppressed, the compiler generates checks to trap stack overflows. While overflows provide an indication of how much stack space a task is using, it usually a cumbersome way to determine the application's stack requirements. To assist in this effort the Apex debugger provides stack usage analysis. See "Display Stack Usage and Location" in Using the Apex Debugger for more information.

Once the appropriate amount of stack storage has been determined, its configuration can be specified in several different ways:

In addition to the task stacks used for normal processing there are other stacks used by the runtime system . Like the task stacks, these are configurable with pragmas, configuration parameters, and/or switches.

Figure 10 Task Stack

Storage_Size Clause and Pragma Storage_Size

A Storage_Size clause or a Storage_Size pragma can be used to specify a task's stack size (see Ada95 RM 13.3). The use of the clause or pragma will override the defaults given in a Pragma Main specification (as well as any configuration package or session switch defaults). The amount of stack space allocated to a task, T, can be determined by evaluating its T'Storage_Size attribute.

Pragma Main

In addition to allowing the specification of a default for task stack sizes (the Task_Stack_Size_Default argument), Pragma Main provides for the configuration of several other stack storage parameters via these arguments:

See pragma Main in the Ada Compiler Reference for more information.

Configuration Package Parameters

The configuration package V_Usr_Conf, which is found in usr_conf.ss views, provides the same configuration parameters described above for Pragma Main. Setting the parameters in the body of V_Usr_Conf enables them to be applied to any application program which imports the configured usr_conf.ss view. Task or program specific configurations given by a pragma Main, or Storage_Size pragma or clause, or a session switch will override the defaults given in V_Usr_Conf.

For additional information about stack configuration with Apex Embedded for Rational Exec, see the Configuration Guide for Rational Exec.

The default V_Usr_Conf package that you are using is:

For native development
For cross development

Note: The meta names used in this path are set when Apex is invoked.The environment variable values can be displayed using Tools > Session > Environment.

Session Switches

The main task's stack size and the size of signal stacks can be specified via the Apex session switches:

These switches will override the defaults specified in the V_Usr_Conf package but will not override those specified with pragma Main arguments.


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