Using xdc.runtime Startup

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  [offline version]offline version generated on 23-Oct-2014 06:10 UTC 

Using xdc.runtime Startup

How applications boot, run, and shutdown

Contents

Introduction

The xdc.runtime package contains two modules that together provide the minimal set of services necessary to enable modular application startup and shutdown.

  1. Startup - a module that provides a framework for the orderly initialization of modules prior to main(), and
  2. System - a module that provides exit handling similar to that provided by the ANSI C Standard Library atexit() function.

Architecture

The Startup module manages the boot sequence from application start to the application's main() entry point and provides numerous configuration parameters to enable the developer to augment the startup process with custom C code. The System module, on the other hand, provides mechanisms for modules (initialized under the control of Startup) to shutdown.

Boot Sequence and Control Points

This section describes the sequence of events that occurs immediately after a device is reset until execution reaches the application's main() function. It also identifies the specific points during this boot sequence at which user provided functions ("boot hooks") are called.

Architecture

All targets follow the same set of boot sequence steps. In outline, the target independent boot sequence steps are:

  1. Immediately after CPU reset, perform target-specific CPU initialization to, at a minimum, setup a C call stack.
  2. Run user-supplied reset function (see Startup.resetFxn).
  3. Perform additional target-specific initialization to a complete C execution environment for subsequent steps.
  4. Run user-supplied "first functions" (See Startup.firstFxns).
  5. Run all module initialization functions.
  6. Run user-supplied last functions (See Startup.lastFxns).
  7. Call main().

The reset function (in step 2 above) is run as early as possible in the boot sequence. In fact, for some targets it is called before the C environment is fully initialized; static variables may not be fully initialized, for example. To maximize portablilty, reset functions should only assume that a C stack is initialized.

Although the functions in steps 4-6 are C functions, they are run during normal C++ static object initialization. This has two consequences:

  1. Since the ANSI C++ Language Standard does not provide a means to control the order of execution of static constructors, the initialization of application modules may not run before a C++ constructor runs. If you need to use a module (for memory allocation, for example) before step 6 completes and all modules are initialized, your code must explicitly call Startup_exec() before using any other module in the system. It is safe to call Startup_exec() more than once. So, you may call it from each C++ constructor that needs a module's services.
  2. If you are using a target that does not support C++, you must explicitly call Startup_exec() prior to using any module's services. You can simply call Startup_exec() as the first step in main(), for example.

Specific information about each environment's startup sequence is provided by the topics indexed in the table below.


Target Family Detailed Boot Sequence Information
TI TI Compiler Runtime Startup Sequence
Gnu Unix GNU Native Compiler Runtime Startup Sequence
Microsoft Microsoft Compiler Runtime Startup Sequence

Module Initialization

The material in this section is primarily for module producers. However, if you have troubles getting your application to successfully run to main() from reset, it may be useful to understand how module's are initialized.

Every module can optionally define a startup function which is called before main(). Modules declare that they want to participate in this startup sequence via the @ModuleStartup attribute in the module's spec file. Modules that use this attribute must also implement the following startup function:

 
Int Mod_Module_startup(Int state);

where "Mod" is the name of the module requesting startup support.

The parameter to the startup function serves as "state variable" whose initial value will be Startup_NOTDONE (0) and whose final value will eventually be Startup_DONE (-1). If startup() returns a value other than Startup_DONE, it will be called in a subsequent pass with this return value passed in as state. To ensure this process terminates, no startup function is ever called more than Startup.maxPasses times.

For situations in which the startup of one module depends upon another having completed its startup processing, the following function is automatically defined for all modules and proxies:

 
Bool Mod_Module_startupDone();

where "Mod" is the name of some module or proxy. These predicates can be used as guards inside of a startup function to probe whether a particular module has completed its own startup processing. As a convenience, the function Startup_rtsDone() probes the necessary set of xdc.runtime modules required to support a module instance create, and should be called before any startup-time instance creation and/or memory allocation is performed.

 
 
 
 
 
 
 
 
Int Mod_Module_startup(Int state)
{
    if (!Startup_rtsDone()) {
        return (Startup_NOTDONE);
    }
        :
    return (Startup_DONE);
}

Application Termination

There are two "modes" of application termination:

  1. exit - triggered by calls to System_exit() or exit(), manages the expected and orderly shutdown of an application
  2. abort - triggered by calls to System_abort() or abort(), manages the unexpected fatal application errors

The System_exit() function is intended to be used for a graceful termination. The System_abort() is intended for catastrophic termination. The main difference is that the atexit functions (bound via System_atexit or the ANSI Standard Library atexit() function) are executed on a call to System_exit() (or exit()) and not on a call to System_abort(). Applications call abort when continued execution risks further damage to the system; the application must as quickly as possible execute a function that puts and keeps the system in a "safe" state.

atexit Handling

atexit Handling.  An atexit function is a function that is called whenever some thread in the application calls either System_exit() or exit(). The System module allows you to configure the number of atexit functions that are bound at runtime via the maxAtexitHandlers configuration parameter (default is 8). The following statements set the maximum number of atexit functions that can be added, via System_atexit(), after the application starts running.

 
 
var System = xdc.useModule("xdc.runtime.System");
System.maxAtexitHandlers = 4;

The System module's atexit functions have the following prototype:

 
typedef Void (*AtexitHandler)(Int status);

The System module's atexit functions are called when a System_exit() is called and the System_atexit() function is used to add a function to the list of functions called. The status parameter passed to System_exit() is passed into each of these atexit functions, and they are executed on a last in first out (LIFO) basis.

 
 
 
if (System_atexit(myExitFxn) == FALSE) {
    /* failed to add myExitFxn atexit function */
}

The System module's atexit functions are independent of the ANSI Standard C Library's atexit functions. During startup, the System module registers a special System_rtsExit() function via the ANSI Standard C Library's atexit() function. During the execution of the ANSI Standard C Library's atexit functions, System_rtsExit() executes all of the System module's atexit functions.

System_exit

System_exit.  When called, the System_exit() function performs the following operations:

  1. Calls the standard C runtime exit() function.
  2. Via System_rtsExit (the standard C runtime atexit function that System registered):
    • Enters the System gate,
    • Calls the System module's atexit functions, and finally
    • Calls the Support Proxy's exit function

If the ANSI Standard C Library's exit() function is called instead of the System_exit(), the exit status passed into exit() is not passed to the System module's atexit functions. The constant System_STATUS_UNKNOWN (equal to 0xCAFE) is used instead.

System_abort

System_abort.  When called, the System_abort() function performs the following operations

  1. Enters the System gate,
  2. Calls the Support Proxy's abort function, and finally
  3. Calls the standard C runtime abort() function.

Neither the System module's atexit nor standard C runtime atexit functions are executed. If the standard C runtime abort() function is called instead of the System_abort(), the first two steps are not performed.

[printable version]  [offline version]offline version generated on 23-Oct-2014 06:10 UTC 
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Personal tools
package reference