Warning: Be sure to return the test CICS to its original condition by removing transaction class definitions and program threadsafe definitions.
Before comparing the two sets of results, verify that the number of DB2 calls is roughly the same in both runs. If the number of DB2 calls is different, that’s an indication the before and after runs were different and calls the test results into question.
The key metric is to find the ratio of TCB switches to DB2 calls in the form of TCB switches/2: DB2 calls. A ratio near one indicates that no actual savings was found, as either the test was performed incorrectly or the programs have non-threadsafe commands after almost every DB2 call. A ratio near zero indicates this is the ideal candidate; a threadsafe conversion will result in your actual savings coming very close to your potential savings.
A ratio greater than one indicates that non-threadsafe exits are active in the region. Under no circumstances should you start a threadsafe conversion in an environment where non-threadsafe exits are found. Use the IBM-supplied STAT transaction (program DFH0STAT) with the DB2, user exit and global user exit options selected to produce a complete list of all exits active in the region along with their threadsafe status. If a user exit program supplied by a vendor is defined as QUASIRENT, contact the vendor for an updated version of the exit program; if a threadsafe version of the exit program isn’t available from the vendor, it may indicate that the vendor has, for all practical purposes, stopped supporting the product in question. If a user exit program developed in-house is marked as QUASIRENT, you must convert it to threadsafe before implementing any threadsafe programs into production. Be careful when reviewing user exit programs, as the nature of the exit program environment lends itself to non-threadsafe programming.
Identifying Non-Threadsafe Application or System Code
After identifying the programs that will produce the greatest CPU savings, the next step is to determine if these programs are already threadsafe, or if a threadsafe conversion will be required. Unfortunately, there’s no automated method to prove code is threadsafe, partly because it can be difficult to tell if a given field is in shared storage, and partly because whether access to shared storage is threadsafe depends on how the storage is used.
Begin a threadsafe review by running the IBM load module scanner, DFHEISUP, with the IBM-supplied filter set of DFHEIDTH against the load library containing the programs in question. (Note: Documentation on the use of DFHEISUP is found in the CICS Operations and Utilities manual; the filter set, DFHEIDTH, is found in the SDFHSAMP library.) DFHEISUP will scan the load modules, looking for the EXEC CICS commands listed in the DFHEIDTH table: EXTRACT EXIT, GETMAIN SHARED and ADDRESS CWA. These three commands aren’t the only ways to acquire access to shared storage, but they’re the most common. Any program flagged by DFHEISUP as issuing these commands must be manually reviewed to determine what use is made of the shared area(s).
Figure 2 shows an example of non-threadsafe use of the CICS common work area (CWA.) In this case, a field in the CWA is used as a counter to generate a unique field in a key sequenced data set (KSDS). When program PROG001 builds the key, it copies the current value of 0001 from the CWA to its key field in working storage, increments the counter in CWA by one and writes the record out. This processing isn’t threadsafe because it relies on the CWA counter field remaining unchanged during the period between extracting the current value and updating the counter to its new value.
The result of incorrectly defining program PROG001 as threadsafe while it contains this non-threadsafe routine is shown in Figure 3. In this case, two tasks (TASK1 and TASK2) are running PROG001 simultaneously. TASK1’s PROG001 starts the process by copying the current value of 0001 from the CWA to its key field in working storage. At the same time, TASK2’s PROG001 also copies the value of 0001 to its key field in its working storage. TASK1’s PROG001 then increments the counter in CWA by one to 0002; TASK2’s PROG001 also increments the counter by one—from 0002 to 0003. TASK1 then writes out its KSDS record and continues normally. When TASK2 attempts to write out its record, the key isn’t unique, and the write receives a DUPREC error condition. Since it’s “impossible” for a key not to be unique (after all, that’s what the CWA counter is used for—generating unique key values), it’s likely there’s no special program code to handle the DUPREC condition, and TASK2 fails with a condition that simply can’t occur. Worse, when nightly batch is run, there’s a “missing” record on the KSDS because the counter “jumped” from one to three, and the batch job also fails with an “impossible” condition.