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

C/C++

  1. char   netcpu_procstat_id[]="
  2. @(#)netcpu_procstat.c (c) Copyright 2005-2007 Version 2.4.3";
  3. /* netcpu_procstat.c
  4.   
  5.    Implement the /proc/stat specific portions of netperf CPU
  6.    utilization measurements. These are broken-out into a separate file
  7.    to make life much nicer over in netlib.c which had become a maze of
  8.    twisty, CPU-util-related, #ifdefs, all different.  raj 2005-01-26
  9.    */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <stdio.h>
  14. #ifdef HAVE_FCNTL_H
  15. # include <fcntl.h>
  16. #endif
  17. #if HAVE_UNISTD_H
  18. # include <unistd.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 <string.h>
  29. #include "netsh.h"
  30. #include "netlib.h"
  31. /* the lib_start_count and lib_end_count arrays hold the starting
  32.    and ending values of whatever is counting when the system is
  33.    idle. The rate at which this increments during a test is compared
  34.    with a previous calibrarion to arrive at a CPU utilization
  35.    percentage. raj 2005-01-26 */
  36. static uint64_t  lib_start_count[MAXCPUS];
  37. static uint64_t  lib_end_count[MAXCPUS];
  38. /* The max. length of one line of /proc/stat cpu output */
  39. #define CPU_LINE_LENGTH ((8 * sizeof (long) / 3 + 1) * 4 + 8)
  40. #define PROC_STAT_FILE_NAME "/proc/stat"
  41. #define N_CPU_LINES(nr) (nr == 1 ? 1 : 1 + nr)
  42. static int proc_stat_fd = -1;
  43. static char *proc_stat_buf = NULL;
  44. static int proc_stat_buflen = 0;
  45. void
  46. cpu_util_init(void) 
  47. {
  48.   if (debug) {
  49.     fprintf(where,
  50.     "cpu_util_init enter, proc_stat_fd %d proc_stat_buf %pn",
  51.     proc_stat_fd,
  52.     proc_stat_buf);
  53.     fflush(where);
  54.   }
  55.   if (proc_stat_fd < 0) {
  56.     proc_stat_fd = open (PROC_STAT_FILE_NAME, O_RDONLY, NULL);
  57.     if (proc_stat_fd < 0) {
  58.       fprintf (stderr, "Cannot open %s!n", PROC_STAT_FILE_NAME);
  59.       exit (1);
  60.     };
  61.   };
  62.   if (!proc_stat_buf) {
  63.     proc_stat_buflen = N_CPU_LINES (lib_num_loc_cpus) * CPU_LINE_LENGTH;
  64.     if (debug) {
  65.       fprintf(where,
  66.       "lib_num_loc_cpus %d lines %d CPU_LINE_LENGTH %d proc_stat_buflen %dn",
  67.       lib_num_loc_cpus,
  68.       N_CPU_LINES(lib_num_loc_cpus),
  69.       CPU_LINE_LENGTH,
  70.       proc_stat_buflen);
  71.       fflush(where);
  72.     }
  73.     proc_stat_buf = (char *)malloc (proc_stat_buflen);
  74.     if (!proc_stat_buf) {
  75.       fprintf (stderr, "Cannot allocate buffer memory!n");
  76.       exit (1);
  77.     }
  78.   }
  79.   return;
  80. }
  81. void
  82. cpu_util_terminate(void)
  83. {
  84.   close(proc_stat_fd);
  85.   proc_stat_fd = -1;
  86.   free(proc_stat_buf);
  87.   proc_stat_buf = NULL;
  88.   return;
  89. }
  90. int
  91. get_cpu_method()
  92. {
  93.   return PROC_STAT;
  94. }
  95. float
  96. calibrate_idle_rate (int iterations, int interval)
  97. {
  98.   if (proc_stat_fd < 0) {
  99.     proc_stat_fd = open (PROC_STAT_FILE_NAME, O_RDONLY, NULL);
  100.     if (proc_stat_fd < 0) {
  101.       fprintf (stderr, "Cannot open %s!n", PROC_STAT_FILE_NAME);
  102.       exit (1);
  103.     };
  104.   };
  105.   if (!proc_stat_buf) {
  106.     proc_stat_buflen = N_CPU_LINES (lib_num_loc_cpus) * CPU_LINE_LENGTH;
  107.     if (debug) {
  108.       fprintf(where,
  109.       "calibrate: lib_num_loc_cpus %d lines %d CPU_LINE_LENGTH %d proc_stat_buflen %dn",
  110.       lib_num_loc_cpus,
  111.       N_CPU_LINES(lib_num_loc_cpus),
  112.       CPU_LINE_LENGTH,
  113.       proc_stat_buflen);
  114.       fflush(where);
  115.     }
  116.     proc_stat_buf = (char *)malloc (proc_stat_buflen);
  117.     if (!proc_stat_buf) {
  118.       fprintf (stderr, "Cannot allocate buffer memory!n");
  119.       exit (1);
  120.     };
  121.   };
  122.   return sysconf (_SC_CLK_TCK);
  123. }
  124. void
  125. get_cpu_idle (uint64_t *res)
  126. {
  127.   int space;
  128.   int i;
  129.   int n = lib_num_loc_cpus;
  130.   char *p = proc_stat_buf;
  131.   lseek (proc_stat_fd, 0, SEEK_SET);
  132.   read (proc_stat_fd, p, proc_stat_buflen);
  133.   if (debug) {
  134.     fprintf(where,"proc_stat_buf '%.*s'n",proc_stat_buflen,p);
  135.     fflush(where);
  136.   }
  137.   /* Skip first line (total) on SMP */
  138.   if (n > 1) p = strchr (p, 'n');
  139.   /* Idle time is the 4th space-separated token */
  140.   for (i = 0; i < n; i++) {
  141.     for (space = 0; space < 4; space ++) {
  142.       p = strchr (p, ' ');
  143.       while (*++p == ' ');
  144.     };
  145.     res[i] = strtoul (p, &p, 10);
  146.     if (debug) {
  147.       fprintf(where,"res[%d] is %llun",i,res[i]);
  148.       fflush(where);
  149.     }
  150.     p = strchr (p, 'n');
  151.   };
  152. }
  153. /* take the initial timestamp and start collecting CPU utilization if
  154.    requested */
  155. void
  156. measure_cpu_start()
  157. {
  158.   cpu_method = PROC_STAT;
  159.   get_cpu_idle(lib_start_count);
  160. }
  161. /* collect final CPU utilization raw data */
  162. void
  163. measure_cpu_stop()
  164. {
  165.   get_cpu_idle(lib_end_count);
  166. }
  167. float
  168. calc_cpu_util_internal(float elapsed_time)
  169. {
  170.   int i;
  171.   float actual_rate;
  172.   float correction_factor;
  173.   lib_local_cpu_util = (float)0.0;
  174.   /* It is possible that the library measured a time other than */
  175.   /* the one that the user want for the cpu utilization */
  176.   /* calculations - for example, tests that were ended by */
  177.   /* watchdog timers such as the udp stream test. We let these */
  178.   /* tests tell up what the elapsed time should be. */
  179.   
  180.   if (elapsed_time != 0.0) {
  181.     correction_factor = (float) 1.0 + 
  182.       ((lib_elapsed - elapsed_time) / elapsed_time);
  183.   }
  184.   else {
  185.     correction_factor = (float) 1.0;
  186.   }
  187.   for (i = 0; i < lib_num_loc_cpus; i++) {
  188.     /* it would appear that on some systems, in loopback, nice is
  189.      *very* effective, causing the looper process to stop dead in its
  190.      tracks. if this happens, we need to ensure that the calculation
  191.      does not go south. raj 6/95 and if we run completely out of idle,
  192.      the same thing could in theory happen to the USE_KSTAT path. raj
  193.      8/2000 */ 
  194.     
  195.     if (lib_end_count[i] == lib_start_count[i]) {
  196.       lib_end_count[i]++;
  197.     }
  198.     
  199.     actual_rate = (lib_end_count[i] > lib_start_count[i]) ?
  200.       (float)(lib_end_count[i] - lib_start_count[i])/lib_elapsed :
  201.       (float)(lib_end_count[i] - lib_start_count[i] +
  202.       MAXLONG)/ lib_elapsed;
  203.     lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
  204.       lib_local_maxrate * 100;
  205.     if (debug) {
  206.       fprintf(where,
  207.               "calc_cpu_util: actual_rate on processor %d is %f start %llx end %llx util %fn",
  208.               i,
  209.               actual_rate,
  210.               lib_start_count[i],
  211.               lib_end_count[i],
  212.       lib_local_per_cpu_util[i]);
  213.     }
  214.     lib_local_cpu_util += lib_local_per_cpu_util[i];
  215.   }
  216.   /* we want the average across all n processors */
  217.   lib_local_cpu_util /= (float)lib_num_loc_cpus;
  218.   
  219.   lib_local_cpu_util *= correction_factor;
  220.   return lib_local_cpu_util;
  221. }
  222. void
  223. cpu_start_internal(void)
  224. {
  225.   get_cpu_idle(lib_start_count);
  226.   return;
  227. }
  228. void
  229. cpu_stop_internal(void)
  230. {
  231.   get_cpu_idle(lib_end_count);
  232. }