Examples
Example 10. VSMLIST - Virtual Storage Information
Virtual storage allocation information can be obtained using the VSMLIST macro. Information for allocated, free, or unallocated storage can be obtained for storage below the "bar." The routine in this example obtains information about allocated storage by subpool and by task. Additionally, information from the VSM Local Data Area is obtained.
The output from the routine is in comma delimited format. The three tables below are an example of the output with headings added for clarity.
| Subpool No. |
Total Storage |
Below Line |
Above Line |
|---|---|---|---|
| 0 | 1097728 | 8192 | 1089536 |
| 229 | 1204224 | 0 | 1204224 |
| 230 | 913408 | 81920 | 831488 |
| 236 | 163840 | 61440 | 102400 |
| 237 | 421888 | 86016 | 335872 |
| 249 | 8192 | 0 | 8192 |
| 251 | 16384 | 0 | 16384 |
| Task No. |
Task Name |
Total Storage |
Below Line | Above Line |
|---|---|---|---|---|
| 0 | IEAVAR00 | 831488 | 57344 | 774144 |
| 1 | IEFSD060 | 933888 | 90112 | 843776 |
| 2 | IEFIIC | 1429504 | 81920 | 1347584 |
| 3 | VSMLIST2 | 36864 | 8192 | 28672 |
| 4 | IEAVTSDT | 593920 | 0 | 593920 |
| Summary of Key Information from LDA (Local Data Area) |
|
|---|---|
| 6000 | Address of start of private storage area |
| 9412608 | Size of private storage area |
| 8000 | Address of current top of user region |
| 9412608 | Maximum size of user region (< 16M) |
| 8192 | Total bytes allocated to user region (< 16M) |
| 258048 | Total bytes allocated to LSQA/SWA/229/230 region (< 16M) |
| 1E800000 | Address of start of extended private storage area |
| 1635778560 | Size of extended private storage area |
| 1E90E000 | Address of current top of extended user region |
| 398458880 | Maximum Size of extended user region (>16M) |
| 1105920 | Total bytes allocated to extended user region (> 16M) |
| 12185600 | Total bytes allocated to extended LSQA/SWA/229/230 (> 16M) |
C Source
/* MVS manages storage through the use of subpools designed to accommodate a variety of storage needs. Storage is allocated or assigned to a subpool in one page (4K) multiples System Queue Area (SQA/Extended SQA) This area contains tables and queues relating to the entire system. Its contents are highly dependent on configuration and job requirements at an installation. The total amount of virtual storage and number of private virtual storage address spaces are two of the factors that affect the system's use of SQA. Local System Queue Area (LSQA/Extended LSQA) Each virtual address space has an LSQA. This area contains tables and queues associated with the user's address space. The area contains TCBs, RBs, CDEs, SPQEs, DQEs, FQEs, tables and queues associated with the user's address space. LSQA is intermixed with SWA and subpools 229, 230, and 249 downward from the bottom of the CSA into the unallocated portion of the private area, as needed. Common Service Area (CSA and Extended CSA) This area contains pageable and fixed data areas that are addressable by all active virtual storage address spaces. CSA normally contains data referenced by a number of system address spaces, enabling address spaces to communicate by referencing the same piece of CSA data. The common area contains system control programs and control blocks. This storage can be shared across address spaces within the logical partition. The following storage areas are located in the common area: The common service area is a getmainable common area containing control blocks used by subsystem programs such as JES2, DFSMS, and RACF, and access methods like VSAM. It is a sort of virtual storage reserved area for future getmains/freemains issued by such programs. This area is used for buffers for IMS, ACF-VTAM, JES. It is also used for TSO buffer sharing (TIOC), Event Notification Facility (ENF) and Message Processing Facility (MPF). Subpools 229, 230, 249 - Extended 229, 230, 249 This area allows local storage within a virtual address space to be obtained in the requestor's storage protect key. The area is used for control blocks that can be obtained only by authorized programs having appropriate storage protect keys. These control blocks were placed in storage by system components on behalf of the user. These subpools are intermixed with LSQA and SWA. Subpool 229 is fetch protected; subpools 230 and 249 are not. All three subpools are pageable. Subpools 229 and 230 are freed automatically at task termination; subpool 249 is freed automatically at jobstep task termination. Specifies the storage areas for which information is requested. The following subpools are listed for the specified storage areas: - SQA: 226, 239, 245, 247, 248 - CSA: 227, 228, 231, 241 - LSQA: 205, 215, 225, 255 - PVT: 0-127, 129–132, 229, 230, 236, 237, 244, 249, 251, 252 GETMAIN/FREEMAIN/STORAGE processing translates the original subpool numbers that were specified on the GETMAIN, FREEMAIN, or STORAGE macros to different subpool numbers as shown below: Original Translated Subpool Subpool Number Number 203-205 205 213-215 215 223-225 225 233-235, 253-255 255 0, 240, 250 0 VSMLIST reports the translated subpool numbers, not the original subpool numbers. In addition, VSMLIST does not report incorrect subpool numbers (subpool numbers greater than 255) or undefined subpool numbers. IEAVAR00 - RCT Initialization/Termination (Region Control Task) IEFSD060 - Initiator primary entry point IEFSD160 - Initiator Initialization IEFIIC - Initiator Interface IEAVTSDT - Dump Task IEESB605 - The started task control job scheduling subroutine. IEAVARxx - IEAVAXxx Region control task (RCT) of address space control IEFSDxxx - Master subsystem/subsystem interface (MSI and SSI) IEFIxxxx - Initiator/terminator IEAVTSxx - Recovery termination manager (RTM) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "ascb.h" #include "cvt.h" #include "psa.h" #include "ihadcb.h" #include "cde.h" #include "rb.h" #include "tcb.h" #include "ihalda.h" #define pageSize 4096 #ifndef __MVS__ #include#define __CSE_CURRENT_VERSION __CSE_VERSION_1 #define __CSE_VERSION_1 1 #include "env.h" __csysenv_t __cinit(struct __csysenv_s * csysenv); void __cterm(__csysenv_t csysenvtkn); #endif #ifdef __MVS__ #pragma pack(packed) #endif // Workarea used by VSMLIST struct workArea { int returnCode; char *dataArea; // Address of the data area int length; // Length of the data area char reserved[4]; char work[pageSize * 4]; } ; struct PVTSubpool { int NoOfTCBs; /* Number of TCBs in Private Area */ } ; struct LSQASubpool { int NoOfSubpools; /* Number of Subpools */ } ; struct SubpoolDescriptor { struct { unsigned char _Identifier; /* x'00' to identify a subpool descriptor */ unsigned char _Length; /* Length of subpool descriptor */ unsigned char _Id; /* Subpool Id */ struct { unsigned int _StorageKey : 4; unsigned int _owns : 1; unsigned int _shared : 1; unsigned int _reserved : 2; } Misc; void *_TCBAddr; /* Owning TCB Address if PVT subpool */ } Descriptor; int NoOfAllocBlocks; /* Number of Allocated Block in subpool */ } ; struct TCBAllocation { void *TCB; /* Address of TCB */ int NoOfSubpools; /* Number of Subpools */ } ; struct AllocatedBlockDescriptor { int BlockAddr; /* The virtual Address of the allocated block */ int BlockLength; /* The length of the allocated block */ } ; #define Identifier Descriptor._Identifier #define Length Descriptor._Length #define Id Descriptor._Id #define StorageKey Descriptor.Misc._StorageKey #define TCBAddr Descriptor._TCBAddr /* Values for field "StorageKey" */ #define TCBOwnsStorage 0x80 #define SharedStorage 0x40 #ifdef __MVS__ #pragma pack(reset) #endif struct subpool { int totalBytes; int bytesAboveLine; int bytesBelowLine; } ; struct AllocatedStorage { int numberOfTCBs; // Storage by TCB struct { char name[8]; int numberOfSubpools; int totalBytes; int bytesAboveLine; int bytesBelowLine; } TCB[256]; // Storage by Subpool int PVTSubpools; int SQASubpools; int CSASubpools; int LSQASubpools; struct subpool PVT[256]; struct subpool SQA[256]; struct subpool CSA[256]; struct subpool LSQA[256]; } ; #ifdef __MVS__ #pragma insert_asm("MODELDCB DCB DDNAME=MODELDCB,MACRF=PM,DSORG=PS,DCBE=MODELDCBE") #pragma insert_asm("MODELDCBE DCBE RMODE31=BUFF") #endif struct storage { char dcb[152]; } ; struct dcb { char ddname[8]; int lrecl; int blksize; char recfm[3]; void *storage; int size; void *currentRecord; void *token; __csysenv_t _envtkn; } ; void replace(char *name) { int i; int length; length = strlen(name) + 1; for (i = 0; i < length; i++) { if (name[i] == 0x00) { name[i] = ' '; } } } extern int init(struct dcb *_dcb) { int returnCode; returnCode = 0; #ifdef __MVS__ struct __csysenv_s _sysenv; /* The __cinit() function establishes a Metal C environment based on the characteristics in the input csysenv structure.*/ // Initialize the csysenv structure. memset(&_sysenv, 0x0, sizeof(_sysenv)); _sysenv.__cseversion = __CSE_VERSION_1; // Set heap initial and increment sizes. _sysenv.__cseheap31initsize = 65536; _sysenv.__cseheap31incrsize = 8192; _sysenv.__cseheap64initsize = 20; _sysenv.__cseheap64incrsize = 1; // Create a Metal C environment. */ _dcb->_envtkn = __cinit(&_sysenv); #endif #ifdef __MVS__ __asm(" ST 15,%0 " : "=m"(_dcb->token) : : "r0", "r1", "r14", "r15"); #endif return returnCode; } extern int term(struct dcb *_dcb) { int returnCode; int storageSize; void *storagePtr; returnCode = 0; storageSize = _dcb->size; storagePtr = _dcb->storage; #ifdef __MVS__ __asm( (" STORAGE RELEASE" ",LENGTH=(%0)" ",ADDR=(%1)") : : "r"(storageSize), "r"(storagePtr) : "r0", "r1", "r14", "r15"); // clobber list __asm(" ST 15,%0 " : "=m"(returnCode) : : "r0", "r1", "r14", "r15"); #endif #ifdef __MVS__ __cterm((__csysenv_t) _dcb->_envtkn); #endif return returnCode; } void recfm(struct ihadcb *_ihadcb, struct dcb *_dcb) { /* Allowed RECFM F V FA VA FB VB FBA VBA FBM VBM FM VM */ _ihadcb->dcbrecfm = 0x00; if (_dcb->recfm[0] == 'f' || _dcb->recfm[0] == 'F') { _ihadcb->dcbrecfm = dcbrecf; } else if (_dcb->recfm[0] == 'v' || _dcb->recfm[0] == 'V') { _ihadcb->dcbrecfm = dcbrecv; } if (_dcb->recfm[1] == 'b' || _dcb->recfm[1] == 'B') { _ihadcb->dcbrecfm |= dcbrecbr; } else if (_dcb->recfm[1] == 'a' || _dcb->recfm[1] == 'A') { _ihadcb->dcbrecfm |= dcbrecca; } else if (_dcb->recfm[1] == 'm' || _dcb->recfm[1] == 'M') { _ihadcb->dcbrecfm |= dcbreccm; } if (_dcb->recfm[2] == 'a' || _dcb->recfm[2] == 'A') { _ihadcb->dcbrecfm |= dcbrecca; } else if (_dcb->recfm[2] == 'm' || _dcb->recfm[2] == 'M') { _ihadcb->dcbrecfm |= dcbreccm; } } extern int open(struct dcb *_dcb) { int storageSize; char wrkarea[256]; int returnCode; struct storage *_storage; struct ihadcb *_ihadcb; returnCode = 0; storageSize = 152; #ifdef __MVS__ __asm( (" STORAGE OBTAIN,LOC=BELOW" ",LENGTH=(%1)" ",ADDR=%0") : "=m"(_dcb->storage) : "r"(storageSize) : "r0", "r1", "r14", "r15"); // clobber list" __asm(" ST 15,%0 " : "=m"(returnCode) : : "r0", "r1", "r14", "r15"); __asm(" ST 0,%0 " : "=m"(_dcb->size) : : "r0", "r1", "r14", "r15"); #endif _storage = _dcb->storage; memset(wrkarea, 0, sizeof(wrkarea)); wrkarea[0] = 0x80; #ifdef __MVS__ // Length of DCB = 96 // Length of DCBE = 56 // Length Total = 152 __asm(" MVC 0(152,%0),MODELDCB" : : "r"(_storage->dcb) : "r0", "r1", "r14", "r15"); #endif _ihadcb = (void*) _storage->dcb; memcpy(_ihadcb->dcbddnam, _dcb->ddname, 8); _ihadcb->dcblrecl = _dcb->lrecl; _ihadcb->dcbblksi = _dcb->blksize; recfm(_ihadcb, _dcb); #ifdef __MVS__ __asm( (" OPEN (%1,(OUTPUT)),MODE=31,MF=(E,%0)") : "=m"(wrkarea[0]) : "m"(_storage->dcb) : "r0", "r1", "r14", "r15"); // clobber list" __asm(" ST 15,%0 " : "=m"(returnCode) : : "r0", "r1", "r14", "r15"); #endif return returnCode; } extern int put(struct dcb *_dcb) { char wrkarea[256]; int returnCode; void *outputPtr; struct storage *_storage; returnCode = 0; _storage = _dcb->storage; replace(_dcb->currentRecord); outputPtr = _dcb->currentRecord; #ifdef __MVS__ __asm( (" PUT (%0),(%1)") : : "r"(_storage->dcb), "r"(outputPtr) : "r0", "r1", "r14", "r15"); // clobber list" __asm(" ST 15,%0 " : "=m"(returnCode) : : "r0", "r1", "r14", "r15"); #endif return returnCode; } extern int close(struct dcb *_dcb) { int storageSize; char wrkarea[256]; int returnCode; struct storage *_storage; _storage = _dcb->storage; memset(wrkarea, 0, sizeof(wrkarea)); wrkarea[0] = 0x80; #ifdef __MVS__ __asm( (" CLOSE (%1),MODE=31,MF=(E,%0)") : "=m"(wrkarea[0]) : "m"(_storage->dcb) : "r0", "r1", "r14", "r15"); // clobber list" __asm(" ST 15,%0 " : "=m"(returnCode) : : "r0", "r1", "r14", "r15"); #endif return returnCode; } void programDump(int returnCode) { //PROGRAM TERMINATION - ABNORMAL #ifdef __MVS__ __asm( (" ABEND (%0),DUMP") : : "r"(returnCode) : "r0", "r1", "r14", "r15"); // clobber list #endif } void getTaskName(struct TCBAllocation *_TCBAllocation, char *name) { struct tcb *_tcb; struct rb *_rb; struct cdentry *_cde; struct cdePtr { union { void *tempPtr; unsigned int tempInt; } ; } ; struct cdePtr _cdePtr; _tcb = _TCBAllocation->TCB; _rb = _tcb->tcbrbp; _cdePtr.tempInt = 0; _cdePtr.tempInt = _rb->rbcde._rbcde1; _cde = _cdePtr.tempPtr; memcpy(name, _cde->cdname, 8); } int main() { int returnCode; void *TCBptr; int i; int j; int k; int rc; int workAreaLength; int NoOfSubpools; int NoOfTCBs; int NoOfBlocks; int subpool; char TCBName[8]; struct PVTSubpool *_PVTSubpool; struct AllocatedStorage _AllocatedStorage; struct workArea _workArea; struct TCBAllocation *_TCBAllocation; struct SubpoolDescriptor *_SubpoolDescriptor; struct AllocatedBlockDescriptor *_AllocatedBlockDescriptor; struct psa *psa; struct ascb *ascb; void *tcb; struct LSQASubpool *_LSQASubpool; struct lda *_lda; struct dcb _dcb; char message[133]; rc = 0; memset(&_dcb, 0, sizeof(struct dcb)); memcpy(_dcb.ddname, "SYSPRINT", 8); _dcb.lrecl = 133; _dcb.blksize = 1330; memcpy(_dcb.recfm, "FB ", 3); rc = init(&_dcb); rc = open(&_dcb); memset (&_workArea, 0, sizeof(_workArea)); memset (&_AllocatedStorage, 0, sizeof(_AllocatedStorage)); workAreaLength = sizeof(_workArea); // PSA - Prefixed Save Area psa = 0; // PSAAOLD - Pointer to the home (current) ASCB. ascb = psa->psaaold; // ASCBRCTP - POINTER TO REGION CONTROL TASK (RCT) TCB. tcb = ascb->ascbrctp; // VSM Local Data Area _lda = ascb->ascblda; // Retrieve Storage Information for Subpool = PVT #ifdef __MVS__ __asm( (" VSMLIST SP=PVT" ",WKAREA=((%0),(%1))" ",TCB=((%2),ALL)" ",SPACE=ALLOC,PVTSP=OWNED,LOC=ANY,LINKAGE=SYSTEM") : : "r"(&_workArea), "r"(workAreaLength), "r"(tcb) : "r0", "r1", "r14", "r15"); // clobber list __asm(" ST 15,%0 " : "=m"(returnCode) : : "r0", "r1", "r14", "r15"); #endif _PVTSubpool = (struct PVTSubpool*) _workArea.dataArea; _AllocatedStorage.numberOfTCBs = _PVTSubpool->NoOfTCBs; _TCBAllocation = (struct TCBAllocation*) ((char *) _PVTSubpool + sizeof(struct PVTSubpool)); for (i = 0; i < _AllocatedStorage.numberOfTCBs; i++) { NoOfSubpools = _TCBAllocation->NoOfSubpools; memset(&TCBName, 0, 8); getTaskName(_TCBAllocation, TCBName); memcpy(_AllocatedStorage.TCB[i].name, TCBName, 8); _SubpoolDescriptor = (struct SubpoolDescriptor*) ((char *) _TCBAllocation + sizeof(struct TCBAllocation)); for (j = 0; j < NoOfSubpools; j++) { _AllocatedBlockDescriptor = (struct AllocatedBlockDescriptor*) ((char *) _SubpoolDescriptor + sizeof(struct SubpoolDescriptor)); subpool = _SubpoolDescriptor->Descriptor._Id; for (k = 0; k < _SubpoolDescriptor->NoOfAllocBlocks; k++) { _AllocatedStorage.TCB[i].totalBytes += _AllocatedBlockDescriptor->BlockLength; _AllocatedStorage.PVT[subpool].totalBytes += _AllocatedBlockDescriptor->BlockLength; if ((_AllocatedBlockDescriptor->BlockAddr >> 24) == 0) { _AllocatedStorage.PVT[subpool].bytesBelowLine += _AllocatedBlockDescriptor->BlockLength; _AllocatedStorage.TCB[i].bytesBelowLine += _AllocatedBlockDescriptor->BlockLength; } else { _AllocatedStorage.PVT[subpool].bytesAboveLine += _AllocatedBlockDescriptor->BlockLength; _AllocatedStorage.TCB[i].bytesAboveLine += _AllocatedBlockDescriptor->BlockLength; } _AllocatedBlockDescriptor++; } _SubpoolDescriptor = (struct SubpoolDescriptor*) _AllocatedBlockDescriptor; } _TCBAllocation = (struct TCBAllocation*) _SubpoolDescriptor; } for (i = 0; i < 256; i++) { memset(&message, ' ', sizeof(message)); if (_AllocatedStorage.PVT[i].totalBytes > 0) { sprintf((char*) &message, "%i, %i, %i, %i", i, _AllocatedStorage.PVT[i].totalBytes, _AllocatedStorage.PVT[i].bytesBelowLine, _AllocatedStorage.PVT[i].bytesAboveLine); _dcb.currentRecord = &message; rc = put(&_dcb); } } for (i = 0; i < 256; i++) { memset(&message, ' ', sizeof(message)); if (_AllocatedStorage.TCB[i].totalBytes > 0) { sprintf((char*) &message, "%i, %8.8s, %i, %i, %i", i, _AllocatedStorage.TCB[i].name, _AllocatedStorage.TCB[i].totalBytes, _AllocatedStorage.TCB[i].bytesBelowLine, _AllocatedStorage.TCB[i].bytesAboveLine); _dcb.currentRecord = &message; rc = put(&_dcb); } } memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%s", "Summary of Key Information from LDA (Local Data Area)"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%12X %s", _lda->ldastrta, " Address of start of private storage area"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldasiza, " Size of private storage area"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%12X %s", _lda->ldacrgtp, " Address of current top of user region"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldalimit, " Maximum size of user region (< 16M V=V Region limit value)"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldaloal, " Total bytes allocated to user region (< 16M USER Region alloc value)"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldahial, " Total bytes allocated to LSQA/SWA/229/230 region (< 16M AUTH Region alloc value)"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%12X %s", _lda->ldaestra, " Address of start of extended private storage area"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldaesiza, " Size of extended private storage area"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%12X %s", _lda->ldaergtp, " Address of current top of extended user region"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldaelim, " Maximum Size of extended user region (> 16M V=V Region limit value)"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldaeloal, " Total bytes allocated to extended user region (> 16M USER Region alloc value)"); _dcb.currentRecord = &message; rc = put(&_dcb); memset(&message, ' ', sizeof(message)); sprintf((char*) &message, "%'12i %s", _lda->ldaehial, " Total bytes allocated to extended LSQA/SWA/229/230 (> 16M AUTH Region alloc value)"); _dcb.currentRecord = &message; rc = put(&_dcb); return (0); }