TSO/E CONTROL BLOCKS, AND MORE By Sam Golob and Courtney Taylor -- --- ----- --- -------- ------ (c) 2008 by Sam Golob Sam Golob MVS Systems Programmer P.O. Box 906 Tallman, New York 10982 Sam Golob is a Senior Systems Programmer. He also participates in library tours and book signings with his wife, author Courtney Taylor. Sam can be contacted at sbgolob@cbttape.org and/or sbgolob@cbttape.org. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IBM owns the z/OS operating system. Therefore, IBM can take liberties in the way they design and write programs for z/OS (and MVS in general) which we, as outsiders, can't get away with. In a way, this is good for us as MVS administrators. We'll explain. We often see the word "control blocks" mentioned, when it comes to MVS system coding. What IBM does, to create control blocks, is that at system initialization time, MVS obtains lots of pieces of common storage (accessible by all address spaces) which it loads with values that are used and modified by the system programs. Rather than keeping constants that are used by the system programs within the programs themselves (the way WE do when WE code), MVS's programs are usually made to reference constants, values, and bit settings that are EXTERNAL TO THEMSELVES. These values reside instead, in certain blocks of common storage that remain accessible at all times, through paths that are documented and well known. These related areas of storage containing the quantities needed by the system, are thus called "control blocks". Control blocks are related blocks of storage containing quantities that are used to control the system and the system's programs. Again, the reason why we need control blocks, is to contain common values and bit settings that are EXTERNAL TO THE SYSTEM PROGRAMS but which control and manipulate them. The layouts of most control blocks in MVS (read z/OS or whatever your flavor of MVS is) are described by pieces of source code called MACROS, and you can see what's in the publicly known IBM macros by looking at the "System Data Areas" books for your release of MVS. Or you can find most of the macros, in machine-readable form, in either of the SYS1.MACLIB or SYS1.MODGEN pds'es that reside on your system. But the important facts for us to know, regarding any control block, are two things. One, is the path through system storage on which to go, in order to reach that particular contol block itself. And two, is the layout of the data in that control block. In other words, we first have to GET THERE, and then once we're there, we have to know WHAT DATA IS THERE. Knowing all this, we can now get around to saying why it's an advantage for us, as MVS administrators, to have the significant MVS-controlled values BEING EXTERNAL to the programs which control them. The reason is that most often, THE ACTUAL VALUES are the most important things for us to know, rather than the details of the programming which manipulates them. Practically speaking, we find that we don't really care too much how the programs manipulate the values. We just care WHAT THE VALUES ARE. So IBM can change the programming in a specific system program, but if it doesn't affect how a control block value is used, we don't really care. Therefore, this takes the worry of the system's programming code away from us. We just want to follow the significant system VALUES. The way they are used and controlled by the programs, doesn't usually affect us too much. A REAL-WORLD EXAMPLE Let us show you a good example about how this works. The TSO/E TRANSMIT (or XMIT) command converts a complex dataset such as a pds (a partitioned dataset) into a simple FB (fixed blocked) sequential dataset with LRECL (record length) equal to 80. The reason for the conversion is so the dataset may be transmitted over NJE lines to another system, and once there, it is reconverted back to its original form by a TSO/E RECEIVE command running on the destination system. When IBM designed this method of data transmission, they wanted the installation to control the size of datasets which could be so transmitted over their existing lines. If one dataset was too large, the line would be tied up while that dataset was going through, and no other transmissions would be able to take place for a while. Anyone who has ever administered a set of transmission lines, is very familiar with this scenario. So IBM has provided a place in PARMLIB, in the IKJTSOxx member, where the maximum number of output lines from an XMIT command can be controlled. This is a "system-wide", global value. This value is placed into the system in any of three ways: At IPL time, the system initialization processes read the IKJTSOxx member and create a control block (called the INMXPARM control block) that contains this limiting value in one of its fields. Or, after IPL time, either a PARMLIB UPDATE(xx) TSO command is issued to re-create the INMXPARM control block in common storage from the new values in the (same or a different) PARMLIB member. Or, a SET IKJTSO=xx operator command gets issued by an operator, which has that same effect. The net result is that the outlimit value in the INMXPARM control block will cut off the creation of the FB-80 sequential dataset in the middle, if its length exceeds that cutoff value. Originally, there were no exceptions. But there is a problem with this setup. The XMIT command has an optional parameter called OUTDSN(your.dataset.name) that causes the reformatting of the initial dataset into the new sequential dataset called 'your.dataset.name', which is in FB-80 sequential format, but it doesn't actually transmit that reformatted data anywhere. It just places the reformatted data into dataset 'your.dataset.name' on the same MVS system. Thus, if the OUTDSN keyword is used in an XMIT command, NO TRANSMISSION OVER DATA LINES ACTUALLY OCCURS. Therefore we might ask the question: Why should we impose an artificial limit on that data, if it isn't going to clog any transmission lines? Until z/OS 1.9 where it seems this problem was addressed by IBM, we either had to increase the outlimit value by doing a PARMLIB UPDATE(xx) TSO command or a SET IKJTSO=xx operator command. After z/OS 1.9, it seems that when OUTDSN(your.dataset.name) is coded in an XMIT command, and the output dataset is larger than the limit, that XMIT command is nevertheless allowed to continue past the limit, to its completion. By the way, I myself have addressed this problem to deal with that situation in an unobtrusive way. I wrote two TSO commands, which can be found on either the CBT page or the Updates page of www.cbttape.org as File 731. The first command, called INMXD, will display the current settings in the INMXPARM control block that is on your system. The second command, called CINMX, which has to run APF-authorized, can change three of the quantities in the INMXPARM control block. CINMX nnnnn will reset the outlimit value for the XMIT command. CINMX W nnnnn will reset the Warn Threshold value for the XMIT command. And CINMX I nnnnn will reset the Warn Interval value for the XMIT command. Thus, if you have authority to run the CINMX command (and of course, if you have installed it on the system), you can adjust these values in the existing active INMXPARM control block, without having to make any PARMLIB changes. But after z/OS 1.9, if all you want to do is to reformat your dataset with the OUTDSN( ) keyword of the XMIT command, you probably won't need these commands to perform any circumventions of the existing values. Anyway, the net result of all this, is that we've shown you one thing: We don't care how the XMIT command is really programmed. We just care about what its limiting value is set to. And this shows us, in one easy lesson, how important the "control block" design is for MVS. The control block design simplifies MVS administration for us, by lessening the requirement for us to know about the details of MVS internal code. MORE ABOUT TSO CONTROL BLOCKS Now we'd like to talk about how to get to TSO/E control blocks in general. There is a lot of history involved here, but we can get a quick start by first talking about modern MVS systems (recent z/OS releases), and how things with TSO work there. The starting point for MVS control block searches is almost always the CVT (Communication Vector Table) that is described by the CVT macro in SYS1.MACLIB on your system. All programs can get to the CVT by pointing at the address location at virtual address X'10' or decimal 16 from the beginning of low storage. An alternative pointer to the CVT, not known by many people, is located at virtual address X'4C'. At X'9C' off the beginning of the CVT is a pointer to the TSVT or TSO Vector Table. That's where we start to look for TSO information. Because we want to limit our discussion of TSO control blocks to those created by the IKJTSOxx PARMLIB member, we have to say that most of those control blocks are pointed to by the TPVT (TSO Parmlib Vector Table) control block whose address is at X'4C' off the beginning of the TSVT. The TPVT control block is not documented officially by IBM, so we have to construct our own map of it. Please see Figure 1, which contains our map of the TPVT. If you'll take a look at the z/OS Initialization and Tuning Reference (SA22-7592) and look at the IKJTSOxx member documentation, you'll see various settings. Each of these settings determines a control block location in Common Storage (mostly above the 16M line). The various settings are: ALLOCATE, AUTHCMD, AUTHPGM, AUTHTSF, HELP, NOTBKGND, CONSOLE, PLATCMD, PLATPGM, TEST, TRANSREC, and SEND. See Figure 2, which will show you the locations of these control blocks, starting off the beginning of the TPVT, which are created from these respective IKJTSOxx settings. USING THE "LOOK" FREE TSO COMMAND AS AN AID TO EXPLORE Because of lack of space here, we are going to leave it to your own initiative, to explore your own system. But before doing so, we'll give you a good tool to do that with. The tool is called LOOK, and it is a full screen TSO command. LOOK is absolutely free, and it is found on File 264 of the CBT Tape collection of free MVS programs and tools (www.cbttape.org). Instead of first looking at the CBT section of www.cbttape.org, I'd suggest that you try the Updates section of www.cbttape.org first, to see if there's a newer version of File 264 there. The LOOK program is a full screen core browser that contains tools to make it easy to follow a chain of control blocks. Now we'll show you how. The subcommand of LOOK which does that, is called "J". If you say Jnnnnnnnn, where nnnnnnnn is an address in 32-bit virtual storage, LOOK will display the storage pointed to in that address, and all addresses for 256 bytes further, on a full screen. If you are at a certain storage location, and you say J+xx where xx is a Hex number, LOOK will display the storage pointed to by the location at xx OFF OF the current location. This is the equivalent of a LOAD instruction in Assembler Language. If you want to go further in storage (the equivalent of a LOAD ADDRESS instruction roughly), just use a "+". Thus, to display X'432' bytes in storage further, you just say +432 in the LOOK subcommand area at the top of the screen. And you can use a minus or "-" to similarly go backward in storage from the current location. We can illustrate how LOOK works by referencing Figure 2. Suppose we want to look at the AUTHCMD table IKJEFTE2 in storage. First we get to the CVT by saying J10. Remember that virtual X'10' contains the address of the location of the CVT. Then we say J+9C to point to the TSVT (TSO Vector Table). Then we say J+14 to point to the CTLT table. Then we say J+8 to point to the IKJEFTE2 table. That's ALMOST all that there is. To go back to the previous screen, we say PF9. One more thing. LOOK also has a built-in HELP facility which you can access by pressing PF1 and you exit by pressing PF9. Knowing this much, you can already invoke LOOK and start searching through control blocks by yourself. But not so fast. There is at least one more thing to explain, and we'll tell you what it is. Besides displaying the raw data in control blocks, LOOK can also FORMAT control blocks as it displays them. See Figure 3 for an example of a formatted control block, and see Figure 4 for how LOOK displays the same data, unformatted. How does the formatting work? Actually it works quite cleverly. And the formatted layout, set up according to the fields described by each control block's own mapping macro, is created directly from the macro itself. A separate CSECT called CBMACS is assembled using all the real macro layouts, and CBMACS is linkedited together with the LOOK load module. If the control block exhibits a telltale sign that CBMACS "knows about", a formatted pattern will appear on the full LOOK screen automatically instead of just a raw storage dump. Again, see Figure 3 to see a formatted control block, and Figure 4, to see the same data, unformatted. If you use LOOK to navigate through a formatted control block display, then you use a command called "L" instead of the command called "J". I'll show you an easy example. When you say J10 to point LOOK to the CVT, LOOK will automatically format the CVT. In a formatted version of the CVT, the pointer to the TSVT is called "TVT". So, from the formatted CVT screen, you can get to the TSO Vector Table by saying the subcommand LTVT. The TSVT control block, in turn, is also formatted. So you can get to the TPVT control block from there, by simply saying LTPVT. This is simple, once you get the hang of it. There is one more caveat to using LOOK, this one being of very recent origin. This situation came up with z/OS 1.8 originally, and it is critical to know about when you are running MVS at the z/OS 1.9 level. It just so happens that LOOK will allocate common storage in Key 8, which is a user storage key. Starting from z/OS 1.8 and onward, an installation can prohibit common storage allocation in a User Key by coding VSM ALLOWUSERKEYCSA(NO) in the active DIAGxx member of PARMLIB, and by issuing a SET DIAG=xx operator command for a DIAGxx member where VSM ALLOWUSERKEYCSA(NO) is coded. At the z/OS 1.9 level, VSM ALLOWUSERKEYCSA(NO) is the default setting. But for LOOK to work on z/OS 1.9, that has to be reversed by coding a (YES) setting of the same parameter. Doing that isn't exactly the safest thing to do, especially in a commercially active installation, since Key 8 storage can be changed by anyone. We DO have a solution to this situation. I have coded an APF-authorized TSO command which turns this "allow Key 8 storage in CSA" setting ON, or OFF, and you can change the setting for a short time. My program is called UKEYCSA, and it can also be found on a (recent) copy of CBT Tape File 264 (see the Updates page at www.cbttape.org). So, if you are using LOOK to view storage in a "sandbox MVS environment" such as a test system, where it is safe to code VSM ALLOWUSERKEYCSA(YES) in the DIAGxx member of PARMLIB, all is well and good, and you can use LOOK as is. But if you have to code (NO), or when you're using the z/OS 1.9 default, and then you try to use LOOK, you'll get a SB0A, reason code 5C abend. So to remedy the situation on the fly, we have written an APF-authorized TSO command, found in CBT Tape File 264 together with LOOK, called UKEYCSA, which can turn the allowance of User Key allocation in CSA on or off on the fly. UKEYCSA Y allows User Key allocation in CSA, and UKEYCSA N turns it off. This way, you can use LOOK for a few minutes, even if VSM ALLOWUSERKEYCSA(NO) is the default in your installation. But you need to have the authority to run the APF-authorized TSO command UKEYCSA, in order to do this for yourself. And you're exposing the installation to a remote possibility of risk for short intervals at a time, when you do this. But it's certainly much safer to use the UKEYCSA program for a short interval of time, rather than allowing User Key allocation of common storage ALL of the time. Caveats aside, LOOK is a marvelous tool to look at (and trace) common storage control blocks in (nearly) real time. And you can learn a ton of system information if you use the LOOK command often. This includes learning about all of the TSO-related control blocks mentioned here. SUMMARY We hope that this article will open your eyes to exploring your MVS (read z/OS or OS/390 etc.) system further. It's true that whenever a system control block can be changed by a PARMLIB setting and a SET command, all of its controlling values are present in common storage somewhere. These values are always accessed by following a documented path, as you step through control block pointers, usually starting from the CVT. TSO/E control blocks that were created by the IKJTSOxx PARMLIB member, are no exception, as we have shown here in Figure 2. Figure 2 completely documents the control block pointers whose origin comes from the IKJTSOxx PARMLIB member. To graphically illustrate the specific principles outlined here, we've provided you with a free "core browsing" tool called "LOOK", which is obtained from the CBT Tape collection (www.cbttape.org - Updates page or CBT page), File 264. LOOK will graphically show you in fullscreen, the contents of much of the control block information in your system. So besides the specific knowledge we've conveyed about the TSO-specific control blocks on your system, we've also opened the way for you to discover much more. We wish all of you the best of everything personally, and we hope that you will gain a lot of knowledge and "MVS street smarts", as you continue to safely explore your MVS system, well into the future. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Figure 1. Layout of the TPVT control block, figured out by experiment. MACRO IKJTPVT TPVT DSECT TSO PARMLIB vector table TPVT_ID DS C'TPVT' BLOCK ID TPVT_LEN DS H'72' LENGTH OF TPVT (OLD TPVT FORMAT) **** DS H'220' LENGTH OF TPVT HTE26E2 TPVT_VERS DS FL1'2' VERSION TPVT_MEM1 DS 0C'IKJTSO00' 07 (OLD TPVT FORMAT) HTE25E2 DS X HTE26E2 TPVT_MEM DS C'IKJTSO00' 08 ACTIVE PARMLIB MEMBER HTE26E2 TPVT_GEN DS F PARMLIB generation count TPVTCTLT DS A(CTLT) 14 IKJCTLT (Auth tables) TPVTCTLT_LEN DS F'60' length of CTLT DS 4X TPVTSEND DS V(SCB) 20 IKJEESCB (SYS1.BRODCAST) TPVTALPL DS V(ALPL) 24 ALPL (ALLOCATE defaults) TPVTTEST DS V(TPT) 28 TPT (TEST) TPVTXPRMD DS V(XPRM) 2C INMXPARM (XMIT) TPVTCONSOLE DS V(CNPRM) 30 IKJCNPRM (CONSOLE) TPVTFCVEC DS A,F 34 FCVE (Platform commands) TPVTHELP DS V(HCB) 3C IKJEFHCB (HELP) TPVTPPVEC DS A,F 40 PPVE (Platform programs) ORG TPVT+X'50' TPVTDSNAM DS CL44'SYS1.PARMLIB' 50 dsname HTE26E2 TPVTVOLSER DS C'SYSCAT' 7C volser HTE26E2 DS 2X HTE26E2 TPVTSNAME DS CL8'P390' 84 from system HTE26E2 TPVTUSERID DS CL8'**IPL**' 8C by userid HTE26E2 TPVTHHMMSS DS CL8'16:59:56' 94 at hh:mm:ss HTE26E2 TPVTYYMMDD DS C'1998-10-29' 9C on yyyy-mm-dd HTE26E2 DS X'0600,00000001,7490,16595156,19981029' HTE26E2 ORG TPVT+X'DC' end of TPVT HTE26E2 MEND - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Figure 2. Locations of the Control Blocks created by the IKJTSOxx PARMLIB member. Starting reference is the TPVT control block, pointed to at +X'4C' off the beginning of the IKJTSVT (TSO Vector Table) control block. The location of the TSVT control block is at +X'9C' off the beginning of the CVT. The CVT is pointed to, at virtual location X'10' or decimal 16. ALLOCATE - X'24' points to ALPL control block. AUTHCMD - X'14' goes to CTLT. X'8' off CTLT gets IKJEFTE2 table. AUTHPGM - X'14' goes to CTLT. X'14' off CTLT gets IKJEFTE8 table. AUTHTSF - X'14' goes to CTLT. X'2C' off CTLT gets IKJEFTAP table. HELP - X'3C' points to IKJEFHCB control block. NOTBKGND - X'14' goes to CTLT. X'20' off CTLT gets IKJEFTNS table. CONSOLE - X'30' points to IKJCNPRM control block. PLATCMD - X'34' points to FCVE if it exists, if not, X'00000000'. PLATPGM - X'40' points to PPVE if it exists, if not, X'00000000'. TEST - X'28' points to TPT. TRANSREC - X'2C' points to INMXPARM control block. SEND - X'20' points to IKJEESCB control block. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Figure 3. A formatted LOOK screen with the fields and their contents laid out. The IKJTSVT (TSO Vector Table) control block is laid out, according to the fields in the mapping macro IKJTSVT. LOOK COMMAND - DISPLAY VIRTUAL MEMORY DISPLAY ASID= 004C ENTER CMD - LAST CMD - J+4C 00CB0140 TSVT TSVT TSVT LEV . FLG1 NCT 11779158 VACC 00CE0A4E ASF 00CCD1E0 LTBL 00D95B30 FLA1 83E19000 CTIO 80D9A000 CTAB 83E15030 T440 83EA16AE T441 83EBB910 PUTL 83EB2028 PTGT 83EB2F18 GETL 83EB651E STCK 83EAD220 TSL 80CD0990 SCAN 83EC1000 PARS 83E80000 EF02 83E72000 TPVT 117A16D0 RCVY 84A829B0 TRAN 83EC3000 BCMT ...B.... CAF 83E463D8 LVER 3 LREL 08 LMOD 0 CTDB 83273B88 RIF 83269370 RAF 83E3C000 RTRP 83EBE000 TBLS 00CE0A30 ADTB 83680EB8 TBLR 83EDED20 ESTK 84074E98 TVAR 840C55E8 INIT 84090910 OLAR 80D7E000 TO00 840C0000 T44X 83EA0CC8 FTS2 83E41000 EXE 8408D4E8 INOU 8408F8D8 LOA 8408FCB0 TER 840BB7B0 SUBC 8408DE28 MSGI 840A81D0 EXCO 8408E1F8 TERM 840A5B90 ETVP 00C9BAD0 TSFI 83E3F000 TSFT 82B0A868 PCN1 00001A00 SNTA 1197A490 SVTA 1197AE48 SYML 00000B70 XCFU 00000000 MSTR 00FDC400 BECB 808E8068 APPC 82886A40 URPS 83EC5000 PCN2 00001A01 MSR0 83E74000 MDT@ 8319F718 1= HELP 2= 3= END 4= 5= REPEAT 6= 7= BACKWARD 8= FORWARD 9= HIST BWD 10= HIST FWD 11= 12= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Figure 4. The unformatted data on a LOOK screen, which is the same data as on the formatted screen shown in Figure 3. This is the very same IKJTSVT control block data. To turn off formatting, we enter the command ONULL. To turn on formatting according to a particular control block, we enter the command "O" joined to the name of the control block, such as OTSVT. LOOK COMMAND - DISPLAY VIRTUAL MEMORY DISPLAY ASID= 004C ENTER CMD - LAST CMD - ONULL 00CB0140 >E3E2E5E3 07400000 11779158 00CE0A4E *>TSVT. ....j....+* 00CB0150 00CCD1E0 00D95B30 83E19000 80D9A000 *..J..R$.c....R..* 00CB0160 83E15030 83EA16AE 83EBB910 83EB2028 *c.&.c...c...c...* 00CB0170 83EB2F18 83EB651E 83EAD220 80CD0990 *c...c...c.K.....* 00CB0180 83EC1000 83E80000 83E72000 117A16D0 *c...cY..cX...:..* 00CB0190 84A829B0 83EC3000 010000C2 00070001 *dy..c......B....* 00CB01A0 83E463D8 F3F0F8F0 83273B88 83269370 *cU.Q3080c..hc.l.* 00CB01B0 83E3C000 83EBE000 00CE0A30 83680EB8 *cT..c.......c...* 00CB01C0 83EDED20 84074E98 840C55E8 84090910 *c...d.+qd..Yd...* 00CB01D0 80D7E000 840C0000 83EA0CC8 83E41000 *.P..d...c..HcU..* 00CB01E0 8408D4E8 8408F8D8 8408FCB0 840BB7B0 *d.MYd.8Qd...d...* 00CB01F0 8408DE28 840A81D0 8408E1F8 840A5B90 *d...d.a.d..8d.$.* 00CB0200 00C9BAD0 83E3F000 82B0A868 00001A00 *.I..cT0.b.y.....* 00CB0210 1197A490 1197AE48 00000B70 00000000 *.pu..p..........* 00CB0220 00FDC400 808E8068 82886A40 83EC5000 *..D.....bh. c.&.* 00CB0230 00001A01 83E74000 8319F718 40000000 *....cX .c.7. ...* 1= HELP 2= 3= END 4= 5= REPEAT 6= 7= BACKWARD 8= FORWARD 9= HIST BWD 10= HIST FWD 11= 12=