sm_cpu.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (c) 2001-2007 Willem Dijkstra
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following
  13. * disclaimer in the documentation and/or other materials provided
  14. * with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  20. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  22. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  26. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. */
  30. /*
  31. * Get current cpu statistics in percentages (total of all counts = 100.0)
  32. * and returns them in symon_buf as
  33. *
  34. * user : nice : system : interrupt : idle
  35. *
  36. * This module uses the sysctl interface and can run as any user.
  37. */
  38. #include "conf.h"
  39. #include <sys/dkstat.h>
  40. #include <sys/param.h>
  41. #include <sys/sysctl.h>
  42. #include <errno.h>
  43. #include <limits.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include "error.h"
  47. #include "percentages.h"
  48. #include "symon.h"
  49. void
  50. init_cpu(struct stream *st)
  51. {
  52. char buf[SYMON_MAX_OBJSIZE];
  53. #ifdef HAS_KERN_CPTIME2
  54. const char *errstr;
  55. int mib[2] = {CTL_HW, HW_NCPU};
  56. int ncpu;
  57. long num;
  58. size_t size = sizeof(ncpu);
  59. #endif
  60. st->parg.cp.mib[0] = CTL_KERN;
  61. st->parg.cp.mib[1] = KERN_CPTIME;
  62. st->parg.cp.miblen = 2;
  63. #ifdef HAS_KERN_CPTIME2
  64. if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1) {
  65. warning("could not determine number of cpus: %.200s", strerror(errno));
  66. ncpu = 1;
  67. }
  68. num = strtonum(st->arg, 0, SYMON_MAXCPUID - 1, &errstr);
  69. if (errstr != NULL) {
  70. fatal("cpu(%.200s) is invalid: %.200s", st->arg, errstr);
  71. }
  72. if (ncpu > 1) {
  73. st->parg.cp.mib[0] = CTL_KERN;
  74. st->parg.cp.mib[1] = KERN_CPTIME2;
  75. st->parg.cp.mib[2] = num;
  76. st->parg.cp.miblen = 3;
  77. if (st->parg.cp.mib[2] >= ncpu) {
  78. fatal("cpu(%d) is not present", st->parg.cp.mib[2]);
  79. }
  80. }
  81. #endif
  82. /* Call get_cpu once to fill the cp_old structure */
  83. get_cpu(buf, sizeof(buf), st);
  84. info("started module cpu(%.200s)", st->arg);
  85. }
  86. void
  87. gets_cpu()
  88. {
  89. /* EMPTY */
  90. }
  91. int
  92. get_cpu(char *symon_buf, int maxlen, struct stream *st)
  93. {
  94. int i, total;
  95. size_t len;
  96. len = sizeof(st->parg.cp.time2);
  97. if (sysctl(st->parg.cp.mib, st->parg.cp.miblen, &st->parg.cp.time2, &len, NULL, 0) < 0) {
  98. warning("%s:%d: sysctl kern.cp_time* for cpu%d failed", __FILE__, __LINE__,
  99. st->parg.cp.mib[2]);
  100. return 0;
  101. }
  102. /* sysctl will return 32 bit longs for CPTIME and 64 bit longs for CPTIME2 */
  103. if (st->parg.cp.mib[1] == KERN_CPTIME) {
  104. bcopy(st->parg.cp.time2, st->parg.cp.time1, sizeof(st->parg.cp.time1));
  105. for (i = 0; i < CPUSTATES; i++) {
  106. st->parg.cp.time2[i] = (int64_t) st->parg.cp.time1[i];
  107. }
  108. }
  109. /* convert cp_time counts to percentages */
  110. total = percentages(CPUSTATES, st->parg.cp.states, st->parg.cp.time2, st->parg.cp.old, st->parg.cp.diff);
  111. return snpack(symon_buf, maxlen, st->arg, MT_CPU,
  112. (double) (st->parg.cp.states[CP_USER] / 10.0),
  113. (double) (st->parg.cp.states[CP_NICE] / 10.0),
  114. (double) (st->parg.cp.states[CP_SYS] / 10.0),
  115. (double) (st->parg.cp.states[CP_INTR] / 10.0),
  116. (double) (st->parg.cp.states[CP_IDLE] / 10.0));
  117. }