CPUMeter.c 6.18 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop - CPUMeter.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#include "CPUMeter.h"
#include "Meter.h"

#include "ProcessList.h"

#include <stdlib.h>
#include <curses.h>
#include <string.h>
#include <math.h>

#include "debug.h"
#include <assert.h>

21
int CPUMeter_attributes[] = {
22
   CPU_NICE, CPU_NORMAL, CPU_KERNEL, CPU_IRQ, CPU_SOFTIRQ, CPU_IOWAIT, CPU_STEAL, CPU_GUEST
23
};
Hisham Muhammad's avatar
Hisham Muhammad committed
24
25
26
27
28
29
30
31

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif

32
static void CPUMeter_init(Meter* this) {
33
34
   int cpu = this->param;
   if (this->pl->cpuCount > 1) {
35
      char caption[10];
36
      sprintf(caption, "%-3d", ProcessList_cpuId(this->pl, cpu));
37
      Meter_setCaption(this, caption);
Hisham Muhammad's avatar
Hisham Muhammad committed
38
   }
39
40
   if (this->param == 0)
      Meter_setCaption(this, "Avg");
Hisham Muhammad's avatar
Hisham Muhammad committed
41
42
}

43
static void CPUMeter_setValues(Meter* this, char* buffer, int size) {
44
   ProcessList* pl = this->pl;
45
46
   int cpu = this->param;
   if (cpu > this->pl->cpuCount) {
Hisham Muhammad's avatar
Hisham Muhammad committed
47
48
49
      snprintf(buffer, size, "absent");
      return;
   }
50
51
52
53
54
   CPUData* cpuData = &(pl->cpus[cpu]);
   double total = (double) ( cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod);
   double percent;
   this->values[0] = cpuData->nicePeriod / total * 100.0;
   this->values[1] = cpuData->userPeriod / total * 100.0;
55
   if (pl->detailedCPUTime) {
56
57
58
59
60
61
62
63
      this->values[2] = cpuData->systemPeriod / total * 100.0;
      this->values[3] = cpuData->irqPeriod / total * 100.0;
      this->values[4] = cpuData->softIrqPeriod / total * 100.0;
      this->values[5] = cpuData->ioWaitPeriod / total * 100.0;
      this->values[6] = cpuData->stealPeriod / total * 100.0;
      this->values[7] = cpuData->guestPeriod / total * 100.0;
      this->type->items = 8;
      percent = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2]+
64
                       this->values[3]+this->values[4])));
65
   } else {
66
67
68
69
      this->values[2] = cpuData->systemAllPeriod / total * 100.0;
      this->values[3] = (cpuData->stealPeriod + cpuData->guestPeriod) / total * 100.0;
      this->type->items = 4;
      percent = MIN(100.0, MAX(0.0, (this->values[0]+this->values[1]+this->values[2]+this->values[3])));
70
   }
71
72
   if (isnan(percent)) percent = 0.0;
   snprintf(buffer, size, "%5.1f%%", percent);
Hisham Muhammad's avatar
Hisham Muhammad committed
73
74
}

75
static void CPUMeter_display(Object* cast, RichString* out) {
Hisham Muhammad's avatar
Hisham Muhammad committed
76
77
   char buffer[50];
   Meter* this = (Meter*)cast;
78
   RichString_prune(out);
79
   if (this->param > this->pl->cpuCount) {
Hisham Muhammad's avatar
Hisham Muhammad committed
80
81
82
      RichString_append(out, CRT_colors[METER_TEXT], "absent");
      return;
   }
83
   sprintf(buffer, "%5.1f%% ", this->values[1]);
Hisham Muhammad's avatar
Hisham Muhammad committed
84
85
   RichString_append(out, CRT_colors[METER_TEXT], ":");
   RichString_append(out, CRT_colors[CPU_NORMAL], buffer);
86
   if (this->pl->detailedCPUTime) {
87
88
89
90
91
92
93
94
95
96
97
98
      sprintf(buffer, "%5.1f%% ", this->values[2]);
      RichString_append(out, CRT_colors[METER_TEXT], "sy:");
      RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
      sprintf(buffer, "%5.1f%% ", this->values[0]);
      RichString_append(out, CRT_colors[METER_TEXT], "ni:");
      RichString_append(out, CRT_colors[CPU_NICE], buffer);
      sprintf(buffer, "%5.1f%% ", this->values[3]);
      RichString_append(out, CRT_colors[METER_TEXT], "hi:");
      RichString_append(out, CRT_colors[CPU_IRQ], buffer);
      sprintf(buffer, "%5.1f%% ", this->values[4]);
      RichString_append(out, CRT_colors[METER_TEXT], "si:");
      RichString_append(out, CRT_colors[CPU_SOFTIRQ], buffer);
99
100
101
      sprintf(buffer, "%5.1f%% ", this->values[5]);
      RichString_append(out, CRT_colors[METER_TEXT], "wa:");
      RichString_append(out, CRT_colors[CPU_IOWAIT], buffer);
102
103
104
105
106
107
108
109
      sprintf(buffer, "%5.1f%% ", this->values[6]);
      RichString_append(out, CRT_colors[METER_TEXT], "st:");
      RichString_append(out, CRT_colors[CPU_STEAL], buffer);
      if (this->values[7]) {
         sprintf(buffer, "%5.1f%% ", this->values[7]);
         RichString_append(out, CRT_colors[METER_TEXT], "gu:");
         RichString_append(out, CRT_colors[CPU_GUEST], buffer);
      }
110
111
112
113
114
115
116
   } else {
      sprintf(buffer, "%5.1f%% ", this->values[2]);
      RichString_append(out, CRT_colors[METER_TEXT], "sys:");
      RichString_append(out, CRT_colors[CPU_KERNEL], buffer);
      sprintf(buffer, "%5.1f%% ", this->values[0]);
      RichString_append(out, CRT_colors[METER_TEXT], "low:");
      RichString_append(out, CRT_colors[CPU_NICE], buffer);
117
118
119
120
121
      if (this->values[3]) {
         sprintf(buffer, "%5.1f%% ", this->values[3]);
         RichString_append(out, CRT_colors[METER_TEXT], "vir:");
         RichString_append(out, CRT_colors[CPU_GUEST], buffer);
      }
122
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
123
}
124

125
static void AllCPUsMeter_init(Meter* this) {
126
   int cpus = this->pl->cpuCount;
127
128
   if (!this->drawData)
      this->drawData = calloc(sizeof(Meter*), cpus);
129
   Meter** meters = (Meter**) this->drawData;
130
131
132
133
134
   for (int i = 0; i < cpus; i++) {
      if (!meters[i])
         meters[i] = Meter_new(this->pl, i+1, &CPUMeter);
      meters[i]->type->init(meters[i]);
   }
135
   this->h = Meter_modes[this->mode]->h * cpus;
136
137
}

138
static void AllCPUsMeter_done(Meter* this) {
139
   int cpus = this->pl->cpuCount;
140
   Meter** meters = (Meter**) this->drawData;
141
   for (int i = 0; i < cpus; i++)
142
143
144
      Meter_delete((Object*)meters[i]);
}

145
static void AllCPUsMeter_setMode(Meter* this, int mode) {
146
   this->mode = mode;
147
   int cpus = this->pl->cpuCount;
148
   int h = Meter_modes[this->mode]->h;
149
   this->h = h * cpus;
150
151
}

152
static void AllCPUsMeter_draw(Meter* this, int x, int y, int w) {
153
   int cpus = this->pl->cpuCount;
154
   Meter** meters = (Meter**) this->drawData;
155
   for (int i = 0; i < cpus; i++) {
156
      Meter_setMode(meters[i], this->mode);
157
158
      meters[i]->draw(meters[i], x, y, w);
      y += meters[i]->h;
159
160
   }
}
161
162
163
164
165

MeterType CPUMeter = {
   .setValues = CPUMeter_setValues, 
   .display = CPUMeter_display,
   .mode = BAR_METERMODE,
166
   .items = 8,
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
   .total = 100.0,
   .attributes = CPUMeter_attributes, 
   .name = "CPU",
   .uiName = "CPU",
   .caption = "CPU",
   .init = CPUMeter_init
};

MeterType AllCPUsMeter = {
   .mode = 0,
   .items = 1,
   .total = 100.0,
   .attributes = CPUMeter_attributes, 
   .name = "AllCPUs",
   .uiName = "All CPUs",
   .caption = "CPU",
   .draw = AllCPUsMeter_draw,
   .init = AllCPUsMeter_init,
   .setMode = AllCPUsMeter_setMode,
   .done = AllCPUsMeter_done
};