CPUMeter.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. htop - CPUMeter.c
  3. (C) 2004-2011 Hisham H. Muhammad
  4. Released under the GNU GPLv2+, see the COPYING file
  5. in the source distribution for its full text.
  6. */
  7. #include "config.h" // IWYU pragma: keep
  8. #include "CPUMeter.h"
  9. #include <assert.h>
  10. #include <stdbool.h>
  11. #include <stddef.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "CRT.h"
  15. #include "Machine.h"
  16. #include "Macros.h"
  17. #include "Object.h"
  18. #include "Platform.h"
  19. #include "RichString.h"
  20. #include "Settings.h"
  21. #include "XUtils.h"
  22. static const int CPUMeter_attributes[] = {
  23. CPU_NICE,
  24. CPU_NORMAL,
  25. CPU_SYSTEM,
  26. CPU_IRQ,
  27. CPU_SOFTIRQ,
  28. CPU_STEAL,
  29. CPU_GUEST,
  30. CPU_IOWAIT
  31. };
  32. typedef struct CPUMeterData_ {
  33. unsigned int cpus;
  34. Meter** meters;
  35. } CPUMeterData;
  36. static void CPUMeter_init(Meter* this) {
  37. unsigned int cpu = this->param;
  38. const Machine* host = this->host;
  39. if (cpu == 0) {
  40. Meter_setCaption(this, "Avg");
  41. } else if (host->activeCPUs > 1) {
  42. char caption[10];
  43. xSnprintf(caption, sizeof(caption), "%3u", Settings_cpuId(host->settings, cpu - 1));
  44. Meter_setCaption(this, caption);
  45. }
  46. }
  47. // Custom uiName runtime logic to include the param (processor)
  48. static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) {
  49. assert(length > 0);
  50. if (this->param > 0)
  51. xSnprintf(buffer, length, "%s %u", Meter_uiName(this), this->param);
  52. else
  53. xSnprintf(buffer, length, "%s", Meter_uiName(this));
  54. }
  55. static void CPUMeter_updateValues(Meter* this) {
  56. memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT);
  57. const Machine* host = this->host;
  58. const Settings* settings = host->settings;
  59. unsigned int cpu = this->param;
  60. if (cpu > host->existingCPUs) {
  61. xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "absent");
  62. return;
  63. }
  64. double percent = Platform_setCPUValues(this, cpu);
  65. if (!isNonnegative(percent)) {
  66. xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "offline");
  67. return;
  68. }
  69. char cpuUsageBuffer[8] = { 0 };
  70. char cpuFrequencyBuffer[16] = { 0 };
  71. char cpuTemperatureBuffer[16] = { 0 };
  72. if (settings->showCPUUsage) {
  73. xSnprintf(cpuUsageBuffer, sizeof(cpuUsageBuffer), "%.1f%%", percent);
  74. }
  75. if (settings->showCPUFrequency) {
  76. double cpuFrequency = this->values[CPU_METER_FREQUENCY];
  77. if (isNonnegative(cpuFrequency)) {
  78. xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency);
  79. } else {
  80. xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
  81. }
  82. }
  83. #ifdef BUILD_WITH_CPU_TEMP
  84. if (settings->showCPUTemperature) {
  85. double cpuTemperature = this->values[CPU_METER_TEMPERATURE];
  86. if (isNaN(cpuTemperature))
  87. xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A");
  88. else if (settings->degreeFahrenheit)
  89. xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%3d%sF", (int)(cpuTemperature * 9 / 5 + 32), CRT_degreeSign);
  90. else
  91. xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%d%sC", (int)cpuTemperature, CRT_degreeSign);
  92. }
  93. #endif
  94. xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%s%s%s%s",
  95. cpuUsageBuffer,
  96. (cpuUsageBuffer[0] && (cpuFrequencyBuffer[0] || cpuTemperatureBuffer[0])) ? " " : "",
  97. cpuFrequencyBuffer,
  98. (cpuFrequencyBuffer[0] && cpuTemperatureBuffer[0]) ? " " : "",
  99. cpuTemperatureBuffer);
  100. }
  101. static void CPUMeter_display(const Object* cast, RichString* out) {
  102. char buffer[50];
  103. int len;
  104. const Meter* this = (const Meter*)cast;
  105. const Machine* host = this->host;
  106. const Settings* settings = host->settings;
  107. if (this->param > host->existingCPUs) {
  108. RichString_appendAscii(out, CRT_colors[METER_SHADOW], " absent");
  109. return;
  110. }
  111. if (this->curItems == 0) {
  112. RichString_appendAscii(out, CRT_colors[METER_SHADOW], " offline");
  113. return;
  114. }
  115. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NORMAL]);
  116. RichString_appendAscii(out, CRT_colors[METER_TEXT], ":");
  117. RichString_appendnAscii(out, CRT_colors[CPU_NORMAL], buffer, len);
  118. if (settings->detailedCPUTime) {
  119. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]);
  120. RichString_appendAscii(out, CRT_colors[METER_TEXT], "sy:");
  121. RichString_appendnAscii(out, CRT_colors[CPU_SYSTEM], buffer, len);
  122. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]);
  123. RichString_appendAscii(out, CRT_colors[METER_TEXT], "ni:");
  124. RichString_appendnAscii(out, CRT_colors[CPU_NICE_TEXT], buffer, len);
  125. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]);
  126. RichString_appendAscii(out, CRT_colors[METER_TEXT], "hi:");
  127. RichString_appendnAscii(out, CRT_colors[CPU_IRQ], buffer, len);
  128. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_SOFTIRQ]);
  129. RichString_appendAscii(out, CRT_colors[METER_TEXT], "si:");
  130. RichString_appendnAscii(out, CRT_colors[CPU_SOFTIRQ], buffer, len);
  131. if (isNonnegative(this->values[CPU_METER_STEAL])) {
  132. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_STEAL]);
  133. RichString_appendAscii(out, CRT_colors[METER_TEXT], "st:");
  134. RichString_appendnAscii(out, CRT_colors[CPU_STEAL], buffer, len);
  135. }
  136. if (isNonnegative(this->values[CPU_METER_GUEST])) {
  137. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_GUEST]);
  138. RichString_appendAscii(out, CRT_colors[METER_TEXT], "gu:");
  139. RichString_appendnAscii(out, CRT_colors[CPU_GUEST], buffer, len);
  140. }
  141. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IOWAIT]);
  142. RichString_appendAscii(out, CRT_colors[METER_TEXT], "wa:");
  143. RichString_appendnAscii(out, CRT_colors[CPU_IOWAIT], buffer, len);
  144. } else {
  145. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_KERNEL]);
  146. RichString_appendAscii(out, CRT_colors[METER_TEXT], "sys:");
  147. RichString_appendnAscii(out, CRT_colors[CPU_SYSTEM], buffer, len);
  148. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_NICE]);
  149. RichString_appendAscii(out, CRT_colors[METER_TEXT], "low:");
  150. RichString_appendnAscii(out, CRT_colors[CPU_NICE_TEXT], buffer, len);
  151. if (isNonnegative(this->values[CPU_METER_IRQ])) {
  152. len = xSnprintf(buffer, sizeof(buffer), "%5.1f%% ", this->values[CPU_METER_IRQ]);
  153. RichString_appendAscii(out, CRT_colors[METER_TEXT], "vir:");
  154. RichString_appendnAscii(out, CRT_colors[CPU_GUEST], buffer, len);
  155. }
  156. }
  157. if (settings->showCPUFrequency) {
  158. char cpuFrequencyBuffer[10];
  159. double cpuFrequency = this->values[CPU_METER_FREQUENCY];
  160. if (isNonnegative(cpuFrequency)) {
  161. len = xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz ", (unsigned)cpuFrequency);
  162. } else {
  163. len = xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A ");
  164. }
  165. RichString_appendAscii(out, CRT_colors[METER_TEXT], "freq: ");
  166. RichString_appendnWide(out, CRT_colors[METER_VALUE], cpuFrequencyBuffer, len);
  167. }
  168. #ifdef BUILD_WITH_CPU_TEMP
  169. if (settings->showCPUTemperature) {
  170. char cpuTemperatureBuffer[10];
  171. double cpuTemperature = this->values[CPU_METER_TEMPERATURE];
  172. if (isNaN(cpuTemperature)) {
  173. len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A");
  174. } else if (settings->degreeFahrenheit) {
  175. len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sF", cpuTemperature * 9 / 5 + 32, CRT_degreeSign);
  176. } else {
  177. len = xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%5.1f%sC", cpuTemperature, CRT_degreeSign);
  178. }
  179. RichString_appendAscii(out, CRT_colors[METER_TEXT], "temp:");
  180. RichString_appendnWide(out, CRT_colors[METER_VALUE], cpuTemperatureBuffer, len);
  181. }
  182. #endif
  183. }
  184. static void AllCPUsMeter_getRange(const Meter* this, int* start, int* count) {
  185. const CPUMeterData* data = this->meterData;
  186. unsigned int cpus = data->cpus;
  187. switch (Meter_name(this)[0]) {
  188. default:
  189. case 'A': // All
  190. *start = 0;
  191. *count = cpus;
  192. break;
  193. case 'L': // First Half
  194. *start = 0;
  195. *count = (cpus + 1) / 2;
  196. break;
  197. case 'R': // Second Half
  198. *start = (cpus + 1) / 2;
  199. *count = cpus / 2;
  200. break;
  201. }
  202. }
  203. static void AllCPUsMeter_updateValues(Meter* this) {
  204. CPUMeterData* data = this->meterData;
  205. Meter** meters = data->meters;
  206. int start, count;
  207. AllCPUsMeter_getRange(this, &start, &count);
  208. for (int i = 0; i < count; i++)
  209. Meter_updateValues(meters[i]);
  210. }
  211. static void CPUMeterCommonInit(Meter* this) {
  212. unsigned int cpus = this->host->existingCPUs;
  213. CPUMeterData* data = this->meterData;
  214. if (!data) {
  215. data = this->meterData = xMalloc(sizeof(CPUMeterData));
  216. data->cpus = cpus;
  217. data->meters = xCalloc(cpus, sizeof(Meter*));
  218. }
  219. Meter** meters = data->meters;
  220. int start, count;
  221. AllCPUsMeter_getRange(this, &start, &count);
  222. for (int i = 0; i < count; i++) {
  223. if (!meters[i])
  224. meters[i] = Meter_new(this->host, start + i + 1, (const MeterClass*) Class(CPUMeter));
  225. Meter_init(meters[i]);
  226. }
  227. }
  228. static void CPUMeterCommonUpdateMode(Meter* this, MeterModeId mode, int ncol) {
  229. CPUMeterData* data = this->meterData;
  230. Meter** meters = data->meters;
  231. this->mode = mode;
  232. int start, count;
  233. AllCPUsMeter_getRange(this, &start, &count);
  234. for (int i = 0; i < count; i++) {
  235. Meter_setMode(meters[i], mode);
  236. }
  237. int h = meters[0]->h;
  238. assert(h > 0);
  239. this->h = h * ((count + ncol - 1) / ncol);
  240. }
  241. static void AllCPUsMeter_done(Meter* this) {
  242. CPUMeterData* data = this->meterData;
  243. Meter** meters = data->meters;
  244. int start, count;
  245. AllCPUsMeter_getRange(this, &start, &count);
  246. for (int i = 0; i < count; i++)
  247. Meter_delete((Object*)meters[i]);
  248. free(data->meters);
  249. free(data);
  250. }
  251. static void SingleColCPUsMeter_updateMode(Meter* this, MeterModeId mode) {
  252. CPUMeterCommonUpdateMode(this, mode, 1);
  253. }
  254. static void DualColCPUsMeter_updateMode(Meter* this, MeterModeId mode) {
  255. CPUMeterCommonUpdateMode(this, mode, 2);
  256. }
  257. static void QuadColCPUsMeter_updateMode(Meter* this, MeterModeId mode) {
  258. CPUMeterCommonUpdateMode(this, mode, 4);
  259. }
  260. static void OctoColCPUsMeter_updateMode(Meter* this, MeterModeId mode) {
  261. CPUMeterCommonUpdateMode(this, mode, 8);
  262. }
  263. static void CPUMeterCommonDraw(Meter* this, int x, int y, int w, int ncol) {
  264. CPUMeterData* data = this->meterData;
  265. Meter** meters = data->meters;
  266. int start, count;
  267. AllCPUsMeter_getRange(this, &start, &count);
  268. int colwidth = (w - ncol) / ncol + 1;
  269. int diff = (w - (colwidth * ncol));
  270. int nrows = (count + ncol - 1) / ncol;
  271. for (int i = 0; i < count; i++) {
  272. int d = (i / nrows) > diff ? diff : (i / nrows); // dynamic spacer
  273. int xpos = x + ((i / nrows) * colwidth) + d;
  274. int ypos = y + ((i % nrows) * meters[0]->h);
  275. meters[i]->draw(meters[i], xpos, ypos, colwidth);
  276. }
  277. }
  278. static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) {
  279. CPUMeterCommonDraw(this, x, y, w, 2);
  280. }
  281. static void QuadColCPUsMeter_draw(Meter* this, int x, int y, int w) {
  282. CPUMeterCommonDraw(this, x, y, w, 4);
  283. }
  284. static void OctoColCPUsMeter_draw(Meter* this, int x, int y, int w) {
  285. CPUMeterCommonDraw(this, x, y, w, 8);
  286. }
  287. static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) {
  288. CPUMeterData* data = this->meterData;
  289. Meter** meters = data->meters;
  290. int start, count;
  291. AllCPUsMeter_getRange(this, &start, &count);
  292. for (int i = 0; i < count; i++) {
  293. meters[i]->draw(meters[i], x, y, w);
  294. y += meters[i]->h;
  295. }
  296. }
  297. const MeterClass CPUMeter_class = {
  298. .super = {
  299. .extends = Class(Meter),
  300. .delete = Meter_delete,
  301. .display = CPUMeter_display
  302. },
  303. .updateValues = CPUMeter_updateValues,
  304. .getUiName = CPUMeter_getUiName,
  305. .defaultMode = BAR_METERMODE,
  306. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  307. .maxItems = CPU_METER_ITEMCOUNT,
  308. .total = 100.0,
  309. .attributes = CPUMeter_attributes,
  310. .name = "CPU",
  311. .uiName = "CPU",
  312. .caption = "CPU",
  313. .init = CPUMeter_init
  314. };
  315. const MeterClass AllCPUsMeter_class = {
  316. .super = {
  317. .extends = Class(Meter),
  318. .delete = Meter_delete,
  319. .display = CPUMeter_display
  320. },
  321. .updateValues = AllCPUsMeter_updateValues,
  322. .defaultMode = BAR_METERMODE,
  323. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  324. .total = 100.0,
  325. .attributes = CPUMeter_attributes,
  326. .name = "AllCPUs",
  327. .uiName = "CPUs (1/1)",
  328. .description = "CPUs (1/1): all CPUs",
  329. .caption = "CPU",
  330. .draw = SingleColCPUsMeter_draw,
  331. .init = CPUMeterCommonInit,
  332. .updateMode = SingleColCPUsMeter_updateMode,
  333. .done = AllCPUsMeter_done
  334. };
  335. const MeterClass AllCPUs2Meter_class = {
  336. .super = {
  337. .extends = Class(Meter),
  338. .delete = Meter_delete,
  339. .display = CPUMeter_display
  340. },
  341. .updateValues = AllCPUsMeter_updateValues,
  342. .defaultMode = BAR_METERMODE,
  343. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  344. .isMultiColumn = true,
  345. .total = 100.0,
  346. .attributes = CPUMeter_attributes,
  347. .name = "AllCPUs2",
  348. .uiName = "CPUs (1&2/2)",
  349. .description = "CPUs (1&2/2): all CPUs in 2 shorter columns",
  350. .caption = "CPU",
  351. .draw = DualColCPUsMeter_draw,
  352. .init = CPUMeterCommonInit,
  353. .updateMode = DualColCPUsMeter_updateMode,
  354. .done = AllCPUsMeter_done
  355. };
  356. const MeterClass LeftCPUsMeter_class = {
  357. .super = {
  358. .extends = Class(Meter),
  359. .delete = Meter_delete,
  360. .display = CPUMeter_display
  361. },
  362. .updateValues = AllCPUsMeter_updateValues,
  363. .defaultMode = BAR_METERMODE,
  364. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  365. .isMultiColumn = true,
  366. .total = 100.0,
  367. .attributes = CPUMeter_attributes,
  368. .name = "LeftCPUs",
  369. .uiName = "CPUs (1/2)",
  370. .description = "CPUs (1/2): first half of list",
  371. .caption = "CPU",
  372. .draw = SingleColCPUsMeter_draw,
  373. .init = CPUMeterCommonInit,
  374. .updateMode = SingleColCPUsMeter_updateMode,
  375. .done = AllCPUsMeter_done
  376. };
  377. const MeterClass RightCPUsMeter_class = {
  378. .super = {
  379. .extends = Class(Meter),
  380. .delete = Meter_delete,
  381. .display = CPUMeter_display
  382. },
  383. .updateValues = AllCPUsMeter_updateValues,
  384. .defaultMode = BAR_METERMODE,
  385. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  386. .isMultiColumn = true,
  387. .total = 100.0,
  388. .attributes = CPUMeter_attributes,
  389. .name = "RightCPUs",
  390. .uiName = "CPUs (2/2)",
  391. .description = "CPUs (2/2): second half of list",
  392. .caption = "CPU",
  393. .draw = SingleColCPUsMeter_draw,
  394. .init = CPUMeterCommonInit,
  395. .updateMode = SingleColCPUsMeter_updateMode,
  396. .done = AllCPUsMeter_done
  397. };
  398. const MeterClass LeftCPUs2Meter_class = {
  399. .super = {
  400. .extends = Class(Meter),
  401. .delete = Meter_delete,
  402. .display = CPUMeter_display
  403. },
  404. .updateValues = AllCPUsMeter_updateValues,
  405. .defaultMode = BAR_METERMODE,
  406. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  407. .isMultiColumn = true,
  408. .total = 100.0,
  409. .attributes = CPUMeter_attributes,
  410. .name = "LeftCPUs2",
  411. .uiName = "CPUs (1&2/4)",
  412. .description = "CPUs (1&2/4): first half in 2 shorter columns",
  413. .caption = "CPU",
  414. .draw = DualColCPUsMeter_draw,
  415. .init = CPUMeterCommonInit,
  416. .updateMode = DualColCPUsMeter_updateMode,
  417. .done = AllCPUsMeter_done
  418. };
  419. const MeterClass RightCPUs2Meter_class = {
  420. .super = {
  421. .extends = Class(Meter),
  422. .delete = Meter_delete,
  423. .display = CPUMeter_display
  424. },
  425. .updateValues = AllCPUsMeter_updateValues,
  426. .defaultMode = BAR_METERMODE,
  427. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  428. .isMultiColumn = true,
  429. .total = 100.0,
  430. .attributes = CPUMeter_attributes,
  431. .name = "RightCPUs2",
  432. .uiName = "CPUs (3&4/4)",
  433. .description = "CPUs (3&4/4): second half in 2 shorter columns",
  434. .caption = "CPU",
  435. .draw = DualColCPUsMeter_draw,
  436. .init = CPUMeterCommonInit,
  437. .updateMode = DualColCPUsMeter_updateMode,
  438. .done = AllCPUsMeter_done
  439. };
  440. const MeterClass AllCPUs4Meter_class = {
  441. .super = {
  442. .extends = Class(Meter),
  443. .delete = Meter_delete,
  444. .display = CPUMeter_display
  445. },
  446. .updateValues = AllCPUsMeter_updateValues,
  447. .defaultMode = BAR_METERMODE,
  448. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  449. .isMultiColumn = true,
  450. .total = 100.0,
  451. .attributes = CPUMeter_attributes,
  452. .name = "AllCPUs4",
  453. .uiName = "CPUs (1&2&3&4/4)",
  454. .description = "CPUs (1&2&3&4/4): all CPUs in 4 shorter columns",
  455. .caption = "CPU",
  456. .draw = QuadColCPUsMeter_draw,
  457. .init = CPUMeterCommonInit,
  458. .updateMode = QuadColCPUsMeter_updateMode,
  459. .done = AllCPUsMeter_done
  460. };
  461. const MeterClass LeftCPUs4Meter_class = {
  462. .super = {
  463. .extends = Class(Meter),
  464. .delete = Meter_delete,
  465. .display = CPUMeter_display
  466. },
  467. .updateValues = AllCPUsMeter_updateValues,
  468. .defaultMode = BAR_METERMODE,
  469. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  470. .isMultiColumn = true,
  471. .total = 100.0,
  472. .attributes = CPUMeter_attributes,
  473. .name = "LeftCPUs4",
  474. .uiName = "CPUs (1-4/8)",
  475. .description = "CPUs (1-4/8): first half in 4 shorter columns",
  476. .caption = "CPU",
  477. .draw = QuadColCPUsMeter_draw,
  478. .init = CPUMeterCommonInit,
  479. .updateMode = QuadColCPUsMeter_updateMode,
  480. .done = AllCPUsMeter_done
  481. };
  482. const MeterClass RightCPUs4Meter_class = {
  483. .super = {
  484. .extends = Class(Meter),
  485. .delete = Meter_delete,
  486. .display = CPUMeter_display
  487. },
  488. .updateValues = AllCPUsMeter_updateValues,
  489. .defaultMode = BAR_METERMODE,
  490. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  491. .isMultiColumn = true,
  492. .total = 100.0,
  493. .attributes = CPUMeter_attributes,
  494. .name = "RightCPUs4",
  495. .uiName = "CPUs (5-8/8)",
  496. .description = "CPUs (5-8/8): second half in 4 shorter columns",
  497. .caption = "CPU",
  498. .draw = QuadColCPUsMeter_draw,
  499. .init = CPUMeterCommonInit,
  500. .updateMode = QuadColCPUsMeter_updateMode,
  501. .done = AllCPUsMeter_done
  502. };
  503. const MeterClass AllCPUs8Meter_class = {
  504. .super = {
  505. .extends = Class(Meter),
  506. .delete = Meter_delete,
  507. .display = CPUMeter_display
  508. },
  509. .updateValues = AllCPUsMeter_updateValues,
  510. .defaultMode = BAR_METERMODE,
  511. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  512. .isMultiColumn = true,
  513. .total = 100.0,
  514. .attributes = CPUMeter_attributes,
  515. .name = "AllCPUs8",
  516. .uiName = "CPUs (1-8/8)",
  517. .description = "CPUs (1-8/8): all CPUs in 8 shorter columns",
  518. .caption = "CPU",
  519. .draw = OctoColCPUsMeter_draw,
  520. .init = CPUMeterCommonInit,
  521. .updateMode = OctoColCPUsMeter_updateMode,
  522. .done = AllCPUsMeter_done
  523. };
  524. const MeterClass LeftCPUs8Meter_class = {
  525. .super = {
  526. .extends = Class(Meter),
  527. .delete = Meter_delete,
  528. .display = CPUMeter_display
  529. },
  530. .updateValues = AllCPUsMeter_updateValues,
  531. .defaultMode = BAR_METERMODE,
  532. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  533. .isMultiColumn = true,
  534. .total = 100.0,
  535. .attributes = CPUMeter_attributes,
  536. .name = "LeftCPUs8",
  537. .uiName = "CPUs (1-8/16)",
  538. .description = "CPUs (1-8/16): first half in 8 shorter columns",
  539. .caption = "CPU",
  540. .draw = OctoColCPUsMeter_draw,
  541. .init = CPUMeterCommonInit,
  542. .updateMode = OctoColCPUsMeter_updateMode,
  543. .done = AllCPUsMeter_done
  544. };
  545. const MeterClass RightCPUs8Meter_class = {
  546. .super = {
  547. .extends = Class(Meter),
  548. .delete = Meter_delete,
  549. .display = CPUMeter_display
  550. },
  551. .updateValues = AllCPUsMeter_updateValues,
  552. .defaultMode = BAR_METERMODE,
  553. .supportedModes = METERMODE_DEFAULT_SUPPORTED,
  554. .isMultiColumn = true,
  555. .total = 100.0,
  556. .attributes = CPUMeter_attributes,
  557. .name = "RightCPUs8",
  558. .uiName = "CPUs (9-16/16)",
  559. .description = "CPUs (9-16/16): second half in 8 shorter columns",
  560. .caption = "CPU",
  561. .draw = OctoColCPUsMeter_draw,
  562. .init = CPUMeterCommonInit,
  563. .updateMode = OctoColCPUsMeter_updateMode,
  564. .done = AllCPUsMeter_done
  565. };