This source file includes following definitions.
- ftdm_cpu_read_stats
- FT_DECLARE
- FT_DECLARE
- FT_DECLARE
- FT_DECLARE
- FT_DECLARE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #ifdef WIN32
40 #define _WIN32_WINNT 0x0501
41 #include <windows.h>
42 #else
43
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <sys/types.h>
49 #include <fcntl.h>
50 #include <errno.h>
51 #endif
52
53 #include "private/ftdm_core.h"
54 #include "ftdm_cpu_monitor.h"
55 struct ftdm_cpu_monitor_stats
56 {
57
58 int valid_last_times;
59
60
61 double last_percentage_of_idle_time;
62
63 #ifdef __linux__
64
65 int disabled;
66
67
68 unsigned long long last_user_time;
69 unsigned long long last_system_time;
70 unsigned long long last_idle_time;
71
72 unsigned long long last_nice_time;
73 unsigned long long last_irq_time;
74 unsigned long long last_soft_irq_time;
75 unsigned long long last_io_wait_time;
76 unsigned long long last_steal_time;
77
78
79 int procfd;
80 int initd;
81 #elif defined (WIN32) || defined (WIN64)
82 __int64 i64LastUserTime;
83 __int64 i64LastKernelTime;
84 __int64 i64LastIdleTime;
85 #else
86
87 #endif
88 };
89
90 #ifdef __linux__
91 static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
92 unsigned long long *user,
93 unsigned long long *nice,
94 unsigned long long *system,
95 unsigned long long *idle,
96 unsigned long long *iowait,
97 unsigned long long *irq,
98 unsigned long long *softirq,
99 unsigned long long *steal)
100 {
101
102
103
104 #define CPU_ELEMENTS_1 7
105 #define CPU_INFO_FORMAT_1 "cpu %llu %llu %llu %llu %llu %llu %llu"
106
107 #define CPU_ELEMENTS_2 8
108 #define CPU_INFO_FORMAT_2 "cpu %llu %llu %llu %llu %llu %llu %llu %llu"
109
110 #define CPU_ELEMENTS_3 9
111 #define CPU_INFO_FORMAT_3 "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu"
112
113 static const char procfile[] = "/proc/stat";
114 int rc = 0;
115 int myerrno = 0;
116 int elements = 0;
117 const char *cpustr = NULL;
118 char statbuff[1024];
119 unsigned long long guest = 0;
120
121 if (!p->initd) {
122 p->procfd = open(procfile, O_RDONLY, 0);
123 if(p->procfd == -1) {
124 ftdm_log(FTDM_LOG_ERROR, "Failed to open CPU statistics file %s: %s\n", procfile, strerror(myerrno));
125 return FTDM_FAIL;
126 }
127 p->initd = 1;
128 } else {
129 lseek(p->procfd, 0L, SEEK_SET);
130 }
131
132 rc = read(p->procfd, statbuff, sizeof(statbuff) - 1);
133 if (rc <= 0) {
134 myerrno = errno;
135 ftdm_log(FTDM_LOG_ERROR, "Failed to read CPU statistics file %s: %s\n", procfile, strerror(myerrno));
136 return FTDM_FAIL;
137 }
138
139 cpustr = strstr(statbuff, "cpu ");
140 if (!cpustr) {
141 ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: missing cpu string\n");
142 return FTDM_FAIL;
143 }
144
145
146 elements = sscanf(cpustr, CPU_INFO_FORMAT_3, user, nice, system, idle, iowait, irq, softirq, steal, &guest);
147 if (elements == CPU_ELEMENTS_3) {
148 user += guest;
149 return FTDM_SUCCESS;
150 }
151
152 elements = sscanf(cpustr, CPU_INFO_FORMAT_2, user, nice, system, idle, iowait, irq, softirq, steal);
153 if (elements == CPU_ELEMENTS_2) {
154 return FTDM_SUCCESS;
155 }
156
157 elements = sscanf(cpustr, CPU_INFO_FORMAT_1, user, nice, system, idle, iowait, irq, softirq);
158 if (elements == CPU_ELEMENTS_1) {
159 *steal = 0;
160 return FTDM_SUCCESS;
161 }
162
163 ftdm_log(FTDM_LOG_ERROR, "Unexpected format for Linux proc cpu statistics:%s\n", cpustr);
164 return FTDM_FAIL;
165 }
166 #endif
167
168 #ifdef __linux__
169 FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
170 {
171 unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
172 unsigned long long usertime, kerneltime, idletime, totaltime, halftime;
173
174 *idle_percentage = 100.0;
175 if (p->disabled) {
176 return FTDM_FAIL;
177 }
178 if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) {
179 ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics - disabling cpu monitor\n");
180 p->disabled = 1;
181 return FTDM_FAIL;
182 }
183
184 if (!p->valid_last_times) {
185
186 p->valid_last_times = 1;
187 p->last_user_time = user;
188 p->last_nice_time = nice;
189 p->last_system_time = system;
190 p->last_irq_time = irq;
191 p->last_soft_irq_time = softirq;
192 p->last_io_wait_time = iowait;
193 p->last_steal_time = steal;
194 p->last_idle_time = idle;
195 p->last_percentage_of_idle_time = 100.0;
196 *idle_percentage = p->last_percentage_of_idle_time;
197 return FTDM_SUCCESS;
198 }
199
200 usertime = (user - p->last_user_time) + (nice - p->last_nice_time);
201 kerneltime = (system - p->last_system_time) + (irq - p->last_irq_time) + (softirq - p->last_soft_irq_time);
202 kerneltime += (iowait - p->last_io_wait_time);
203 kerneltime += (steal - p->last_steal_time);
204 idletime = (idle - p->last_idle_time);
205
206 totaltime = usertime + kerneltime + idletime;
207
208 if (totaltime <= 0) {
209
210
211
212
213 *idle_percentage = p->last_percentage_of_idle_time;
214 return FTDM_SUCCESS;
215 }
216
217 halftime = totaltime / 2UL;
218
219 p->last_percentage_of_idle_time = ((100 * idletime + halftime) / totaltime);
220 *idle_percentage = p->last_percentage_of_idle_time;
221
222 p->last_user_time = user;
223 p->last_nice_time = nice;
224 p->last_system_time = system;
225 p->last_irq_time = irq;
226 p->last_soft_irq_time = softirq;
227 p->last_io_wait_time = iowait;
228 p->last_steal_time = steal;
229 p->last_idle_time = idle;
230
231 return FTDM_SUCCESS;
232 }
233
234 #elif defined (__WINDOWS__)
235 FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
236 {
237 FILETIME idleTime;
238 FILETIME kernelTime;
239 FILETIME userTime;
240 int64_t i64UserTime;
241 int64_t i64KernelTime;
242 int64_t i64IdleTime;
243
244 if (!GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
245 return FTDM_FAIL;
246 }
247
248 i64UserTime = (int64_t)userTime.dwLowDateTime | ((int64_t)userTime.dwHighDateTime << 32);
249
250 i64KernelTime = (int64_t)kernelTime.dwLowDateTime | ((int64_t)kernelTime.dwHighDateTime << 32);
251
252 i64IdleTime = (int64_t)idleTime.dwLowDateTime | ((int64_t)idleTime.dwHighDateTime << 32);
253
254 if (p->valid_last_times) {
255 int64_t i64User = i64UserTime - p->i64LastUserTime;
256 int64_t i64Kernel = i64KernelTime - p->i64LastKernelTime;
257 int64_t i64Idle = i64IdleTime - p->i64LastIdleTime;
258 int64_t i64System = i64User + i64Kernel;
259 *idle_percentage = 100.0 * i64Idle / i64System;
260 } else {
261 *idle_percentage = 100.0;
262 p->valid_last_times = 1;
263 }
264
265
266 p->i64LastUserTime = i64UserTime;
267 p->i64LastKernelTime = i64KernelTime;
268 p->i64LastIdleTime = i64IdleTime;
269
270
271 return FTDM_SUCCESS;
272 }
273 #else
274
275 FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
276 {
277 *idle_percentage = 100.0;
278 return FTDM_FAIL;
279 }
280 #endif
281
282 FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void)
283 {
284 return calloc(1, sizeof(struct ftdm_cpu_monitor_stats));
285 }
286
287 FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p)
288 {
289 #ifdef __linux__
290 close(p->procfd);
291 #endif
292 free(p);
293 }
294
295
296
297
298
299
300
301
302
303
304
305