The Evolution of CICS: CICS and Multiprocessor Exploitation (2004)

Note: The following text was originally written as an article included in a CICS Newsletter dated January 6, 2004. The objectives for the article were to explain considerations for CICS exploitation of multiprocessor machines and what would be required of CICS applications in order to be dispatched under separate operating system tasks to gain the benefit of such concurrency.

In the early days of CICS (1968-1980) CICS Development determined that hardware and operating systems of the period were limited in terms of the cycles and storage needed to support high volume, online, real time transaction processing. CICS devised its own facilities for task dispatching, storage management and program management which demonstrated greater efficiencies than using native operating system facilities for similar functions.

CICS chose to provide for a multi-tasking environment under a single Task Control Block (TCB) using its own dispatcher (Task Control Program) rather than attempt to multi-task concurrent transaction processing using operating system subtasks. Not only was the overhead of operating system subtasking considered excessive, but having concurrently dispatched applications would have required programs to be reentrant and serialize their use of shared resources. That was felt to be too complicated at the time.

As mainframe hardware and operating system technologies advanced, users of CICS began to question why CICS did not provide that applications in the same region could be dispatched under separate TCBs thereby enabling the CICS workload to be dispatched concurrently on multiple processors within the same machine. Users felt that by this form of multi-tasking system thruput would increase and newly introduced multi-processor hardware would be better utilized.

In the 1980s, CICS began to perform certain functions under separate TCBs however the bulk of CPU utilization in a CICS region was still attributed to application code and not the ancillary functions such as Open/Close, RACF processing, etc. The primary customer interest was having user and/or vendor application code dispatched under separate TCBs.

In 1980 CICS introduced its support for Multi-Region Operation (MRO). MRO was quickly adopted by users because it offered a number of potential advantages. By separating terminal management from application execution, application regions could be started and/or stopped independently, normally or abnormally, without disrupting support for the terminal network and other regions. Adopting a file owning region enabled multiple application regions to share common data with integrity.

An MRO configuration also contributed to better multiprocessor utilization by distributing the CICS workload over some number of regions. Multiple applications could be dispatched concurrently on separate processors. However, this did not enable multiple instances of the same application to be concurrently dispatched because of the concern for sharing resources with integrity.

To better understand the requirement for concurrency and multitasking, one must understand the need that applications be compiled as being pure reentrant and the need for applications to serialize their use of common resources. Until CICS Transaction Server Version 2.2 there had never been a requirement that users (and software vendors of CICS-related products) conform to the rules of reentrancy and resource sharing for application and data integrity.

Let's examine why reentrancy and resource sharing with integrity are absolutely necessary in order for multiple instances of the same application, or simply multiple instances of applications sharing common resources, to be dispatched under separate TCBs in the same machine.

First, reentrancy. To achieve the objective, an application should be compiled as being pure reentrant. This means that the application does not modify itself during execution. Additionally, it would be wise to place applications in protected storage to further insure that they do not modify themselves or are modified by other programs.

There is a reason for the reentrancy requirement. Consider an application which might be initiated by multiple users at virtually the same time. If the application was dispatched on behalf of User A and some computation within the application modified the program in storage, it's possible that incorrect processing might occur. If User B initiated the same application and it is dispatched under a separate TCB, that instance of the application may compute a different value and store it within the program, thereby replacing User A's computed value. You cannot have two or more instances of the same code modifying that code oblivious to other potential concurrent users of the same application.

The second concern for achieving the objective of multiprocessing is that multiple instances of the same application or multiple applications that manipulate common resources must serialize their use of those resources.

Consider a simple example. If two or more instances of the same application were dispatched concurrently under separate TCBs in the same CICS region, and the application manipulated a common resource, for instance a data field in the CICS Common Work Area (CWA), like the reentrancy example given earlier, unpredictable results may occur.

If User A obtained data from a CWA field and began to process based on the data value, User B, being concurrently dispatched might also obtain the CWA data, modify it and store it back into the CWA. Later User A's instance may update and store its value in the CWA field, resulting in User B's computation being lost.

There are many other examples of concurrently executing applications having the potential of causing system, application and/or data errors, because they did not serialize their use of common shared resources. Much like the CWA example, the same potential problem may occur using data fields within a shared GETMAIN area. The area can be shared, but this by itself does not insure integrity.

The concern is not only for potentially concurrent updates of a common data field, but read integrity as well. A task may wish to have a "shared lock" on some read-only data, allowing other tasks to read the same data but preventing other instances of the application or other applications from updating the shared resource until the lock owner was done with the resource.

Still another example might be the use of data contained in a load module loaded into the CICS region and shared by multiple applications. Whether the CWA, shared storage or a shared load module, in order to insure integrity and correct processing by concurrently executing applications, the applications must serialize their use of such resources.

Certain CICS commands that manipulate common resources will insure that only one dispatched application will have access to the resource at one time. These commands are listed in the CICS Application Programming Reference manual, Appendix L. Use of other CICS commands which do not insure serialized use of a resource must be executed under CICS' Quasi-Reentrant (QR) TCB.

The user's applications are responsible for serializing their use of shared resources. The most common technique is through the use of enqueue/dequeue. In the case of the CWA data field example, all applications could agree to enqueue on the field name or address, to gain use of the data, and dequeue off the resource when the processing (update) of that data is complete.

The customer should evaluate all user application code, vendor application code, user exit programs, PLT modules, etc, for conformance to the rules for concurrent dispatch. That is, all code should be compiled as being pure reentrant (RENT) and insure that shared resource usage is serialized.

CICS provides a utility program (DFHEISUP) to offer some assistance in determining conformance. The utility will test program load modules based on the content of DFHEIDTH to determine if any CICS commands are being used for which multiple instances cannot be used concurrently. If an application issued one of these commands, a switch would occur between the application's TCB to the QR TCB, where the command would be executed, and following that, another TCB switch would occur to return to the application's TCB. The user may wish to consider application changes to minimize TCB switching.

Unfortunately, much of the responsibility for insuring resource serialization falls on the user. The CICS Interdependency Analyzer might be of some help, in that it can assist the user in determining resource usage. That is, which transactions use which programs which might use particular resources (files, queues, maps, etc). Even so, this is not a complete assessment of resource sharing.

Some transactions may have complex design in which sharing may not easily be seen. For instance, a transaction may initiate an initial program and it in turn may call other programs or cause exits to be executed. A data resource might be enqueued upon in one program, used by a second program and dequeued by a third program. Only by a detailed examination of the second program would the user be able to determine its use of a shared resource.

Beginning with CICS TS 2.2, CICS is now providing support that CICS DB2 applications can be dispatched concurrently on separate TCBs within the same region. Assume a single application. Once it issues its first DB2 SQL request it can be assigned to execute under a separate TCB. Assuming the application does not use CICS commands that do not support concurrent use, and the application is reentrant and serializes its use of shared resources, that application can continue to execute under the separate TCB.

It is important to understand that CICS has no way of knowing about resources shared by applications. If the user specifies that an application conforms to the concurrency criteria, but in fact does not, the application would execute under the application's TCB, possibly creating a situation where system, application or data integrity is violated. It is a user responsibility to insure concurrency criteria is met.

If the CICS DB2 application uses a CICS command which does not support concurrency, control is passed back to the CICS QR TCB for the execution of that command. If the application issues another DB2 SQL call, control is passed back to its application TCB and execution continues.

The significance of the new support in CICS TS 2.2 is three-fold. First, multiple instances of the same CICS DB2 application can be concurrently dispatched under separate TCBs for more effective use of multiprocessor machines.

Secondly, the new support can reduce TCB switching between the QR TCB and the TCB under which the application and its DB2 usage is executed, resulting in potentially significant CPU savings. For instance, with a CICS DB2 application that might issue 100 SQL calls, prior to CICS TS 2.2, that might incur 200 TCB switches. With CICS TS 2.2 or later and DB2 V6 or later, the example can be reduced to as few as two TCB switches.

Thirdly, the new support represents an architecture which may be expanded in a future CICS version or release in which non-DB2 CICS applications might also be eligible to run concurrently under separate TCBs.

CICS TS 2.2 introduced the new term "threadsafe" by which the user can now specify those programs which meet the concurrency criteria. Repeating again, a program or exit specified as being able to run concurrently should be compiled as being pure reentrant and the program serializes its update intent of shared resources. Specifying that a program is threadsafe does not make the program threadsafe. It is the user's responsibility to insure that the program meets the criteria for concurrency.

Copyright © 2004 - Yelavich Consulting, Sparks, NV
Click here for other articles regarding the evolution of CICS.