Joined: 22 Aug 2005 Posts: 413 Location: Colarado, US
There are many applications where re-entrant programs are necessary or appropriate. Unfortunately, re-entrant programming has gained a reputation of being difficult.
A single copy of a re-entrant program can be used in parallel by more than one user. Obviously, at any one time only one program is actually running. However, a re-entrant program may be exited by one user before it completes (eg to wait for an I/O event to complete) and be re-entered by another user at some other point before the first user returns. In a large system, there may well be very many users; one of the best examples is an airline reservation system where, more or less concurrently, many users will be requesting flight availability information, etc. This immediately makes evident the properties of a re-entrant program:
Every user must have their own data area. The calling program normally provides a unique data area for each instance of the called re-entrant program. An alternative is for the called program to allocate its own data area.
The program module cannot contain any variable data, ie data areas that are not read-only. If this was not the case, the same data could be changed by more than user. A possible relaxation of this requirement is global data, such as for a first time switch, etc. In this case, it is conceivable that such data is contained in the program. However, this conflicts with the requirement for true re-enterability, and it is better to keep such global data centrally outside the program. Furthermore, it may be more efficient to have the program code loaded into a re-entrant memory pool.
Reusability is a related, but much simpler, concept. A reusable program can have only one user before it finishes processing (exits). It can then have a different user. Every call to the program must perform any required reinitialization on entry to the program. A re-entrant program is also reusable.
REQUIREMENTS FOR RE-ENTRANT PROGRAMMING
Each instance must initialize its data area. Because many IBM macros require a parameter list, such macros are provided in three forms:
List form. [/list]
The standard form is used for non-re-entrant programming. The executable and list forms are used for re-entrant programming. The MF (Macro Form) keyword specifies the macro form (E = Executable form, L = List form). Whereas the list form builds the static parameter list, the executable form adds specific (dynamic) parameters to the associated list. Although in some simple cases, eg the CALL macro, the list form represents only placeholders, in most cases it also contains flags, etc. This means that such list form macro expansions must also be included in the initialization. Unless the programmer knows the form of the macro concerned, he should include it in the initialization.
Example for the use of the execute and list forms of a macro:
macname - representative macro name.
dynparms - representative dynamic parameters.
listname - representative list name; the name of the associated list-form macro.
statparms - representative static parameters.
ADVANTAGES OF RE-ENTRANT PROGRAMMING
Re-entrant programming has the advantage that only one copy of the program needs to be present irrespective of the number of users. Frequently used components can be placed in the LPA (Link Pack Area).
DISADVANTAGES OF RE-ENTRANT PROGRAMMING
The disadvantages of re-entrant programs lie in their increased complexity and additional processing:
Variable data must be stored in a work area passed to the program (or allocated by the program itself). Additional areas can be allocated dynamically (GETMAIN) with the addresses and lengths being stored in this work area.
The initialization must be performed dynamically.
The techniques described in this article reduce these disadvantages to a minimum.
Note: Although for traditional reasons GETMAIN is mentioned, STORAGE OBTAIN will normally be used because of its better performance.
Here is some sample code:
SAMPLE RE-ENTRANT PROGRAM
RENTPGM AMODE 31
RENTPGM RMODE ANY
BAKR 14,0 save registers and return address
BASR 12,0 set base register
USING *,12 assign base register
* allocate work area
* register 1: address of allocated dynamic area
LR 9,1 address of dynamic area
* initialise work area
DYN USING UA,9 explicit use of the dynamic area
LA 0,DYN.UADATA address of dynamic area
LA 1,L'UADATA length of dynamic area
LA 14,UADATA address of the definitions
LR 15,1 length
MVCL 0,14 initialise dynamic area
USING UA,9 use variables in the dynamic area
EOP LA 15,0 set return code
PR , program return
LTORG , literal origin (must precede user-area)
* start of definition of the user-area
UA DS 0D user-area, align on double-word
MSGLEN DC AL2(MSGTEXTE-MSG)
MSG DC C'HDR:'
MSGTEXT DS CL8
MSGTEXTE EQU *
WTOLIST WTO TEXT=,ROUTCDE=11,MF=L
LUA EQU *-UA length of user-area
ORG UA reset origin
UADATA DS CL(LUA) redefine field with implicit length (LUA)
* end of definition of the user-area
Although this sample program is very simple, it demonstrates the features of re-entrant programming.
This sample re-entrant program allocates its own work area. This has the advantage that it allocates the space it needs, but at the cost of performing a (relatively time-intensive) GETMAIN. If a re-entrant (sub)program is called very frequently, it may be better for the calling program to perform its own storage management and pass an appropriate work area to the called program. This has the disadvantage that the calling program needs to know the size of such an area.
The key to this program is the use of the labelled USING to simplify the initialization of the work area. To simplify the explanation, MVC rather than MVCL is used in the following code (the restriction to 256 moving maximum characters does not matter in this case).
In the program DYN.UADATA specifies that the USING with the name DYN is to be used as base address (namely register 9). Register 9 addresses to the dynamic area.
Also UADATA without a prefix specifies that the current base register (namely register 12) is to be used for addressing, ie the static data area defined in the program code.
The subsequent USING UA,9 without label allows field names to be used from the dynamic area without requiring the prefix.
DYN USING UA,9 explicit use of the dynamic area
MVC DYN.UADATA,UADATA move to dynamic area
There are times when many users are concurrently using the same program, this is what we call Multi-Threading. For example, 50 users are using program A, CICS will provide 50 Working storage for that program but one Procedure Division. And this technique is known as quasi-reentrancy.
Actually I am working on a project where we are converting all COBOL programs to COBOLE, 31 bit and RENT=Y. I was surprised to see that many of the CICS programs were not re-entrant, as you suggested. Hope changing them to re-entrant does not mess up the system.