percentages.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. /*
  2. * The percentages function was written by William LeFebvre and is part
  3. * of the 'top' utility. His copyright statement is below.
  4. */
  5. /*
  6. * Top users/processes display for Unix
  7. * Version 3
  8. *
  9. * This program may be freely redistributed,
  10. * but this entire comment MUST remain intact.
  11. *
  12. * Copyright (c) 1984, 1989, William LeFebvre, Rice University
  13. * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
  14. */
  15. #include <sys/types.h>
  16. #define UQUAD_MAX ((u_int64_t)0-1)
  17. #define QUAD_MAX ((int64_t)(UQUAD_MAX >> 1))
  18. /*
  19. * percentages(cnt, out, new, old, diffs) - calculate percentage change
  20. * between array "old" and "new", putting the percentages i "out".
  21. * "cnt" is size of each array and "diffs" is used for scratch space.
  22. * The array "old" is updated on each call.
  23. * The routine assumes modulo arithmetic. This function is especially
  24. * useful on BSD mchines for calculating cpu state percentages.
  25. */
  26. int
  27. percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs)
  28. {
  29. int64_t change, total_change, *dp, half_total;
  30. int i;
  31. /* initialization */
  32. total_change = 0;
  33. dp = diffs;
  34. /* calculate changes for each state and the overall change */
  35. for (i = 0; i < cnt; i++) {
  36. if ((change = *new - *old) < 0) {
  37. /* this only happens when the counter wraps */
  38. change = (QUAD_MAX - *old) + *new;
  39. }
  40. total_change += (*dp++ = change);
  41. *old++ = *new++;
  42. }
  43. /* avoid divide by zero potential */
  44. if (total_change == 0)
  45. total_change = 1;
  46. /* calculate percentages based on overall change, rounding up */
  47. half_total = total_change / 2l;
  48. for (i = 0; i < cnt; i++)
  49. *out++ = ((*diffs++ * 1000 + half_total) / total_change);
  50. /* return the total in case the caller wants to use it */
  51. return (total_change);
  52. }