Doubt in reference to CPU utilization of FreeBSD top code

My goal is to have CPU utilization logic in my application so I was referring to top implementation. However, I am having a missing link due to which in my application its displaying huge values over 10000%, could you please help me in understanding and fixing the same?

We are populating cp_time from the following sysctl. However, while calculating percentages I didn't see old value getting populated it's always 0, how is top code implementation in FreeBSD working for CPU utilization?
Any help would be greatly appreciated
Code:
get_system_info(struct system_info *si) {
.............................
..........................

if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1)
                 err(1, "sysctlbyname kern.cp_times");
         GETSYSCTL("kern.cp_time", cp_time);

/* convert cp_time counts to percentages */
  for (i = j = 0; i <= maxid; i++) {
          if ((cpumask & (1ul << i)) == 0)
                  continue;
          percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES],
              &pcpu_cp_time[j * CPUSTATES],                                           <===== only pcpu_cp_time is a valid value from sysctl cp_times , old      value(pcpu_cp_old) is always 0
              &pcpu_cp_old[j * CPUSTATES],
              &pcpu_cp_diff[j * CPUSTATES]);
          j++;
}
percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);


..................................

}


main()
{
..............................

(*d_cpustates)(system_info.cpustates    );    <=================================== Display logic here
......................

d_cpustates => i_cpustates (or u_cpustates)


  /* now walk thru the names and print the line */
while ((thisname = *names++) != NULL)
{
    if (*thisname != '\0')
          {
              /* retrieve the value and remember it */
              value = *states++;

              /* if percentage is >= 1000, print it as 100% */
              printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
                     (i++ % num_cpustates) == 0 ? "" : ", ",
                     ((float)value)/10.,
                     thisname);
          }
      }
}
 
If I remember correctly kern.cp_times sysctl(3) returns incremental counters. There are N ticks in each second and each CPU utilization component is increased with some part of that N, with respect of what CPU were doing during that second. Like if during that second CPU were 10% sys, 20% user, 70% idle, sys will be increased with 10% of N, user with 20% of N and idle with 70% of N.

That being said, you'll have to keep old state (old counter values), calculate increment for each component and divide to sum of all increments; pseudocode:
C:
sys_incr = new.sys - old.sys;
user_incr = new.user - old.user;
idle_incr = new.idle - old.idle;
tot_incr = sys_incr + user_incr + idle_incr;
sys_pct = sys_incr * 100.0 / tot_incr;
user_pct = user_incr * 100.0 / tot_incr;
idle_pct = idle_incr * 100.0 / tot_incr;

Most likely you don't copy pcpu_cp_time into pcpu_cp_old after calling percentages(), hence your old state is always zero.
 
Back
Top