netcpu_kstat.c
Upload User: kvgkvg
Upload Date: 2015-05-07
Package Size: 1129k
Code Size: 9k
Development Platform:

C/C++

  1. char   netcpu_kstat_id[]="
  2. @(#)netcpu_kstat.c  Version 2.4.0";
  3. #if HAVE_CONFIG_H
  4. # include <config.h>
  5. #endif
  6. #include <stdio.h>
  7. #if HAVE_INTTYPES_H
  8. # include <inttypes.h>
  9. #else
  10. # if HAVE_STDINT_H
  11. #  include <stdint.h>
  12. # endif
  13. #endif
  14. #if HAVE_UNISTD_H
  15. # include <unistd.h>
  16. #endif
  17. #if HAVE_STRINGS_H
  18. # include <strings.h>
  19. #endif
  20. #if STDC_HEADERS
  21. # include <stdlib.h>
  22. # include <stddef.h>
  23. #else
  24. # if HAVE_STDLIB_H
  25. #  include <stdlib.h>
  26. # endif
  27. #endif
  28. #include <kstat.h>
  29. #include <sys/sysinfo.h>
  30. #include "netsh.h"
  31. #include "netlib.h"
  32. /* the lib_start_count and lib_end_count arrays hold the starting
  33.    and ending values of whatever is counting when the system is
  34.    idle. The rate at which this increments during a test is compared
  35.    with a previous calibrarion to arrive at a CPU utilization
  36.    percentage. raj 2005-01-26 */
  37. static uint64_t  lib_start_count[MAXCPUS];
  38. static uint64_t  lib_end_count[MAXCPUS];
  39. static  kstat_t *cpu_ks[MAXCPUS]; /* the addresses that kstat will
  40.                                      need to pull the cpu info from
  41.                                      the kstat interface.  at least I
  42.                                      think that is what this is :) raj
  43.                                      8/2000 */  
  44. #define UPDKCID(nk,ok) 
  45. if (nk == -1) { 
  46.   perror("kstat_read "); 
  47.   exit(1); 
  48. if (nk != ok)
  49.   goto kcid_changed;
  50. static kstat_ctl_t *kc = NULL;
  51. static kid_t kcid = 0;
  52. /* do the initial open of the kstat interface, get the chain id's all
  53.    straightened-out and set-up the addresses for get_kstat_idle to do
  54.    its thing.  liberally borrowed from the sources to TOP. raj 8/2000 */
  55. static int
  56. open_kstat()
  57. {
  58.   kstat_t *ks;
  59.   kid_t nkcid;
  60.   int i;
  61.   int changed = 0;
  62.   static int ncpu = 0;
  63.   kstat_named_t *kn;
  64.   if (debug) {
  65.     fprintf(where,"open_kstat: entern");
  66.     fflush(where);
  67.   }
  68.   
  69.   /*
  70.    * 0. kstat_open
  71.    */
  72.   
  73.   if (!kc)
  74.     {
  75.       kc = kstat_open();
  76.       if (!kc)
  77.         {
  78.           perror("kstat_open ");
  79.           exit(1);
  80.         }
  81.       changed = 1;
  82.       kcid = kc->kc_chain_id;
  83.     }
  84. #ifdef rickwasstupid
  85.   else {
  86.     fprintf(where,"open_kstat double open!n");
  87.     fflush(where);
  88.     exit(1);
  89.   }
  90. #endif
  91.   /* keep doing it until no more changes */
  92.  kcid_changed:
  93.   if (debug) {
  94.     fprintf(where,"passing kcid_changedn");
  95.     fflush(where);
  96.   }
  97.   
  98.   /*
  99.    * 1.  kstat_chain_update
  100.    */
  101.   nkcid = kstat_chain_update(kc);
  102.   if (nkcid)
  103.     {
  104.       /* UPDKCID will abort if nkcid is -1, so no need to check */
  105.       changed = 1;
  106.       kcid = nkcid;
  107.     }
  108.   UPDKCID(nkcid,0);
  109.   if (debug) {
  110.     fprintf(where,"kstat_lookup for unix/system_miscn");
  111.     fflush(where);
  112.   }
  113.   
  114.   ks = kstat_lookup(kc, "unix", 0, "system_misc");
  115.   if (kstat_read(kc, ks, 0) == -1) {
  116.     perror("kstat_read");
  117.     exit(1);
  118.   }
  119.   
  120.   
  121.   if (changed) {
  122.     
  123.     /*
  124.      * 2. get data addresses
  125.      */
  126.     
  127.     ncpu = 0;
  128.     
  129.     kn = kstat_data_lookup(ks, "ncpus");
  130.     if (kn && kn->value.ui32 > lib_num_loc_cpus) {
  131.       fprintf(stderr,"number of CPU's mismatch!");
  132.       exit(1);
  133.     }
  134.     
  135.     for (ks = kc->kc_chain; ks;
  136.          ks = ks->ks_next)
  137.       {
  138.         if (strncmp(ks->ks_name, "cpu_stat", 8) == 0)
  139.           {
  140.             nkcid = kstat_read(kc, ks, NULL);
  141.             /* if kcid changed, pointer might be invalid. we'll deal
  142.                wtih changes at this stage, but will not accept them
  143.                when we are actually in the middle of reading
  144.                values. hopefully this is not going to be a big
  145.                issue. raj 8/2000 */
  146.             UPDKCID(nkcid, kcid);
  147.             
  148.             if (debug) {
  149.               fprintf(where,"cpu_ks[%d] getting %pn",ncpu,ks);
  150.               fflush(where);
  151.             }
  152.             cpu_ks[ncpu] = ks;
  153.             ncpu++;
  154.             if (ncpu > lib_num_loc_cpus)
  155.               {
  156.                 /* with the check above, would we ever hit this? */
  157.                 fprintf(stderr, 
  158.                         "kstat finds too many cpus %d: should be %dn",
  159.                         ncpu,lib_num_loc_cpus);
  160.                 exit(1);
  161.               }
  162.           }
  163.       }
  164.     /* note that ncpu could be less than ncpus, but that's okay */
  165.     changed = 0;
  166.   }
  167. }
  168. /* return the value of the idle tick counter for the specified CPU */
  169. static long
  170. get_kstat_idle(cpu)
  171.      int cpu;
  172. {
  173.   cpu_stat_t cpu_stat;
  174.   kid_t nkcid;
  175.   if (debug) {
  176.     fprintf(where,
  177.             "get_kstat_idle reading with kc %x and ks %pn",
  178.             kc,
  179.             cpu_ks[cpu]);
  180.   }
  181.   nkcid = kstat_read(kc, cpu_ks[cpu], &cpu_stat);
  182.   /* if kcid changed, pointer might be invalid, fail the test */
  183.   UPDKCID(nkcid, kcid);
  184.   return(cpu_stat.cpu_sysinfo.cpu[CPU_IDLE]);
  185.  kcid_changed:
  186.   perror("kcid changed midstream and I cannot deal with that!");
  187.   exit(1);
  188. }
  189. void
  190. cpu_util_init(void) 
  191. {
  192.   open_kstat();
  193.   return;
  194. }
  195. void
  196. cpu_util_terminate(void)
  197. {
  198.   return;
  199. }
  200. int
  201. get_cpu_method(void)
  202. {
  203.   return KSTAT;
  204. }
  205. void
  206. get_cpu_idle(uint64_t *res)
  207. {
  208.   int i;
  209.   /* this open may be redundant */
  210.   open_kstat();
  211.   for (i = 0; i < lib_num_loc_cpus; i++){
  212.     res[i] = get_kstat_idle(i);
  213.   }
  214.   return;
  215. }
  216. float
  217. calibrate_idle_rate(int iterations, int interval)
  218. {
  219.  
  220.   long  
  221.     firstcnt[MAXCPUS],
  222.     secondcnt[MAXCPUS];
  223.   float 
  224.     elapsed,
  225.     temp_rate,
  226.     rate[MAXTIMES],
  227.     local_maxrate;
  228.   long  
  229.     sec,
  230.     usec;
  231.   int   
  232.     i,
  233.     j;
  234.   
  235.   struct  timeval time1, time2 ;
  236.   struct  timezone tz;
  237.   
  238.   if (debug) {
  239.     fprintf(where,"calling open_kstat from calibrate_kstatn");
  240.     fflush(where);
  241.   }
  242.   open_kstat();
  243.   if (iterations > MAXTIMES) {
  244.     iterations = MAXTIMES;
  245.   }
  246.   local_maxrate = (float)-1.0;
  247.   
  248.   for(i = 0; i < iterations; i++) {
  249.     rate[i] = (float)0.0;
  250.     for (j = 0; j < lib_num_loc_cpus; j++) {
  251.       firstcnt[j] = get_kstat_idle(j);
  252.     }
  253.     gettimeofday (&time1, &tz);
  254.     sleep(interval);
  255.     gettimeofday (&time2, &tz);
  256.     if (time2.tv_usec < time1.tv_usec)
  257.       {
  258.         time2.tv_usec += 1000000;
  259.         time2.tv_sec -=1;
  260.       }
  261.     sec = time2.tv_sec - time1.tv_sec;
  262.     usec = time2.tv_usec - time1.tv_usec;
  263.     elapsed = (float)sec + ((float)usec/(float)1000000.0);
  264.     
  265.     if(debug) {
  266.       fprintf(where, "Calibration for kstat counter run: %dn",i);
  267.       fprintf(where,"tsec = %ld usec = %ldn",sec,usec);
  268.       fprintf(where,"telapsed time = %gn",elapsed);
  269.     }
  270.     for (j = 0; j < lib_num_loc_cpus; j++) {
  271.       secondcnt[j] = get_kstat_idle(j);
  272.       if(debug) {
  273.         /* I know that there are situations where compilers know about */
  274.         /* long long, but the library functions do not... raj 4/95 */
  275.         fprintf(where,
  276.                 "tfirstcnt[%d] = 0x%8.8lx%8.8lx secondcnt[%d] = 0x%8.8lx%8.8lxn",
  277.                 j,
  278.                 firstcnt[j],
  279.                 firstcnt[j],
  280.                 j,
  281.                 secondcnt[j],
  282.                 secondcnt[j]);
  283.       }
  284.       /* we assume that it would wrap no more than once. we also */
  285.       /* assume that the result of subtracting will "fit" raj 4/95 */
  286.       temp_rate = (secondcnt[j] >= firstcnt[j]) ?
  287.         (float)(secondcnt[j] - firstcnt[j])/elapsed : 
  288.           (float)(secondcnt[j]-firstcnt[j]+MAXLONG)/elapsed;
  289.       if (temp_rate > rate[i]) rate[i] = temp_rate;
  290.       if(debug) {
  291.         fprintf(where,"trate[%d] = %gn",i,rate[i]);
  292.         fflush(where);
  293.       }
  294.       if (local_maxrate < rate[i]) local_maxrate = rate[i];
  295.     }
  296.   }
  297.   if(debug) {
  298.     fprintf(where,"tlocal maxrate = %g per sec. n",local_maxrate);
  299.     fflush(where);
  300.   }
  301.   return local_maxrate;
  302. }
  303. float
  304. calc_cpu_util_internal(float elapsed_time)
  305. {
  306.   int i;
  307.   float correction_factor;
  308.   float actual_rate;
  309.   lib_local_cpu_util = (float)0.0;
  310.   /* It is possible that the library measured a time other than */
  311.   /* the one that the user want for the cpu utilization */
  312.   /* calculations - for example, tests that were ended by */
  313.   /* watchdog timers such as the udp stream test. We let these */
  314.   /* tests tell up what the elapsed time should be. */
  315.   
  316.   if (elapsed_time != 0.0) {
  317.     correction_factor = (float) 1.0 + 
  318.       ((lib_elapsed - elapsed_time) / elapsed_time);
  319.   }
  320.   else {
  321.     correction_factor = (float) 1.0;
  322.   }
  323.   for (i = 0; i < lib_num_loc_cpus; i++) {
  324.     /* it would appear that on some systems, in loopback, nice is
  325.      *very* effective, causing the looper process to stop dead in its
  326.      tracks. if this happens, we need to ensure that the calculation
  327.      does not go south. raj 6/95 and if we run completely out of idle,
  328.      the same thing could in theory happen to the USE_KSTAT path. raj
  329.      8/2000 */ 
  330.     
  331.     if (lib_end_count[i] == lib_start_count[i]) {
  332.       lib_end_count[i]++;
  333.     }
  334.     
  335.     actual_rate = (lib_end_count[i] > lib_start_count[i]) ?
  336.       (float)(lib_end_count[i] - lib_start_count[i])/lib_elapsed :
  337.       (float)(lib_end_count[i] - lib_start_count[i] +
  338.       MAXLONG)/ lib_elapsed;
  339.     if (debug) {
  340.       fprintf(where,
  341.               "calc_cpu_util: actual_rate on processor %d is %f start %lx end %lxn",
  342.               i,
  343.               actual_rate,
  344.               lib_start_count[i],
  345.               lib_end_count[i]);
  346.     }
  347.     lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
  348.       lib_local_maxrate * 100;
  349.     lib_local_cpu_util += lib_local_per_cpu_util[i];
  350.   }
  351.   /* we want the average across all n processors */
  352.   lib_local_cpu_util /= (float)lib_num_loc_cpus;
  353.   
  354.   lib_local_cpu_util *= correction_factor;
  355.   return lib_local_cpu_util;
  356. }
  357. void
  358. cpu_start_internal(void)
  359. {
  360.   get_cpu_idle(lib_start_count);
  361.   return;
  362. }
  363. void
  364. cpu_stop_internal(void)
  365. {
  366.   get_cpu_idle(lib_end_count);
  367. }