gtpa2m3a | Application Programming |
At times, several programs are required to process a single message. This can be done under the control of a single ECB, or the active ECB can create another independent entry, which has the effect of subdividing the processing. The active entry also has the ability to change the processing order by suspending its own processing or lowering its priority.
Application programs transfer control to other entry points that use the same ECB with the enter/back services. The enter/back mechanism allows the application program to call or return to other application programs. The enter/back mechanism generates a code expansion that contains the information required by the linkage editor to create the linkage to reach the appropriate system service routine. The TPF system locates the programs in system storage and manages the main storage required to execute the programs. In assembler, only the 4-character program library name (for example, CYYA) is needed to call other programs. As programs return, main storage can be released by the system.
Information necessary to locate and execute an application program is transferred through one of the program Enter macros. Enter macros are coded explicitly by assembly language programs. The action of the ENTRC macro is performed automatically by the C language calling mechanism, so there is no C language equivalent of the ENTRC macro. There is a C function that corresponds to the ENTDC (Enter-Drop) macro. A request can be to:
The process of calling a chain of application programs under the control of the same ECB (using the enter/back services) is called nesting. The ECB contains 35 program levels that TPF uses to control program linkage. If more than 35 levels are required, TPF uses an additional block of working storage to control program linkages and correlate the ECB and the programs that it references. This linkage is transparent to the application program. However, the application programs must not exceed the nesting limit determined at system initialization. If the limit is exceeded, a system error will result and the entry will be exited.
You should release all programs as soon as possible to allow efficient use of main storage. This is the significance of the ENTDC macro or the entdc function. When the logic flow indicates that a series of programs no longer need to be activated, you can use entdc to release them. The ENTDC macro or the entdc function handles situations in which a programmer wishes to leave the C programming environment for the assembler environment. For ISO-C after a call to entdc, the stack pointer is reset to the top of the stack and the static storage is kept. For TARGET(TPF) after a call to entdc, all associated stack storage and static storage are released.
The C language programmer who also is experienced in assembler programming under TPF should note that the ENTNC assembler macro is not supported for C programming because a goto concept to an entry point does not exist in the C language.
Sometimes it is desirable to subdivide the processing of a given message to enable faster response to time-dependent functions or a more efficient program structure. TPF provides a set of macros and functions to permit an active entry to create another independent entry (TPF normally creates an entry as the result of an input message). When tpf_cresc is used, one creating entry can pass as much as 4 K bytes of data to a created entry and the created entry can pass a return value back to the creating entry. The creating entry can pass up to 104 bytes of parameter information to the created entry. Once TPF creates the entry, it retains the name of the creating entry at ECB location ce1trc, but that is the extent of any linkage between the 2 entries--they continue processing completely independently of one another.
TPF stores the parameters to be passed to the created entry in an interim main storage block that it adds as an item to a CPU loop list. This list is one of the following:
TPF dispatches these lists, among others, whenever it is given control. The dispatching is in the above order; therefore, no item on the deferred list can be processed unless the input list is completely empty, and no item on the input list can be processed unless the ready list is completely empty.
When the item placed on the list by the create function is removed from the list for execution, the parameters to be passed to the newly created entry are moved into a new ECB that operational program zero (OPZERO) creates. An ECB is created for each new entry in the system and is assigned an activation number, which is obtained either from a system counter in OPZERO or from the ECB of the program executing the create function. The activation number determines which version of the E-type program the ECB will use. TPF then transfers control to the entry point specified in the create function call.
The type of create function called determines the priority of the
processing that will be associated with the new ECB. Table 21 describes the create functions available to programmers
using the C language under TPF.
Table 21. Description of Create Functions
Function | Action |
---|---|
credc | Creates a deferred entry and places the entry on the deferred list. |
creec | Creates an entry with an attached main storage block, for immediate or deferred processing. |
cremc | Creates an entry for immediate processing on the ready list. |
cretc | Creates a time-initiated entry from an item placed on the ready list after a specified time interval. This function requires an interface with the system clocks. |
cretc_level | Creates a time-initiated entry from an item placed on the ready list after a specified time interval. It places the entry on the specified core block reference word. This function requires an interface with the system clocks. |
crexc | Creates a low priority deferred entry from the deferred list. This function is like credc, but crexc requires that more main storage blocks be available for real-time processing before it will execute. Programs that create many deferred entries use crexc to avoid depleting the number of blocks available for more critical real-time processing. |
sipcc | In a loosely coupled environment, provides communication between processors; in a tightly coupled environment, provides communication between instruction streams. This is for system programs only. |
swisc_create | Creates a new ECB on another I-stream. |
system | Creates a synchronous entry for immediate processing of a program that has a main function and suspends the current entry. |
tpf_cresc | Creates a synchronous entry for immediate processing on the ready list and suspends the current entry. |
tpf_fork | Creates an asynchronous ECB on a specified I-stream. |
All these functions subdivide the processing of a given entry by creating a new ECB and passing it to a specified entry point to continue processing. The entry point must have been allocated by means of the system allocator. The proper linkage also must be available to the entry point.
In assembly language, the program to be activated must be specified in the macro instruction operand. R14 and R15 must be used to reference the parameters being passed. For CREDC, CREEC, CREMC, and CREXC, R14 must be loaded with the number of bytes of parameters being passed, and R15 with the location of the parameters. For CRETC, R14 can be loaded with the time interval prior to activation or the time interval can be passed via the TIMEINC parameter of the CRETC macro. R15 contains data to be passed, or the PARM parameter can be used in the CRETC call. See the TPF General Macros for further details on using CRETC parameters.
The CRESC macro, which creates a synchronous entry for immediate processing, may request the creation of up to 50 ECBs. The ECBs are created in the same subsystem and subsystem user as the creating ECB (also called the parent ECB) but may be dispatched on any I-stream. The creating ECB may pass up to 4 K of data to each of the created ECBs. The creating ECB is placed on the wait list until the created ECB has completed. Upon exiting, the ECB that was created may pass a return value back to the creating ECB. See TPF General Macros for further details on using tpf_cresc parameters and register specifications.
Examples:
LA R1,PGM Name of program to enter LA R2,2 I-stream number LA R3,DATA Address of data to pass LA R4,20 Number of bytes of data LA R5,100 100 second timeout CRESC PROGRAM=(R1),WAIT=YES,DATA=(R3,R4),IS=(R2),TIMEOUT=(R5), RTNLST=(R6) One ECB will be created and dispatched on the I-stream specified by R2. Twenty bytes of data, beginning at DATA, will be passed. The creating ECB will wait 100 seconds for the created ECB to be completed successfully. Upon reactivation, the creating ECB can access the value returned by the created ECB using R6. LA R15,EBW020 Address of bytes to pass CREMC ABCI Activate program ABCI LA R14,48 Number of bytes passed LA R15,EBW020 Address of bytes to pass CREMC ABCI Activate program ABCI LA R14,10 Time increment value L R15,EBW040 Data meaningful to program ABCI CRETC S,ABCI Time interval is seconds (may also be 'M' for minutes) Activate program ABCI after 10 seconds CRETC S,ABCI,TIMEINC=10,PARM=pgmlabel Time interval will be placed in R14 by the CRETC macro Activate program ABCI after 10 seconds Data meaningful to program ABCI at label 'pgmlabel' will be placed in R15 by the CRETC macro
You must supply the following arguments when calling C language functions credc, cremc, and crexc:
A creec function call also must specify the data level that contains the working storage block to be passed to the new ECB. A creec function call also must specify an integer value, either DEFERRED or IMMEDIATE priority, to determine the list where the block is to be placed.
For cretc, you must specify the following arguments:
A cretc_level function call also must specify the data level of the core block reference word on which the ECB will be placed.
For tpf_cresc, you must specify the following arguments:
Examples of Using the Create Functions:
The following example creates a deferred entry for program COT0, passing the string "VPH" as input data to the program.
#include <tpfapi.h> char *parmstring = "VPH";
·
·
·
credc(strlen(parmstring),parmstring,COT0);
The following example creates an ECB dispatched from the ready list for program OMA0, passing the string "755/15AUG" and the working storage block on level D0 as input to the program.
#include <tpfapi.h> char *parmstring = "755/15AUG";
·
·
·
creec(strlen(parmstring),parmstring,OMA0,D0,IMMEDIATE);
The following example creates an ECB dispatched from the ready list for program COT0, passing the string "VPH" as input data to the program.
#include <tpfapi.h> char *parmstring = "VPH";
·
·
·
cremc(strlen(parmstring),parmstring,COT0);
The following example creates an ECB dispatched from the ready list for program QZZ0 after 5 seconds have elapsed. TPF will place the 4-byte character string "INIT" in ebw000-ebw003 of the new ECB.
#include <tpfapi.h>
·
·
·
cretc(SECONDS,QZZ0,5,"INIT");
The following example creates a deferred entry for program COT0, passing the string "VPH" as input data to the program.
#include <tpfapi.h> char *parmstring = "VPH";
·
·
·
crexc(strlen(parmstring),parmstring,COT0);
The following example creates two synchronous ECBs for immediate processing. The first ECB that is created will be passed 20 bytes of data and will be dispatched on I-stream 1. The second ECB that is created will not receive any data, will be dispatched on the main I-stream, and the creating ECB will wait indefinitely for the created ECBs to be completed.
#include <stdio.h> #include <stdlib.h> #include <tpfapi.h> /* Initialize parameters for WAIT=NO call. */ char data[16] = "Hi..this is QXQZ"; /* Data to be passed */ struct tpf_cresc_input tci; /* Input structure for */ /* tpf_cresc() */ struct tpf_ev0bk_list_data *ebptr; /* Return value from */ /* tpf_cresc() */ tci.program = "QPM1A"; /* Pgm for child to enter */ tci.istream = 1; /* I/S for child to run on */ tci.wait = TPF_CRESC_WAIT_NO; /* Don't create ECB yet */ tci.data_length = 20; /* Pass 20 bytes of data */ tci.data = data; /* Pass data at label DATA */ /* Issue WAIT=NO call. */ ebptr = tpf_cresc(&tci); /* Issue WAIT=NO call * / /* Initialize parameters for WAIT=YES call. */ tci.program = "QPM1A"; /* Pgm for child to enter */ tci.istream = TPF_CRESC_IS_MAIN; /* I/S for child */ tci.timeout = 0; /* Timeout value for parent */ /* Parent will wait forever */ tci.wait = TPF_CRESC_WAIT_YES; /* Create all children */ tci.data_length = 0; /* No data being passed */ tci.data = NULL; /* No data being passed */ /* Issue WAIT=YES call. All child ECBs requested to date will now */ /* be created and dispatched. */ ebptr = tpf_cresc(&tci); /* Issue WAIT=YES call */
TPF provides 2 macros or functions that permit the entry currently using the CPU to request suspension of processing. TPF places suspended entries on either the input or deferred lists. This permits system programs to restore registers and return control to a suspended program.
The 2 functions used to suspend processing are:
No parameters are required with the defrc and dlayc functions.
The defrc and dlayc functions differ slightly from the waitc function. The waitc function is related to the completion of an I/O operation; if no I/O is pending then no suspension occurs. Both dlayc and defrc place the entry at the bottom of a list.
The period of time during which processing is suspended for deferred entries can be substantial. Accordingly, no records can be held by means of the record hold facility by an entry executing defrc, and no time dependent action (for example, response to a terminal) should follow this function. The entry should hold the least possible amount of working storage to minimize the impact on system performance.
The exit functions are a special case of transferring control. They signify that processing of the entry is complete, and that the application wishes to release the remaining system resources and return control to TPF. Exit functions do the housekeeping required to remove an entry from the system. Resources held by the exiting entry are returned to the system for use by other entries.
When you call an exit function, the TPF system transfers control to the exit system service routine. Several library functions can cause this transfer of control to occur:
A program check (for example: an addressing exception, or an attempt to change protected areas of main storage) also causes the TPF system to transfer control to the exit system service routine.
The exit system service routine performs the following checks and functions when executing on behalf of exit, abort, snapc, and serrc_op with the SERRCEXIT option for C language or SERRC for assembly language:
A held record means the entry was using the system conventions to prevent other entries from modifying the record.
The information needed for clearing an exited entry from the system is contained in various ECB fields.
No operands are required with the EXITC macro. The parameters for the SERRC and snapc macros are described in TPF General Macros.
The exit functions for C language require the following arguments:
Transfer vectors are not supported for load modules. Load modules contain 1 external entry point.
In TARGET(TPF) C language transfer vectors allow a single program segment to have multiple entry points; in other words, transfer vectors allow a single program segment to contain multiple entry points. TPF handles calls to transfer vectors with the enter/back services: even when transfer vectors in the same program segment call each other. You should be aware of the general form of transfer vectors so that you will recognize them when you see them in existing code.
In TARGET(TPF) transfer vectors are coded into the system allocator and cross referenced to the program segment name. From C programs, transfer vectors can be called in the same way as normal entry points. If a C program contains multiple entry points, these functions are treated as transfer vectors. The IBM C compiler with TARGET(TPF) set automatically generates a branch table consisting of a series of unconditional branch instructions associated with each of the transfer vector names. Each transfer vector, once entered, functions as an independent entry point.