Multithreading is a technique that allows a single copy of an application program to be processed by several transactions concurrently. For example, one transaction may begin to execute an application program. When an EXEC CICS® command is reached, causing a CICS WAIT and call to the dispatcher, another transaction may then execute the same copy of the application program. (Compare this with single-threading, which is the execution of a program to completion: processing of the program by one transaction is completed before another transaction can use it.)
Multithreading requires that all CICS application programs be quasi- reentrant; that is, they must be serially reusable between entry and exit points. CICS application programs using the EXEC CICS interface obey this rule automatically. For COBOL, C, and C++ programs, reentrancy is ensured by a fresh copy of working storage being obtained each time the program is invoked. You should always use the RENT option on the compile or pre-link utility even for C and C++ programs that do not have writable statics and are naturally reentrant. Temporary variables and DFHEIPTR fields inserted by the CICS translator are usually defined as writable static variables and require the RENT option. For these programs to stay reentrant, variable data should not appear as static storage in PL/I, or as a DC in the program CSECT in assembler language.
As well as requiring that your application programs are compiled and link-edited as reentrant, CICS also identifies programs as being either quasi-reentrant or threadsafe. These attributes are discussed in the following sections.
CICS runs user programs under a CICS-managed task control block (TCB). If your programs are defined as quasi-reentrant (on the CONCURRENCY attribute of the program resource definition), CICS always invokes them under the CICS quasi-reentrant (QR) TCB. The requirements for a quasi-reentrant program in a multithreading context are less stringent than if the program were to execute concurrently on multiple TCBs.
CICS requires that an application program is reentrant so that it guarantees consistent conditions. In practice, an application program may not be truly reentrant; CICS expects "quasi-reentrancy". This means that the application program should be in a consistent state when control is passed to it, both on entry, and before and after each EXEC CICS command. Such quasi-reentrancy guarantees that each invocation of an application program is unaffected by previous runs, or by concurrent multi-threading through the program by multiple CICS tasks.
For example, application programs could modify their executable code, or the variables defined within the program storage, but these changes must be undone, or the code and variables reinitialized, before there is any possibility of the task losing control and another task executing the same program.
CICS quasi-reentrant user programs (application programs, user-replaceable modules, global user exits, and task-related user exits) are given control by the CICS dispatcher under the QR TCB. When running under this TCB, a program can be sure that no other quasi-reentrant program can run until it relinquishes control during a CICS request, at which point the user task is suspended, leaving the program still "in use".The same program can then be reinvoked for another task, which means the application program can be in use concurrently by more than one task, although only one task at a time can actually be executing.
To ensure that programs cannot interfere with each others working storage, CICS obtains a separate copy of working storage for each execution of an application program. Thus, if a user application program is in use by 11 user tasks, there are 11 copies of working storage in the appropriate dynamic storage area (DSA).
Quasi-reentrancy allows programs to access globally shared resources--for example, the CICS common work area (CWA)--without the need to protect those resources from concurrent access by other programs. Such resources are effectively locked exclusively to the running program, until it issues its next CICS request. Thus, for example, an application can update a field in the CWA without using compare and swap (CS) instructions or locking (enqueuing on) the resource.
Take care if a program involves lengthy calculations: because an application program retains control from one EXEC CICS command to the next, the processing of other transactions on the QR TCB is completely excluded. However, you can use the task-control SUSPEND command to allow other transaction processing to proceed; see Task control for details. Note that runaway task time interval is controlled by the transaction definition and the system initialization parameter ICVR. CICS purges a task that does not return control before expiry of the IVCR-specified interval.
In the CICS open transaction environment (OTE), when application programs, task-related user exits (TRUEs), global user exit programs, and user-replaceable modules are defined to CICS as threadsafe, they can run concurrently on open TCBs. Because of this, they cannot rely on quasi-reentrancy to protect shared resources from concurrent access by another program. Furthermore, quasi-reentrant programs might also be placed at risk if they access shared resources that can also be accessed by a user task running concurrently under an open TCB. The techniques used by user programs to access shared resources must therefore take into account the possibility of simultaneous access by other programs. To gain the performance benefits of the open transaction environment while maintaining the integrity of shared resources, serialization techniques must be used to prohibit concurrent access to shared resources. Programs that use appropriate serialization techniques when accessing shared resources are described as threadsafe. (The term fully reentrant is also used sometimes, but this can be misunderstood, hence threadsafe is the preferred term.)
The performance benefits of being threadsafe can only be gained by applications that involve a task-related user exit (TRUE) enabled using the OPENAPI option on the ENABLE PROGRAM command. Task-related user exits like this are known as open API TRUEs. An open API TRUE will be given control under an L8 mode open TCB, and can use non-CICS APIs without having to create, manage and switch between subtask TCBs. The CICS DB2 task-related user exit that is used by the CICS DB2 attachment facility operates as an open API TRUE when CICS is connected to DB2 Version 6 or later, which means that CICS DB2 applications can gain performance benefits from being threadsafe (as explained in "SQL, threadsafe and other programming considerations for CICS DB2 applications" in the CICS DB2® Guide).
The goal of making programs threadsafe is to enable them to remain on an open TCB, rather than switching back and forth between the open TCB and the QR TCB. When CICS is connected to DB2 Version 6 or later, TCB switching occurs in the following circumstances:
The maximum TCB switching for a CICS DB2 application would occur if your program used a non-threadsafe user exit program and a non-threadsafe EXEC CICS command after every DB2 request. In particular, the use of a non-threadsafe exit program on the CICS-DB2 mainline path (for example, a program that is enabled at XRMIIN or XRMIOUT) causes more TCB switching than what is experienced when CICS is connected to Version 5 or earlier.
If you want to make an application program remain on an open TCB:
As
well as checking EXEC CICS commands that you code explicitly, be aware
of high-level language constructs or Language Environment callable
services used by your program that result in using CICS services.
CICS services used in this way might involve non-threadsafe CICS commands,
and cause a switch back to the QR TCB. In particular, the COBOL statement
DISPLAY UPON SYSOUT, some types of PL/I and C++ output,
and the Language Environment callable services CEEMOUT and CEE3DMP,
write data to the Language Environment transient data destinations
CESE and CESO. This involves an EXEC CICS WRITE TD command, which
is not threadsafe.
To make your program's application logic threadsafe, ensure that it uses appropriate serialization techniques when accessing shared resources. For most resources, such as files, transient data queues, temporary storage queues, and DB2 tables, CICS processing automatically ensures access in a threadsafe manner. As described above, some of the CICS commands that operate on these resources are coded to use appropriate serialization techniques that allow them to execute on open TCBs (that is, they are threadsafe commands). Where this is not the case, CICS ensures threadsafe processing by forcing a switch to the QR TCB, so that access to the resources is serialized regardless of the behaviour of the command. However, for any other resources which are accessed directly by user programs, such as shared storage, it is the responsibility of the user program to ensure threadsafe processing.
Typical examples of shared storage are the CICS CWA, the global work areas for global user exits, and storage acquired explicitly by the application program with the shared option. You can check whether your application programs use these types of shared storage by looking for occurrences of the following EXEC CICS commands:
Although some of these commands are themselves threadsafe, they all give access to global storage areas, so the application logic that follows these commands and uses the global storage areas has the potential to be non-threadsafe. To ensure it is threadsafe, an application program must include the necessary synchronization logic to guard against concurrent update.
The load module scanner utility includes a sample table, DFHEIDTH, to help you identify whether the application logic in your existing application programs is threadsafe. DFHEIDTH contains the filter set for CICS commands that give access to shared storage. The use of these commands could make a program not threadsafe, unless it has the necessary synchronization logic in place to ensure serialization and prevent concurrent update.
Remember that DFHEIDTH, as supplied, is not testing the programs for non-threadsafe CICS commands (that is, commands that cause a switch to the QR TCB), but rather to determine if the application is using CICS commands which give rise to the possibility that the application logic could be not threadsafe. You can modify the supplied sample table to add any non-threadsafe CICS commands that you want to detect. Another sample table, DFHEIDNT, is supplied to help identify the CICS commands in your application which are non-threadsafe. For more information on using the load module scanner, see the CICS Operations and Utilities Guide.
Techniques that you can use to provide threadsafe processing when accessing a shared resource are as follows:
This technique applies to threadsafe application programs and open API task-related user exits only. A linked-to program defined as quasi-reentrant runs under the QR TCB and can take advantage of the serialization provided by CICS quasi-reentrancy. Note that even in quasi-reentrant mode, serialization is provided only for as long as the program retains control and does not wait (see Quasi-reentrant application programs for more information).
If you define a program with CONCURRENCY(THREADSAFE), all routines which are statically or dynamically called from that program (for example, Cobol routines) must also be coded to threadsafe standards.
When an EXEC CICS LINK command is used to link from one program to another, the program link stack level is incremented. However, a routine that is statically called, or dynamically called, does not involve passing through the CICS command level interface, and so does not cause the program link stack level to be incremented. With Cobol routines, for a static call, a simple branch and link is involved to an address that is resolved at linkedit time. For a dynamic call, although there is a program definition involved, this is required only to allow Language Environment to load the program. After that, a simple branch and link is executed. So when a routine is called by either of these methods, CICS does not regard this as a change of program. The program that called the routine is still considered to be executing, and so the program definition for that program is still considered to be the current one.
If the program definition for the calling program states CONCURRENCY(THREADSAFE), the called routine must also comply with this specification. Programs with the CONCURRENCY(THREADSAFE) attribute remain on an open TCB when they return from a DB2 call, and this is not appropriate for a program that is not threadsafe. For example, consider the situation where the initial program of a transaction, program A, issues a dynamic call to program B, which is a Cobol routine. Because the CICS command level interface was not involved, CICS is unaware of the call to program B, and considers the current program to be program A. Program B issues a DB2 call. On return from the DB2 call, CICS needs to determine whether the program can remain on the open TCB, or whether the program has to switch back to the QR TCB to ensure threadsafe processing. To do this, CICS examines the CONCURRENCY attribute of what it considers to be the current program, which is program A. If program A is defined as CONCURRENCY(THREADSAFE), then CICS allows processing to continue on the open TCB. In fact program B is executing, so if processing is to continue safely, program B must be coded to threadsafe standards.
OPENAPI programs (that is, those defined in the resource definition with the OPENAPI attribute) are invoked on an open L8 or L9 mode TCB (depending on the EXECKEY attribute) instead of the main CICS QR TCB.
An OPENAPI program, although freed from the constraints imposed by the QR TCB, nevertheless does have obligations both to the CICS system as a whole and to future users of the L8 or L9 TCB it is using. An L8 or L9 TCB is dedicated for use by the CICS task to which it is allocated, but once the CICS task has completed, the TCB is returned to the dispatcher-managed pool of such TCBs, provided it is still in a "clean " state. (An unclean TCB in this context means that the task using the L8 or L9 mode TCB suffered an unhandled abend in an OPENAPI program. It does not mean that the program has broken the threadsafe restrictions, which CICS would not detect.) Note that the TCB is not dedicated for use by a particular OPENAPI program, but is used by all OPENAPI programs and OPENAPI TRUEs invoked by the CICS task to which the L8 mode TCB is allocated. Also, if an application program invoking an OPENAPI program is coded to threadsafe standards, and defined to CICS as threadsafe, it continues to execute on the L8 mode TCB on return from the program.
An OPENAPI program must not treat the executing open TCB environment in such a way that it causes problems for:
At your own risk, if your OPENAPI program decides to use other (non CICS) APIs, you must be aware of the following:
If you are running applications with programs defined as threadsafe to exploit OTE (for example, in CICS DB2 applications) problems could occur that indicate that one or more programs is not actually threadsafe. If this happens, you can force all your applications programs on to the QR TCB using the FORCEQR system initialization parameter. This could be particularly useful in a production region, where you cannot afford to have applications out of service while you investigate the problem.
The default for this parameter is FORCEQR=NO, which means that CICS honors the CONCURRENCY attribute on your program resource definitions. As a temporary measure, while you investigate and resolve problems connected with threadsafe-defined programs, you can set FORCEQR=YES. Remember to change this back to FORCEQR=NO when you are ready for your programs to resume use of open TCBs under the OTE.
There is nothing to prevent non-reentrant application programs being executed by CICS. However, such an application program would not provide consistent results in a multi-threading environment.
To use non-reentrant application programs, or tables or control blocks that are modifiable by the execution of associated application programs, specify the RELOAD(YES) option on their resource definition. RELOAD(YES) results in a fresh copy of the program or module being loaded into storage for each request. This option ensures that multithreading tasks that access a non- reentrant program or table each work from their own copy of the program, and are unaffected by changes made to another version of the program by other concurrent tasks running in the CICS region.
For information about RELOAD(YES), see the CICS Resource Definition Guide.
CICS/ESA loads any program link-edited with the RENT attributes into a CICS read-only dynamic storage area (DSA). CICS uses the RDSA for RMODE(24) programs, and the ERDSA for RMODE(ANY) programs.By default, the storage for these DSAs is allocated from read-only key-0 protected storage, protecting any modules loaded into them from all except programs running in key-zero or supervisor state.(If CICS initializes with the RENTPGM=NOPROTECT system initialization parameter, it does not use read-only key-0 storage, and use CICS-key storage instead.)
If you want to execute a non-reentrant program or module, it must be loaded into a non-read-only DSA. The SDSA and ESDSA are user-key storage areas for non-reentrant user-key programs and modules.
For more information about CICS DSAs, refer to the CICS System Definition Guide.
[[ Contents Previous Page | Next Page Index ]]