gtpa2m0w | Application Programming |
The following tables show summaries of the calls that are supported in TPF
E-type programs.
Table 7. Function or Program Calls Allowed in ISO-C
Type of Function (or Program) Originating the Call | Dynamic Load Modules (DLMs) | DLMs with main | External Functions (Link Scope) | Library Functions | Static Functions (Source Scope) | Assembler Programs | Dynamic Link Library (DLL) |
---|---|---|---|---|---|---|---|
Dynamic Load Modules (DLMs) | Yes | Yes | Yes2 | Yes | Yes1 | Yes7 | Yes3 |
DLMs with main | Yes | Yes | Yes2 | Yes | Yes1 | Yes | Yes |
External Functions (link scope) | Yes | Yes | Yes2 | Yes | Yes1 | Yes | Yes3 |
Library Functions | Yes | Yes | Yes2 | Yes | Yes1 | Yes | No4 |
Static Functions (source scope) | Yes | Yes | Yes2 | Yes | Yes1 | Yes | Yes3 |
Assembler Programs | Yes6 | No | Not Applicable | No | Not Applicable | Yes | No5 |
Dynamic Link Library | Yes | Yes | Yes2 | Yes | Yes1 | Yes | Yes |
|
See Table 6 and "main or extern "C" Requirement" for more information about this linkage difference.
Table 8. Function or Program Calls Allowed in TARGET(TPF).
Type of Function (or Program) Originating the Call | External Functions | Library Functions | Static Functions | Assembler Programs |
---|---|---|---|---|
External Functions | Yes | Yes | Yes * | Yes |
Library Functions | Yes | Yes | Yes * | No |
Static Functions | Yes | Yes | Yes * | Yes |
Assembler Programs | Yes | No | No | Yes |
|
There are several different types of items that DLMs can call using function call syntax:
The only difference between calling BAL segments and other C functions is that the function prototype for BAL segments is restricted. If you call a BAL segment, the prototype must be:
void SEGN(struct TPF_regs *);
where SEGN is the 4-character segment name.
The call to a BAL segment looks like:
struct TPF_regs regs; /* Set up regs as appropriate to the BAL segment interface */ SEGN(®s);
In standard C or C++, if the BAL segment does not use registers in its interface, you can code a NULL pointer:
SEGN(NULL); /* You MUST code the regs parameter for BAL calls, */ /* even if the called segment doesn't use registers */ /* for its interface. */
Do not use the NULL pointer instead of TPF registers in TARGET(TPF).
There are several functions that activate only E-type programs. The following functions call E-type programs:
If a function is written in assembler with the TMSPC and TMSEC macros, this assembler function can activate E-type programs. The following is a list of the BAL equivalents of the C macros:
Notes:
How ISO-C functions are packaged can affect the overall performance of a program. There are several ways to package functions:
There are advantages and disadvantages to each packaging technique.
The fastest performance for a function comes from using the INLINE option of the compiler. Using inline functions eliminates entirely call linkage, function prolog, function epilog and return linkage, and allows global optimization of calculating function arguments and the function body. If simple functions must be called many times in a loop, the combination of inlining and global optimization can yield significant improvements in path length.
One cost of using inline functions is maintenance. The source code for the functions is included in header files for all the programs that use them. If a function needs to be updated all applications that call it must be recompiled, relinked, and reloaded.
Other disadvantages to inline code are:
Inlining is an optional feature of the IBM C compilers on the System/390 platform. Inlining is standard for the IBM C++ compilers on the System/390 platform. It is not part of the ANSI/ISO C standard.
The next fastest performance is determined by how functions are accessed, whether through a stub or not. Functions that are accessed without using a stub are faster than those accessed through a stub.
For function calls that do not need a stub, the compiler, linkage editor, and relocating loader (program fetch) generate the linkage, which is executed without use of system services or system data. Call linkage is usually 2 instructions, plus parameter loading and unloading, and return linkage is included in the function epilog.
The cost of a function in the same compiled unit as its caller and the cost of link editing functions together are much the same. It is a tradeoff between program execution and easier maintenance. If a function needs to be updated, only the function itself must be recompiled, but all applications that use the function still must be relinked, reloaded, and tested again.
The use of library functions involves a slightly longer path length than the use of link-edited functions. This is because the calling program must use a library call stub to access library functions. In addition, secondary linkage processing makes the path length for the library calls much longer if one of the following conditions exists:
The advantage of library functions is that they are easy to maintain and reuse in many applications. If the function needs to be updated only the function needs to be recompiled, and only the library load module needs to be relinked and loaded.
A disadvantage is that at a given time, for a given library, all functions use the same linkage. Libraries that contain reentrant (RENT) static ALWAYS use secondary linkage. Therefore, library functions that require reentrant static should not be included in libraries that must give high performance.
DLMs are the primary structure for ISO-C functions. Call and return linkages between DLMs are managed by TPF system services and are comparable to ENTRC and BACKC linkage. There is additional overhead for managing linkages between different types of programs.
The performance decision involves the number of DLMs that need to be created for a given application. The fewer DLM calls needed, the faster a given application performs. Calls to DLMs generate the most linkage overhead because they:
The disadvantage is the loss of visibility of the function of a DLM to the system. If DLM A is folded into DLM B to improve DLM B's performance, the service that DLM A provides is lost to other DLMs (without replicating DLM A).
ISO-C uses an array of addresses to library vectors (AOLA) to provide its primary linkage to library functions. See Figure 7. The AOLA is created during TPF restart. AOLA entries are replaced with pointers to library vectors (LIBVECs) as libraries are read into main storage. A LIBVEC is a series of entry point addresses of functions.
Each library is associated with a particular library ordinal, defined by the library interface tool. This library ordinal defines the order that the libraries are placed in the AOLA. See Table 9 to see which ordinals are assigned to which libraries. The AOLA mechanism allows calls to functions in as many as 1024 libraries. A library ordinal in the AOLA and a LIBVEC offset together serve to uniquely identify a particular function.
When a new version of a library included in an E-type loader loadset is activated, a common block is used to build a new AOLA. The common block is key-protected.
Figure 7. Example of an Array of Library Addresses and LIBVECs
Table 9 describes which ordinals are in use by which library.
Library | Ordinal Number | Description |
---|---|---|
CISO | 0000 | Standard C library |
CTAL | 0001 | TPF API library |
CTDF | 0002 | TPFDF library |
CTBX | 0003 | ISO-C general purpose toolbox library |
COMX | 0004 | TPF communications functions |
CMQI | 0007 | MQI client library |
CTHD | 0008 | threads library |
CRPC | 0011 | RPC library |
Linkage to functions contained in libraries is through a
stub. A stub is a small piece of code on the end of a
program used to locate functions in libraries. For example, the
clock function is contained in the TPF library CISO. Imagine
a program BAZ calls clock. To gain access to the
clock function, control transfers to the stub for clock
on the end of BAZ. The stub was added during the link-editing of
BAZ. The stub itself comes from the stub library created by the library
interface tool. The stub for clock contains the library
ordinal and LIBVEC offset for the actual clock function. The
executable form of the clock function was loaded during TPF restart
when the CISO library was loaded. The information in the stub provides
run-time access to the code for clock and the stub transfers
control to the clock code.
Suppose we have a program BAZ. Overall, when the C compiler encounters an external function call (Foo) in an ISO-C program, it generates external function linkage. While satisfying the external linkage, the linkage editor gets a stub to access the external function. (See the Figure 8.)
The address of the function required is not available at compile time. The compiler generates a VCON to be satisfied during linkage editing. During linkage editing the VCON for the external function is satisfied by using the stub function that corresponds to the function called. The linkage editor retrieves the stub from the stub library and appends it on the end of the load module being generated. The stub contains the library ordinal and the LIBVEC offset. When the stub was generated, it was set with information about the location of the function it represents. In the example function Foo is the fourth function defined in library CMAS (301), so the library ordinal is 301 and the LIBVEC offset is 3. When run, the stub function performs like an execution-time "glue module", sticking the library references kept in the function body together with the library as it exists in the online system.
Figure 8. Offline Stub Linkage
When segment BAZ runs on the online system and finds a call to function Foo, the stub for Foo at the end of BAZ uses the library information to locate the executable code for Foo. (See Figure 9) The stub does this by using the library ordinal (301) it contains to look up the pointer to the correct LIBVEC in the AOLA. Using the LIBVEC pointer and the offset (3) it picks up a pointer to the code for Foo (in the CMAS user library). With this LIBVEC the stub uses the function offset to locate the entry point address for function Foo, which was created when the library with Foo was loaded (during restart). The stub transfers to the entry point address to run the Foo function. When Foo returns, it continues at the NSI after the original call to Foo in program BAZ.
It is critical that the order of the libraries in the AOLA must correspond to the order of the libraries used when programs are compiled and linked. Clearly, if the order of the 2 libraries is different, the functions called by the program will not be the functions run by the system.
Figure 9. Online Function Linkage
If a library requires writable static, or contains an active user exit, or is selectively activated using the E-type loader, the linkage for any function in the library uses secondary linkage. In this case, the AOLA entry for the library is a pointer to the secondary LIBVEC. The LIBVEC itself points to a branch vector that receives control instead of the function directly. When the function is called, common code handles the static storage pointers or activates the user exit routine. This additional overhead causes slower performance in these functions.
Writable static involves such overhead that you should be clear about what it is. In C language a variable can be declared static. This means the variable is not reinitialized every time the function containing it is called. An example of static data is a constant character string (like "this is a test"). Constant data can be reinitialized with every function call without loss. What if you wanted to prevent the data from being initialized every time? If the static character string contained a part that changed (like "this is Bob", "this is Fred", and so on), something special would be required to keep the information. This something special is secondary linkage. Secondary linkage is required to keep track of Bob one time, Fred the next, and so on.
Secondary linkage is described in Figure 10 following. Function Foo, which is found in segment BAZ, has its associated library information. The stub for Foo, which is the same whether primary or secondary linkage is used, is at the end of BAZ and uses the library information. The AOLA entry either points to the executable code for Foo in the CMAS library (primary linkage) or it points to the library startup code at the beginning of the library (secondary linkage). Every library has library startup code at its beginning. The startup code takes care of some housekeeping chores before and after transferring to function Foo. If the CMAS library contains writable static or has the user exits active, secondary linkage is used instead of primary linkage.
In the figure primary linkage is shown as a simple double arrow and secondary linkage is shown as steps A, B, and C.
If writable static is required, space in the frame is set up to accommodate the static. If the user exits are active, they receive control. When the user exit ends, the startup code transfers to the entry point address of Foo. When Foo ends, it returns to the startup code, which transfers to another user exit, if they are active. When this ends, the startup code returns to segment BAZ which continues with the next sequential instruction after the call to Foo.