![]() |
![]() |
![]() |
![]() |
![]() |
Common Features
This section describes the parts of the integration that are common to the different models, but also some important differences.
Many of the data structures and macros described in this section are described in more detail in The Master Library. That chapter is, however, focused on a Light Integration. Some things, especially the listings of data structures, are not correct in every detail for Tight Integrations but should still be very useful.
The Use of Macros
A source file generated by an SDL to C compiler is independent from the choice of integration model and operating system. Instead of system calls, it uses macros that have to be defined elsewhere when the system is built. Each SDL concept is represented by one or more C macros. These macros will have different definitions for different integration models and operating systems. The SDL Suite provides a number of integration packages for this purpose. In a Light Integration, many macros are expanded into functions of the standard kernel. A Tight Integration has lower level macros that are defined in separate files for each operating system, and finally expanded into OS primitives or certain OS dependent constructions.
Below is an example of generated code for signal sending. Code in capital letters are the SDL Suite macros. The bracketed numbers indicate corresponding lines of code. For a description of the different macros, see The Master Library.
File Structure
The source file and examples for Tight Integration are not included in the standard delivery. They are available as free downloads from IBM Rational Support web site.
The Generated Files
An integration uses one or more of four files that can be generated by the Code Generator. All integrations require the C source file <systemname>.c, whereas the interface file <systemname>.ifc is optional. For a Tight Integration the signal number file <systemname>.hs may be used, and for a Light Integration the file sctenv.c, representing the environment, can be used.
The source file uses the highest level set of macros, that are defined in the different integration packages.
The Integration Packages
The files containing the necessary macro definitions and support functions are organized as shown in Figure 571. For each operating system there is one package for the Light Integration, and one for the Tight Integration. Although the files in different packages may have the same name they do not necessarily contain the same code. The principles for Tight Integration packages are described more thoroughly in Tight Integration. Details about each operating system can be found in the annexes.
There is also an INCLUDE directory containing source files common to all supported operating systems. These files are described in File Structure. Below are some additional comments on these files:
- scthooks.h:
- sctcommon.h:
- sctos.c:
- sctpred.h and sctpred.c:
- sctsdl.c:
- scttypes.h:
- This file contains the general datatype definitions for signals, IdNodes, etc. It also contains the macro definitions found in generated code. Note that this file is non-OS-specific. This means that if a call to an OS-specific primitive is needed, then a second level of macro is defined, according to the following model.
- In the generated code:
ALLOC_SIGNAL_PAR(ok, ySigN_z3_ok, TO_PROCESS(Env, &yEnvR_env), yPDef_z3_ok)- In scttypes.h:
#define ALLOC_SIGNAL_PAR(SIG_NAME, SIG_IDNODE, \RECEIVER, SIG_PAR_TYPE) \RTOSALLOC_SIGNAL_PAR(SIG_NAME, SIG_IDNODE, \RECEIVER, SIG_PAR_TYPE)- In sct<RTOS>.h:
#define RTOSALLOC_SIGNAL_PAR(SIG_NAME,SIG_IDNODE,\RECEIVER, SIG_PAR_TYPE) \yOutputSignalPtr = \xAlloc(sizeof(xSignalHeaderRec)+ \sizeof(SIG_PAR_TYPE)); \yOutputSignalPtr->SigP = yOutputSignalPtr+1; \yOutputSignalPtr->SignalCode = SIG_NAME; \yOutputSignalPtr->Sender = SDL_SELF;The Examples directory contains a simple SDL system that also uses an external process (a separate OS task). For each supported operating system there is an implementation of this, demonstrating how to hook into the integration package. Further description of the example can be found in A Simple Example.
Naming Conventions
Names of variables, datatypes and support functions in generated code and package files often start with one of the letters x, y and z.
The general rules (there are some exceptions) are:
- Names and objects starting with an `x' represent general datatypes and support functions in the kernel.
- Names starting with a `y' are names of IdNodes representing SDL variables, process states, channels, blocks, datatypes for signals, PAD functions, etc. in generated code.
- Names and objects starting with a `z' are SDL variables, SDL names, process state names, etc. in generated code.
The Symbol Table
All signals, blocks, processes, channels, etc. in an SDL system have a corresponding representation in the symbol table described in The Master Library. This symbol table consists of nodes (IdNodes) each representing one entity of the system. The IdNodes are pointers to structs. See the following example:
extern XCONST struct xPrsIdStruct yPrsR_z02_dynpr1;#define yPrsN_z02_dynpr1 (&yPrsR_z02_dynpr1)The N_ and the R_ just before z02_dynpr1 indicate if it is a node (N_) or a record (R_).
Memory Allocation
The xAlloc function is always used when allocating dynamic memory. The function is placed in the sctos.c file, but in the Tight Integrations the body of the function is found in the sct<RTOS>.h file.
Start-up
The yInit function is called during start-up of the SDL system. It is responsible for creating all static processes and for initializing SDL synonyms.
Implementation of SDL Concepts
SDL Processes
An SDL process consists of three parts in generated code: Instance set common data, instance specific data and dynamic behavior.
Instance set common data
Variables and structures that are common to all instances of a process are stored in a record of the type xPrsIdStruct, defined in scttypes.h. This record is referenced by a node in the symbol table.
Instance specific data
Variables and structures of the process instance are declared via the macro PROCESS_VARS. This macro is defined in different ways in the Light and the two models of Tight Integration. It contains state information, local variables, pointers to parent and offspring, etc. One important entry is the RestartAddress, pointing out which transition to execute when the PAD function runs (see below).
Dynamic behavior
The dynamic behavior of an SDL process is implemented in a PAD function (Process Activity Definition). The PAD function is used somewhat differently in the different integration models:
- In the Light Integration the scheduler calls the PAD function of the process. The PAD function then returns to the scheduler when the transition is finished.
- In the Standard Model Tight Integration the PAD function is called when the process is started and does not return until process termination. It then contains a main loop where one iteration corresponds to one transition.
- The Instance Set Model Tight Integration contains a mix of the two.
Below is the code for ending a transition, before and after macro expansion for a Light Integration.
Signal Queues
Basically, every process has at least one signal queue.
- In a Light Integration each process instance has an input queue.
- In the Standard Model Tight Integration there is an input queue and a save queue for each instance.
- In the Instance Set Model Tight Integration there is an input queue and a save queue for every instance set. These two queues are shared by all the instances.
All signals that are sent to a process arrive in the input queue. The save queue is used to keep signals that cannot be handled in the current state but should be saved for future use. This is tightly connected to the SDL Save concept, but is also used in the implementation of timers. For a Light Integration there are no save queues. Instead, all signals that should be saved will remain in the input queue until they can be received.
Process Priorities
The use of process priorities requires some caution. Priorities can be set with the #PRIO directive in the SDL Suite, but there is no mapping of priorities for different platforms. The generated code will use exactly the values specified in the SDL system. This will not be a problem in a Light Integration, but for Tight Integrations the result may not be the expected.
Example 556 : Process priority problems
Assume that Process1 has its priority set to 100 using the #PRIO 100 directive and Process2 has #PRIO 50. These priority values will be used as-is by the underlying scheduler.
In the SDL Suite simulators and Light integrations, the highest priority is 0. In VxWorks, 0 is the highest priority, whereas in pSOS the highest priority is 255.
Thus the simulated system, a Light integration for any operating system and a Tight integration for VxWorks will all run Process2 at a higher priority than Process1. In contrast, a Tight integration for pSOS will run Process1 at a higher priority than Process2!
Process Creation
Regardless of the integration model there are a number of things that have to be done when an SDL process instance is created. The structs that represent the instance have to be created. It needs a representation in the symbol tree and a signal queue, except in the Instance Set Model of Tight Integration where the signal queue belongs to the instance set. A start-up signal is also always allocated and sent to the process.
SDL Signals
Signal Sending
In generated code a signal sending is handled by two macros: ALLOC_SIGNAL (or ALLOC_SIGNAL_PAR for a signal with parameters) and SDL_2OUTPUT_xxxx (there are different macros depending on how the SDL output was defined, e.g. with or without an explicit TO).
In this example the signal is called go and has no parameters. The SDL_2OUTPUT_COMPUTED_TO macro indicates that it was sent without an explicit TO.
SDL Procedures
An SDL procedure is represented by a function similar to a PAD function. Before a procedure is called there are two support functions that need to be called: xGetPrd and xAddPrdCall.
The xGetPrd function allocates an xPrdStruct for the called procedure and returns an xPrdNode pointing to the struct.
The xAddPrdCall function adds the new procedure call in the calling process' ActivePrd list (an element in the xPrsStruct).
The procedure is called with a pointer to the instance data of the calling SDL process. This is because the procedure must be able to use internal variables in the calling process.
Before a procedure returns to the caller it performs an xReleasePrd call. This function removes the call from the ActivePrd list.
SDL Timers
SDL timers are represented by signals. All active timer signals are kept in a sorted list, either within the single task of a Light Integration or in a certain timer task in a Tight Integration. When a timer expires, the signal representing it is sent to the SDL process that set it.
http://www.ibm.com/rational |
![]() |
![]() |
![]() |
![]() |