Examples
#pragma linkage(BPX1PCT, OS)
extern void BPX1PCT(char *, int, int, char *, int *, int *, int *);
/* #include <stdlib.h> */
#include <stdio.h>
#define ZFSCALL_STATS 0x40000007
#define STATOP_LOCKING 240 /* Performance API queries */
#define u_long unsigned long
typedef struct syscall_parmlist_t
{
int opcode; /* Operation code to perform */
int parms[7]; /* Specific to type of operation, */
/* provides access to the parms */
/* parms[4]-parms[6] are currently unused*/
} syscall_parmlist;
typedef struct Lock_line_t
{
int count; /* Number of thread waits for this lock */
int async; /* Asynchronous disposition*/
int spins; /* Number of attempts to get lock that did not resolve immediately*/
int pad1;
double percentage; /**/
int percentage_whole; /* percentage >= 1*/
int percentage_decimal;/* percentage < 1*/
/* in thousanths.*/
/* For example, 3 means .003 and 300 means .3 */
char description[84]; /* Description of the lock */
int pad2;
} LOCK_LINE;
typedef struct Sleep_line_t
{
unsigned long sleepcount; /* Time spent sleeping */
int pad1;
double percentage; /* Percentage of time spent sleeping*/
int percentage_whole; /* Percentage >=1 */
int percentage_decimal; /* Percentage < 1 */
/* in thousanths.*/
/* For example, 3 means .003 and 300 means .3 */
char description[84]; /*Description of the thread*/
int pad2;
} SLEEP_LINE;
/* reset timestamp */
typedef struct reset_time {
u_long posix_time_high; /* high order 32 bits since epoc */
u_long posix_time_low; /* low order 32 bits since epoch */
u_long posix_usecs; /* microseconds */
int pad1;
} RESET_TIME;
/*********************************************************************/
/* The following structure is the api query control block */
/* It is used for all api query commands */
/*********************************************************************/
typedef struct stat_api_t
{
#define SA_EYE "STAP"
char sa_eye[4]; /* 4 byte identifier must be */
int sa_len; /* length of the buffer to put data into*/
/* this buffer area follows this struct*/
int sa_ver; /* the version number currently always 1*/
#define SA_VER_INITIAL 0x01
char sa_flags; /* flags field must be x00 or x80, x80 means reset statistics*/
#define SA_RESET 0x80
char sa_fill[3]; /* spare bytes */
int sa_reserve[4]; /* Reserved */
struct reset_time reset_time_info;
} STAT_API;
typedef struct stat_locking_t
{
int reserved1;
unsigned long stlk_untimed_sleeps; /* Number of untimed sleeps */
unsigned long stlk_timed_sleeps; /* Number of timed sleeps */
unsigned long stlk_wakeups; /* Number of wake ups */
unsigned long stlk_total_wait_for_locks; /* Total waits for locks */
int pad1;
double stlk_average_lock_wait_time; /*Average lock wait time */
int stlk_avg_lock_wait_time_whole; /*Average lock wait time in msecs */
/*left of the decimal part */
int stlk_avg_lock_wait_time_decimal; /*Average lock wait time in msecs */
/*decimal portion */
/* in thousanths */
/* for example, 3 means .003 and 300 means .3 */
unsigned long stlk_total_monitored_sleeps; /*Total monitored sleeps */
int pad2;
double stlk_average_monitored_sleep_time;/* Average monitored sleep time */
int stlk_avg_mon_sleep_time_whole; /*Average monitored sleep time in msecs */
/* left of the decimal part*/
int stlk_avg_mon_sleep_time_decimal; /*Average monitored sleep time in msecs */
/* decimal portion */
/* in thousanths */
/* for example, 3 means .003 and 300 means .3 */
unsigned long stlk_total_contentions; /*Total lock contention of all kinds*/
char stlk_reserved_space[48]; /* reserved for future use */
int pad3;
#define MAX_LOCKS 15 /* Maximum number of locks in this release*/
#define MAX_SLEEPS 5 /* Maximum number of sleeps in this release*/
LOCK_LINE stlk_locks[MAX_LOCKS]; /* Storage for the lock data */
SLEEP_LINE stlk_sleeps[MAX_SLEEPS]; /* Storage for the top 5 most common sleep threads*/
} STAT_LOCKING;
/*********************************************************************/
/* The following structures are used to represent cfgop queries */
/* for locking stats */
/*********************************************************************/
struct parmstruct
{
syscall_parmlist myparms;
STAT_API myapi;
STAT_LOCKING mystats;
char systemname[9];
} myparmstruct;
int main(int argc, char **argv)
{
int bpxrv;
int bpxrc;
int bpxrs;
int i;
STAT_API *stapptr = &(myparmstruct.myapi);
STAT_LOCKING *stlkptr = &(myparmstruct.mystats);
char buf[33];
myparmstruct.myparms.opcode = STATOP_LOCKING;
myparmstruct.myparms.parms[0] = sizeof(syscall_parmlist);
myparmstruct.myparms.parms[1] = sizeof(syscall_parmlist) + sizeof(STAT_API);
myparmstruct.myparms.parms[2] = 0;
/* Only specify a non-zero offset for the next field (parms[2]) if */
/* you are running z/OS 1.7 and above, and */
/* you want to query the locking statistics of a different system than this one */
/* myparmstruct.myparms.parms[2] = sizeof(syscall_parmlist) + sizeof(STAT_API) + sizeof(STAT_LOCKING); */
myparmstruct.myparms.parms[3] = 0;
myparmstruct.myparms.parms[4] = 0;
myparmstruct.myparms.parms[5] = 0;
myparmstruct.myparms.parms[6] = 0;
memset(stapptr,0,sizeof(STAT_API));
memcpy(stapptr->sa_eye,SA_EYE,4);
stapptr->sa_ver=SA_VER_INITIAL;
stapptr->sa_len=(int) sizeof(STAT_LOCKING);
/* This next field should only be set if parms[2] is non-zero */
/* strcpy(myparmstruct.systemname,"DCEIMGVQ"); */
BPX1PCT("ZFS ",
ZFSCALL_STATS, /* Perf statistics operation */
sizeof(myparmstruct), /* Length of Argument */
(char *) &myparmstruct, /* Pointer to Argument */
&bpxrv, /* Pointer to Return_value */
&bpxrc, /* Pointer to Return_code */
&bpxrs); /* Pointer to Reason_code */
if( bpxrv < 0 )
{
printf("Error querying locking stats, BPXRV = %d BPXRC = %d BPXRS = %x\n",bpxrv,bpxrc,bpxrs);
return bpxrc;
}
else
{
printf("%55s\n","Locking Statistics");
printf("\n");
printf("\n");
printf("Untimed sleeps: %10u Timed Sleeps: %10u Wakeups: %10u\n",
myparmstruct.mystats.stlk_untimed_sleeps,
myparmstruct.mystats.stlk_timed_sleeps,
myparmstruct.mystats.stlk_wakeups);
printf("\n");
printf("Total waits for locks: %10u\n",
myparmstruct.mystats.stlk_total_wait_for_locks);
printf("Average lock wait time: %9u.%3.3u (msecs)\n",
myparmstruct.mystats.stlk_avg_lock_wait_time_whole,
myparmstruct.mystats.stlk_avg_lock_wait_time_decimal);
printf("\n");
printf("Total monitored sleeps: %10u\n",
myparmstruct.mystats.stlk_total_monitored_sleeps);
printf("Average monitored sleep time: %9u.%3.3u (msecs)\n",
myparmstruct.mystats.stlk_avg_mon_sleep_time_whole,
myparmstruct.mystats.stlk_avg_mon_sleep_time_decimal);
printf("\n");
printf(" Top %u Most Highly Contended Locks\n",
MAX_LOCKS);
printf(" Thread Async Spin \n");
printf(" Wait Disp. Resol. Pct. Description\n");
printf("---------- ---------- ---------- ----- --------------\n");
for( i = 0; i < MAX_LOCKS;i++ )
{
printf("%10u %10u %10u %3u.%1.1u%% %.80s\n",
myparmstruct.mystats.stlk_locks[i].count,
myparmstruct.mystats.stlk_locks[i].async,
myparmstruct.mystats.stlk_locks[i].spins,
myparmstruct.mystats.stlk_locks[i].percentage_whole,
myparmstruct.mystats.stlk_locks[i].percentage_decimal,
myparmstruct.mystats.stlk_locks[i].description);
}
printf("\n");
printf("Total lock contention of all kinds: %10u\n",
myparmstruct.mystats.stlk_total_contentions);
printf("\n");
printf(" Top %u Most Common Thread Sleeps\n",
MAX_SLEEPS);
printf("Thread Wait Pct. Description\n");
printf("----------- ----- -----------\n");
for( i = 0; i < MAX_SLEEPS;i++ )
{
printf(" %10u %3u.%1.1u%% %.80s\n",
myparmstruct.mystats.stlk_sleeps[i].sleepcount,
myparmstruct.mystats.stlk_sleeps[i].percentage_whole,
myparmstruct.mystats.stlk_sleeps[i].percentage_decimal,
myparmstruct.mystats.stlk_sleeps[i].description);
printf("\n");
}
if (0==ctime_r((time_t *) &stapptr->reset_time_info.posix_time_low, buf))
{
printf("Could not get timestamp.\n");
}
else
{ /* Insert the microseconds into the displayable time value */
strncpy(&(buf[27]),&(buf[20]),6);
sprintf(&(buf[20]),"%06d",stapptr->reset_time_info.posix_usecs);
buf[26]=' ';
buf[19]='.';
printf("Last Reset Time: %s",buf);
}
}
return 0;
}