perfstat_cpu_total Interface

The perfstat_cpu_total interface returns a perfstat_cpu_total_t structure, which is defined in the libperfstat.h file.

Selected fields from the perfstat_cpu_total_t structure include:
Item Descriptor
purr_coalescing PURR cycles consumes coalescing data if the calling partition is authorized to see pool wide statistics, else set to zero.
spurr_coalescing SPURR cycles consumes coalescing data if the calling partition is authorized to see pool wide statistics, else set to zero.
processorHz Processor speed in Hertz (from ODM)
description Processor type (from ODM)
CPUs Current number of active processors
ncpus_cfg Number of configured processors; that is, the maximum number of processors that this copy of AIX® can handle simultaneously
ncpus_high Maximum number of active processors; that is, the maximum number of active processors since the last reboot
user Number of clock ticks spent in user mode
sys Number of clock ticks spent in system (kernel) mode
idle Number of clock ticks spent idle with no I/O pending
wait Number of clock ticks spent idle with I/O pending
Note: Page coalescing is a transparent operation wherein the hypervisor detects duplicate pages, directs all user reads to a single copy, and reclaims the other duplicate physical memory pages.
Several other processor-related counters (such as number of system calls, number of reads, write, forks, execs, and load average) are also returned. For a complete list, see the perfstat_cpu_total_t section of the libperfstat.h header file.
The following program emulates lparstat's behavior and also shows an example of how the perfstat_cpu_total interface is used:
#include <stdio.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/proc.h>
#include <wpars/wparcfg.h>
#include <libperfstat.h>
#include <stdlib.h>

/* default values for interval and count */

#define INTERVAL_DEFAULT  1
#define COUNT_DEFAULT     1

/* values for wpar status */

#define ACTIVE 		  0 
#define NOTACTIVE	  1 

/* Check value returned by malloc for NULL */
#define CHECK_FOR_MALLOC_NULL(X) {  if ((X) == NULL) {\
                                       perror ("malloc");\
                                       exit(2);\
                                        }\
                                  }

/* Non zero WPAR ID indicates WPAR */

#define IS_WPAR(X) ((X))

 /* stores wpar id for perfstat library */

perfstat_id_wpar_t     wparid;
perfstat_wpar_total_t  wparinfo;
perfstat_wpar_total_t *wparlist;

 /*Corral id for WPAR */

cid_t cid;


int interval = INTERVAL_DEFAULT, count = COUNT_DEFAULT;
int totalwpar, activewpar;   /* to store and number of wpars available and active wpars */

/*
 *Name: do_cleanup
 *      free all allocated data structures
 */

void do_cleanup(void)
{
   if (wparlist)
       free(wparlist);	
 
}

/*
 *Name: display_global_sysinfo_stat
 *      Function used when called from global. 
 *      Gets all the system metrics using perfstat APIs and displays them 
 *
 */

void display_global_sysinfo_stat(void)
{
   perfstat_cpu_total_t *cpustat,*cpustat_last;
   perfstat_id_t first;

   /* allocate memory for data structures and check for any error */
 
   cpustat = (perfstat_cpu_total_t *)malloc(sizeof(perfstat_cpu_total_t));
   CHECK_FOR_MALLOC_NULL(cpustat);

   cpustat_last = (perfstat_cpu_total_t *)malloc(sizeof(perfstat_cpu_total_t));
   CHECK_FOR_MALLOC_NULL(cpustat_last);

   /* get the system wide statistics */

   if (perfstat_cpu_total(NULL , cpustat_last, sizeof(perfstat_cpu_total_t), 1) <= 0){
       perror("perfstat_cpu_total ");
       exit(1);
   }

   printf ("%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", "cswch", "scalls", "sread", "swrite", "fork", "exec", 
							"rchar", "wchar", "deviceint", "bwrite", "bread", "phread");
   printf ("%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n", "=====", "======", "=====", "======", "====", "====", 
							"=====", "=====", "=========", "======", "=====", "======"); 
   while (count > 0){
       sleep(interval);
       if (perfstat_cpu_total(NULL ,cpustat, sizeof(perfstat_cpu_total_t), 1) <= 0){
           perror("perfstat_cpu_total ");
           exit(1);
       }
       /* print the difference between the old structure and new structure */ 
       printf("%10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu %10llu\n",(cpustat->pswitch - cpustat_last->pswitch),
                                                         (cpustat->syscall - cpustat_last->syscall), (cpustat->sysread - cpustat_last->sysread ),
                                                         (cpustat->syswrite - cpustat_last->syswrite),(cpustat->sysfork - cpustat_last->sysfork),
							 (cpustat->sysexec - cpustat_last->sysexec ), (cpustat->readch - cpustat_last->readch),
							 (cpustat->writech - cpustat_last->writech ),(cpustat->devintrs - cpustat_last->devintrs),
                                                         (cpustat->bwrite - cpustat_last->bwrite), (cpustat->bread - cpustat_last->bread ),
                                                         (cpustat->phread - cpustat_last->phread ));
       count--;

       /*copy the present structure to the old structure */
       memcpy(cpustat_last , cpustat , sizeof(perfstat_cpu_total_t));
   }
   /* free the memory allocated for the data structures */
   free(cpustat);
   free(cpustat_last);

}
 
/*
 *Name: display_wpar_sysinfo_stat
 *      Displays both wpar and global metrics 
 *
 */

void display_wpar_sysinfo_stat(void)
{
   perfstat_wpar_total_t wparinfo;
   perfstat_cpu_total_wpar_t cinfo_wpar, cinfo_wpar_last;
   perfstat_cpu_total_t sysinfo, sysinfo_last;

   /* ste the spec and pass the wparname */ 
   wparid.spec = WPARNAME;
   strcpy(wparid.u.wparname, NULL);
   
   /* save the number of wpars which are active */
   activewpar = perfstat_wpar_total( NULL , &wparinfo ,sizeof(perfstat_wpar_total_t), 1);

   /* if the activewpar is less than zero exit with a perror */
   if (activewpar < 0){
       perror("perfstat_wpar_total :");
       exit(1); 
   }

   /* if the wpar is not active exit with a message */
   if (activewpar == 0){
       printf("wpar not active \n");
       exit(1);
   } 
   
   /* get the wpar wide cpu information */ 
   if (perfstat_cpu_total_wpar(NULL, &cinfo_wpar_last, sizeof(perfstat_cpu_total_wpar_t), 1) <=0){
       perror("perfstat_cpu_total_wpar :");
       exit(1);
   }
   if (perfstat_cpu_total(NULL , &sysinfo_last, sizeof(perfstat_cpu_total_t), 1) <=0){
       perror("perfstat_cpu_total_wpar :");
       exit(1);
   }
   printf("%10s %10s %10s %10s %10s %10s %10s %10s\n","wparname ", "cswch" , "syscalls", "fork","runque", "swpque", "runocc", "swpocc" );
   printf("%10s %10s %10s %10s %10s %10s %10s %10s\n","======== ", "=====" , "========", "====","======", "======", "======", "======" );

   while (count > 0){
       sleep(interval);
       if (perfstat_cpu_total_wpar( NULL,&cinfo_wpar,  sizeof(perfstat_cpu_total_wpar_t), 1) <=0){
           perror("perfstat_cpu_total_wpar :");
           exit(1);
       }
       if (perfstat_cpu_total(NULL, &sysinfo, sizeof(perfstat_cpu_total_t), 1) <=0){
           perror("perfstat_cpu_total :");
           exit(1);
       }
      
       /* display the difference between the current and old structure for the current wpar and system wide values*/ 
       printf("%10s %10llu %10llu %10llu %10llu %10llu %10llu %10llu\n",wparinfo.name, (cinfo_wpar.pswitch - cinfo_wpar_last.pswitch),
				(cinfo_wpar.syscall - cinfo_wpar_last.syscall), (cinfo_wpar.sysfork - cinfo_wpar_last.sysfork), 
				(cinfo_wpar.runque - cinfo_wpar_last.runque), (cinfo_wpar.swpque - cinfo_wpar_last.swpque), 
				(cinfo_wpar.runocc - cinfo_wpar_last.runocc), (cinfo_wpar.swpocc - cinfo_wpar_last.swpocc));

       printf("%10s %10llu %10llu %10llu %10llu %10llu %10llu %10llu\n\n", "Global", (sysinfo.pswitch - sysinfo_last.pswitch),
				(sysinfo.syscall - sysinfo_last.syscall), (sysinfo.sysfork - sysinfo_last.sysfork), 
				(sysinfo.runque - sysinfo_last.runque), (sysinfo.swpque - sysinfo_last.swpque), 
				(sysinfo.runocc - sysinfo_last.runocc), (sysinfo.swpocc - sysinfo_last.swpocc));
       count--;

       /* copy the data to the old structure */
       memcpy(&cinfo_wpar_last, &cinfo_wpar, sizeof(perfstat_wpar_total_t));
       memcpy(&sysinfo_last , &sysinfo , sizeof(perfstat_cpu_total_t));
   }
}
  
/* Name: display_wpar_total_sysinfo_stat
 *       displays statistics of individual wpar 
 *
 */
 
int display_wpar_total_sysinfo_stat(void)
{
   int i, *status;
   perfstat_wpar_total_t *wparinfo;
   perfstat_cpu_total_wpar_t *cinfo_wpar, *cinfo_wpar_last;
 
   /* allocate memory for the datastructures and check for any error */ 
   status = (int *) calloc(totalwpar ,sizeof(int));
   CHECK_FOR_MALLOC_NULL(status);

   cinfo_wpar = (perfstat_cpu_total_wpar_t *) malloc(sizeof (perfstat_cpu_total_wpar_t) * totalwpar);
   CHECK_FOR_MALLOC_NULL(cinfo_wpar);

   cinfo_wpar_last = (perfstat_cpu_total_wpar_t *) malloc(sizeof (perfstat_cpu_total_wpar_t) * totalwpar); 
   CHECK_FOR_MALLOC_NULL(cinfo_wpar_last);

   wparlist = (perfstat_wpar_total_t *) malloc(sizeof(perfstat_wpar_total_t) * totalwpar);
   CHECK_FOR_MALLOC_NULL(wparlist);

   activewpar = perfstat_wpar_total(&wparid, wparlist, sizeof(perfstat_wpar_total_t), totalwpar);
   
   if (activewpar < 0){
       perror("perfstat_wpar_total :");
       exit(1);
   }

   /* If no active wpars exit with a message */
   if (activewpar == 0){
       printf("no active wpars found \n");
       exit(1);
   }
   for (i = 0; i < activewpar; i++){
        /* copy the wparname into wparid and collect the data for all active wpars */
        strcpy(wparid.u.wparname, wparlist[i].name);
        if (perfstat_cpu_total_wpar(&wparid, &cinfo_wpar_last[i], sizeof(perfstat_cpu_total_wpar_t), 1) <= 0){
            status[i] = NOTACTIVE;
            continue;
        }
   }
   /*print the headers */ 
   printf("%20s %12s %12s %12s %12s %12s %12s %12s\n","wparname", "cswitch", "fork", "runque", "swpque", "runocc", "swpocc", "syscalls");
   printf("%20s %12s %12s %12s %12s %12s %12s %12s\n","========", "=======", "====", "======", "======", "======", "======", "========");
 
   while (count > 0){
         sleep(interval);
         for (i = 0; i < activewpar; i++){
              strcpy(wparid.u.wparname, wparlist[i].name);
              if (perfstat_cpu_total_wpar(&wparid, &cinfo_wpar[i], sizeof(perfstat_cpu_total_wpar_t), 1) <= 0){
                  status[i] = NOTACTIVE;
                  continue;
              }
         }
	 /* print the data for all active wpars */
         for (i = 0; i < activewpar; i++){
              if(status[i] == ACTIVE)
              printf("%20s %12llu %12llu %12llu %12llu %12llu %12llu %12llu\n", wparlist[i].name,
			(cinfo_wpar[i].pswitch - cinfo_wpar_last[i].pswitch), (cinfo_wpar[i].sysfork - cinfo_wpar_last[i].sysfork),
			(cinfo_wpar[i].runque - cinfo_wpar_last[i].runque), (cinfo_wpar[i].swpque - cinfo_wpar_last[i].swpque),
			(cinfo_wpar[i].runocc - cinfo_wpar_last[i].runocc), (cinfo_wpar[i].swpocc - cinfo_wpar_last[i].swpocc),
			(cinfo_wpar[i].syscall- cinfo_wpar_last[i].syscall));
         }
         printf("\n");
         count--;
         memcpy(cinfo_wpar_last,cinfo_wpar,(totalwpar * sizeof(perfstat_cpu_total_wpar_t)));
   }
   /* free all the memory structures */
   free(cinfo_wpar);
   free(cinfo_wpar_last);
   free(status); 
}

/*
 *Name: showusage
 *      displays the usage message
 *
 */

void showusage()
{
   if (!cid)
       printf("Usage:simplesysinfo [-@ { ALL | WPARNAME }] [interval] [count]\n ");
   else
       printf("Usage:simplesysinfo [interval] [count]\n");

   exit(1);
}
 
/* NAME: main
 *       This function determines the interval, iteration count.
 *       Then it calls the corresponding functions to display
 *       the corresponding metrics
 */

int main(int argc, char* argv[])
{  
   int rc ,atflag = 0, c;
   char wpar[MAXCORRALNAMELEN+1];
   strcpy(wpar, NULL);
   cid = corral_getcid();
    
   while((c = getopt(argc, argv, "@:"))!= EOF){
        if (c == '@'){
            if (IS_WPAR(cid))
                showusage();
            atflag = 1;
            strcpy(wpar, optarg);
        }
   }
   argc -= optind;
   argv += optind;
   
   if (argc > 2)
       showusage();

   if (argc){
       if ((interval = atoi(argv[0])) <= 0)
           showusage();
       argc--;
   }

   if (argc){
       if ((count = atoi(argv[1])) <= 0)
           showusage();
   }      

       
 /* If no -@ flag call display_global_sysinfo_stat function */ 
   if (!atflag ){
       if (!cid)
           /*display global values */
           display_global_sysinfo_stat();
       else
           /* display wpar values */
           display_wpar_sysinfo_stat();
   } 
   else{
       /* if the argument to -@ is not ALL set the totalwpars to 1 */
       if (strcmp(wpar, "ALL")) {
           strcpy(wparid.u.wparname, wpar);
           wparid.spec = WPARNAME;
           totalwpar = 1;
       }
       else{
	   totalwpar = perfstat_wpar_total(NULL, NULL, sizeof(perfstat_wpar_total_t), 0);
 
           if (totalwpar < 0){
               perror("perfstat_wpar_total : ");
               exit(1);
           }
           if (totalwpar == 0){
               printf("No wpars found");
               exit(1);
           }
           wparid.spec = WPARNAME;
           strcpy(wparid.u.wparname, NULL);
      }
      display_wpar_total_sysinfo_stat();
     
   }
   do_cleanup();
   return(0);
}
The program displays an output that is similar to the following example output:
cswch     scalls      sread     swrite       fork       exec      rchar      wchar  deviceint     bwrite      bread     phread
=====     ======      =====     ======       ====       ====      =====      =====  =========     ======      =====     ======
 83        525        133          2          0          1       1009462      264      27           0           0          0