/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/usr/ccs/lib/libperfstat/simplempstat.c 1.2.2.3 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* Restricted Materials of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 2008,2013 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)66 1.2.2.3 src/bos/usr/ccs/lib/libperfstat/simplempstat.c, libperfstat, bos720 10/16/13 02:11:08"; /* The sample program used to Display * * the cpu usage metrics for all cpus */ #include #include #include #include #include #include static int disp_util_header = 1; /*simplelparstat.c file can be used in two modes:- 1) Auto Mode:It makes use of perfstat_cpu_util API to calculate utilization values,enable 'UTIL_AUTO' macro for execution in auto mode. 2) Manual Mode: Calculations are done in the current code. */ /* #define UTIL_AUTO */ #ifdef UTIL_AUTO #define UTIL_MS 1 #define UTIL_PCT 0 #define UTIL_CORE 2 #define UTIL_PURR 0 #define UTIL_SPURR 1 void display_metrics_global_auto(int mode,int cpumode,int count,int interval); #endif /* To Check whether malloc is successful or not */ #define CHECK_FOR_MALLOC_NULL(X) { if ((X) == NULL) {\ perror ("malloc");\ exit(2);\ }\ } /* Convert 4K pages to MB */ #define AS_MB(X) ((X) * 4096/1024/1024) /* WPAR ID for global will always be zero */ #define IS_GLOBAL(X) (!(X)) /* Non zero WPAR ID indicates WPAR */ #define IS_WPAR(X) ((X)) /* For WPAR, use NULL else use the actual WPAR ID (for global) */ #define WPAR_ID ((cid)?NULL:&wparid) /* To store the count of Logical CPUs in the LPAR */ /* Default values for interval and count */ #define INTERVAL_DEFAULT 1 #define COUNT_DEFAULT 1 static int ncpu, atflag; static int returncode, count = COUNT_DEFAULT, interval = INTERVAL_DEFAULT; unsigned long long last_user, last_sys, last_idle, last_wait, last_timebase; unsigned long long delta_user, delta_sys, delta_wait, delta_idle, delta_total, delta_timebase; /* store LPAR level stats */ perfstat_cpu_total_t *totalcinfo, *totalcinfo_last; perfstat_memory_total_t minfo; perfstat_partition_total_t pinfo, qinfo; perfstat_cpu_t *cinfo, *cinfo_last; /* stores wpar id for perfstat library */ perfstat_id_wpar_t wparid; /* store per WPAR stats */ perfstat_wpar_total_t winfo; perfstat_cpu_total_wpar_t cinfo_wpar; /* store current WPAR ID */ cid_t cid; char wpar[MAXCORRALNAMELEN+1]; /* support for remote node statistics collection in a cluster environment */ perfstat_id_node_t nodeid; char nodename[MAXHOSTNAMELEN]; int nflag = 0; /* display the usage */ void showusage(char *cmd) { if (!cid) fprintf(stderr, "usage: %s [-@ { ALL | WPARNAME } | -n nodename ] [-i ] [-c ]\n", cmd); else fprintf(stderr, "usage: %s [-i ] [-c ]\n", cmd); exit(1); } /* Save the current values for the next iteration */ void save_last_values (void) { memcpy( totalcinfo_last, totalcinfo, sizeof(perfstat_cpu_total_t)); memcpy( cinfo_last, cinfo, sizeof(perfstat_cpu_t)); } void initialise(void) { totalcinfo = (perfstat_cpu_total_t *)malloc(sizeof(perfstat_cpu_total_t)); CHECK_FOR_MALLOC_NULL(totalcinfo); totalcinfo_last = (perfstat_cpu_total_t *)malloc(sizeof(perfstat_cpu_total_t)); CHECK_FOR_MALLOC_NULL(totalcinfo_last); cinfo = (perfstat_cpu_t *)malloc(sizeof(perfstat_cpu_t) * ncpu); CHECK_FOR_MALLOC_NULL(cinfo); cinfo_last = (perfstat_cpu_t *)malloc(sizeof(perfstat_cpu_t) * ncpu); CHECK_FOR_MALLOC_NULL(cinfo_last); } void display_configuration (void) { unsigned long long memlimit; double cpulimit; int i ,totalcpu; /* gather LPAR level data */ if(nflag) { strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN); nodeid.spec = NODENAME; if (perfstat_partition_total_node(&nodeid, &pinfo, sizeof(perfstat_partition_total_t), 1) <= 0) { perror("perfstat_partition_total_node:"); exit(1); } if (perfstat_memory_total_node(&nodeid, &minfo, sizeof(perfstat_memory_total_t), 1) <= 0) { perror("perfstat_memory_total_node:"); exit(1); } totalcpu = perfstat_cpu_node(&nodeid, NULL, sizeof(perfstat_cpu_t), 0); } else { if (perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1) <= 0) { perror("perfstat_partition_total:"); exit(1); } if (perfstat_memory_total(NULL, &minfo, sizeof(perfstat_memory_total_t), 1) <= 0) { perror("perfstat_memory_total:"); exit(1); } totalcpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); } /* print LPAR configuration */ printf("Purr counter value = %lld \n",pinfo.purr_counter); printf("Spurr counter value = %lld \n",pinfo.spurr_counter); printf("Free memory = %lld \n",pinfo.real_free); printf("Available memory = %lld \n",pinfo.real_avail); printf("\nlpar configuration : "); printf("lcpus = %d ", totalcpu); /* number of CPUs online */ printf("mem = %lluMB ", AS_MB(minfo.real_total)); /* real memory */ printf("ent = %#5.2f\n", (double)pinfo.entitled_proc_capacity/100.0); /* entitled capacity */ } /* * NAME: display_metrics_global * used to display the metrics when called from global * */ void display_metrics_global(void) { int i; perfstat_id_t first; strcpy(first.name, FIRST_CPU); if(nflag){ strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN); nodeid.spec = NODENAME; if (perfstat_cpu_total_node(&nodeid, totalcinfo_last, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total_node:"); exit(1); } if (perfstat_cpu_node(&nodeid, cinfo_last, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu_node:"); exit(1); } if (perfstat_partition_total_node(&nodeid, &qinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total_node:"); exit(1); } } else{ if (perfstat_cpu_total(NULL, totalcinfo_last, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total:"); exit(1); } if (perfstat_cpu(&first, cinfo_last, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu:"); exit(1); } if (perfstat_partition_total(NULL, &qinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total:"); exit(1); } } printf("\n cpu\tuser\tsys\twait\tidle\tstate\n\n"); while(count) { sleep(interval); if(nflag){ if (perfstat_cpu_total_node(&nodeid, totalcinfo, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total_node:"); exit(1); } if (perfstat_cpu_node(&nodeid, cinfo, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu_node:"); exit(1); } if (perfstat_partition_total_node(&nodeid, &pinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total_node:"); exit(1); } } else{ if (perfstat_cpu_total(NULL, totalcinfo, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total:"); exit(1); } if (perfstat_cpu(&first, cinfo, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu:"); exit(1); } if (perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total:"); exit(1); } } for(i = 0; i < ncpu; i++){ delta_user = cinfo[i].puser - cinfo_last[i].puser; delta_sys = cinfo[i].psys - cinfo_last[i].psys; delta_idle = cinfo[i].pidle - cinfo_last[i].pidle; delta_wait = cinfo[i].pwait - cinfo_last[i].pwait; delta_total= delta_user + delta_sys + delta_idle + delta_wait; delta_timebase = pinfo.timebase_last - qinfo.timebase_last; if(!delta_total) continue; printf("%s\t%#4.1f\t%#4.1f\t%#4.1f\t%#4.1f\t%#4.1d\n",cinfo[i].name, ((double)(delta_user)/(double)(delta_total) * 100.0), ((double)(delta_sys)/(double)(delta_total) * 100.0), ((double)(delta_wait)/(double)(delta_total) * 100.0), ((double)(delta_idle)/(double)(delta_total) * 100.0), cinfo[i].state); } delta_user = totalcinfo->puser - totalcinfo_last->puser; delta_sys = totalcinfo->psys - totalcinfo_last->psys; delta_wait = totalcinfo->pwait - totalcinfo_last->pwait; delta_idle = totalcinfo->pidle - totalcinfo_last->pidle; delta_total= delta_user + delta_sys + delta_idle + delta_wait; printf("%s\t%#4.1f\t%#4.1f\t%#4.1f\t%#4.1f\n\n","ALL",((double)(delta_user)/(double)(delta_total) * 100.0), ((double)(delta_sys)/(double)(delta_total) * 100.0), ((double)(delta_wait)/(double)(delta_total) * 100.0), ((double)(delta_idle)/(double)(delta_total) * 100.0)); count--; save_last_values(); } } /* *NAME: display_metrics_wpar * used to display the metrics when called from wpar * */ void display_metrics_wpar(void) { int i; char last[5]; perfstat_id_wpar_t first; /*first.spec = WPARNAME;*/ strcpy(first.name,NULL ); if (perfstat_wpar_total( NULL, &winfo, sizeof(perfstat_wpar_total_t), 1) <= 0){ perror("perfstat_wpar_total:"); exit(1); } if (perfstat_cpu_total_rset(NULL, totalcinfo_last, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total_rset:"); exit(1); } if (perfstat_cpu_rset(NULL, cinfo_last, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu_rset:"); exit(1); } if (perfstat_partition_total(NULL, &qinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total:"); exit(1); } printf("\n cpu\tuser\tsys\twait\tidle\n\n"); while(count) { sleep(interval); if (perfstat_cpu_total_rset(NULL, totalcinfo, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total_rset:"); exit(1); } if (perfstat_cpu_rset(NULL, cinfo, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu_rset:"); exit(1); } if (perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total:"); exit(1); } for(i=0; ipuser - totalcinfo_last->puser; delta_sys = totalcinfo->psys - totalcinfo_last->psys; delta_wait = totalcinfo->pwait - totalcinfo_last->pwait; delta_idle = totalcinfo->pidle - totalcinfo_last->pidle; delta_total= delta_user + delta_sys + delta_idle + delta_wait; if (winfo.type.b.cpu_rset) strcpy(last,"RST"); else strcpy(last,"ALL"); printf("%s\t%#4.1f\t%#4.1f\t%#4.1f\t%#4.1f\n\n",last,((double)(delta_user)/(double)(delta_total) * 100.0), ((double)(delta_sys)/(double)(delta_total) * 100.0), ((double)(delta_wait)/(double)(delta_total) * 100.0), ((double)(delta_idle)/(double)(delta_total) * 100.0)); count--; save_last_values(); } } /* * NAME: display_metrics_wpar_from_global * display metrics of wpar when called from global * */ void display_metrics_wpar_from_global(void) { char last[5]; int i; if (perfstat_wpar_total( &wparid, &winfo, sizeof(perfstat_wpar_total_t), 1) <= 0){ perror("perfstat_wpar_total:"); exit(1); } if (winfo.type.b.cpu_rset) strcpy(last,"RST"); else strcpy(last,"ALL"); strcpy(wparid.u.wparname,wpar); if (perfstat_cpu_total_rset(&wparid, totalcinfo_last, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total_rset:"); exit(1); } if (perfstat_cpu_rset(&wparid, cinfo_last, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu_rset:"); exit(1); } if (perfstat_partition_total(NULL, &qinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total:"); exit(1); } printf("\n cpu\tuser\tsys\twait\tidle\n\n"); while(count) { sleep(interval); if (perfstat_cpu_total_rset(&wparid, totalcinfo, sizeof(perfstat_cpu_total_t), 1) <= 0){ perror("perfstat_cpu_total_rset:"); exit(1); } if (perfstat_cpu_rset(&wparid, cinfo, sizeof(perfstat_cpu_t), ncpu) <= 0){ perror("perfstat_cpu_rset:"); exit(1); } if (perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1) <= 0){ perror("perfstat_partition_total:"); exit(1); } for(i = 0; i < ncpu; i++){ delta_user = cinfo[i].puser - cinfo_last[i].puser; delta_sys = cinfo[i].psys - cinfo_last[i].psys; delta_idle = cinfo[i].pidle - cinfo_last[i].pidle; delta_wait = cinfo[i].pwait - cinfo_last[i].pwait; delta_total= delta_user + delta_sys + delta_idle + delta_wait; delta_timebase = pinfo.timebase_last - qinfo.timebase_last; if(!delta_total) continue; printf("%s\t%#4.1f\t%#4.1f\t%#4.1f\t%#4.1f\n",cinfo[i].name,((double)(delta_user)/(double)(delta_total) * 100.0), ((double)(delta_sys)/(double)(delta_total) * 100.0), ((double)(delta_wait)/(double)(delta_total) * 100.0), ((double)(delta_idle)/(double)(delta_total) * 100.0)); } delta_user = totalcinfo->puser - totalcinfo_last->puser; delta_sys = totalcinfo->psys - totalcinfo_last->psys; delta_wait = totalcinfo->pwait - totalcinfo_last->pwait; delta_idle = totalcinfo->pidle - totalcinfo_last->pidle; delta_total= delta_user + delta_sys + delta_idle + delta_wait; printf("%s\t%#4.1f\t%#4.1f\t%#4.1f\t%#4.1f\n\n",last, ((double)(delta_user)/(double)(delta_total) * 100.0), ((double)(delta_sys)/(double)(delta_total) * 100.0), ((double)(delta_wait)/(double)(delta_total) * 100.0), ((double)(delta_idle)/(double)(delta_total) * 100.0)); count--; save_last_values(); } } #ifdef UTIL_AUTO void display_metrics_global_auto(int mode,int cpumode,int count,int interval) { float user_core_purr,kern_core_purr,wait_core_purr,idle_core_purr; float user_core_spurr,kern_core_spurr,wait_core_spurr,idle_core_spurr,sum_core_spurr; u_longlong_t user_ms_purr,kern_ms_purr,wait_ms_purr,idle_ms_purr,sum_ms; u_longlong_t user_ms_spurr,kern_ms_spurr,wait_ms_spurr,idle_ms_spurr; perfstat_rawdata_t data; u_longlong_t delta_purr; double phys_proc_consumed, entitlement, percent_ent, delta_sec; perfstat_partition_total_t lparstats; static perfstat_cpu_t *oldt,*newt; perfstat_cpu_util_t *util; int rc,cpu_count,i; perfstat_id_t id; /* retrieve the metrics */ while(count) { /* Print the header for utilization metrics (only once) */ if (disp_util_header) { if(mode==UTIL_PCT) printf("\nCPU %5s %5s %6s %6s %5s \n", "%user", "%sys", "%wait", "%idle", "physc"); else if(mode==UTIL_MS) printf("\nCPU %5s %5s %6s %6s %5s \n", "user(ms)", "sys(ms)", "wait(ms)", "idle(ms)", "physc"); else if(mode==UTIL_CORE) printf("\nCPU %5s %5s %6s %6s %5s %5s \n", "user", "sys", "wait", "idle", "physc", "state"); /* first iteration, we only read the data, print the header and save the data */ } cpu_count = perfstat_cpu(NULL, NULL,sizeof(perfstat_cpu_t),0); /* check for error */ if(cpu_count <= 0) { perror("Error in perfstat_cpu"); exit(-1); } /* allocate enough memory */ oldt = (perfstat_cpu_t *)calloc(cpu_count,sizeof(perfstat_cpu_t)); if(oldt == NULL) { perror("Memory Allocation Error"); exit(-1); } /* set name to first cpu */ strcpy(id.name,FIRST_CPU); /* ask to get all the structures available in one call */ rc = perfstat_cpu(&id, oldt, sizeof(perfstat_cpu_t), cpu_count); /* check for error */ if(rc <=0) { perror("Error in perfstat_cpu"); exit(-1); } data.type = UTIL_CPU; data.prevstat= oldt; data.sizeof_data = sizeof(perfstat_cpu_t); data.prev_elems = cpu_count; sleep(interval); /* Check how many perfstat_cpu_t structures are available after a defined period */ cpu_count = perfstat_cpu(NULL, NULL,sizeof(perfstat_cpu_t),0); /* Check for error */ if(cpu_count <= 0) { perror("Error in perfstat_cpu"); exit(-1); } data.cur_elems = cpu_count; if(data.prev_elems != data.cur_elems) { perror("The number of CPUs has become different for defined period"); exit(-1); } /* allocate enough memory */ newt = (perfstat_cpu_t *)calloc(cpu_count,sizeof(perfstat_cpu_t)); util = (perfstat_cpu_util_t *)calloc(cpu_count,sizeof(perfstat_cpu_util_t)); if(newt == NULL || util == NULL) { perror("Memory Allocation Error"); exit(-1); } data.curstat = newt; rc = perfstat_cpu(&id, newt, sizeof(perfstat_cpu_t), cpu_count); if(rc <= 0) { perror("Error in perfstat_cpu"); exit(-1); } /* Calculate CPU Utilization Metrics*/ rc = perfstat_cpu_util(&data, util, sizeof(perfstat_cpu_util_t), cpu_count); if(rc <= 0) { perror("Error in perfstat_cpu_util"); exit(-1); } switch(mode) { case UTIL_PCT: for(i=0;i2)&& (cpumode>1)) { printf("Error: Invalid Input\n"); exit(0); } display_metrics_global_auto(mode,cpumode,count,interval); #else display_metrics_global(); #endif if(nflag) { /* Now disable cluster statistics by calling perfstat_config */ perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL); } return(0); }