1 #include "config.h"
2 #undef NDEBUG
3 #include <assert.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <memory.h>
7 #include <strings.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <time.h>
11 #include <sys/time.h>
12 #include <sys/stat.h>
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 
17 #ifdef HAVE_SYSINFO
18 #include <sys/sysinfo.h>
19 #endif
20 
21 #ifdef HAVE_MAC_SYSCTL
22 #include <sys/types.h>
23 #include <sys/sysctl.h>
24 #include <sys/socketvar.h>
25 #include <netinet/ip.h>
26 #include <netinet/ip_var.h>
27 #include <netinet/tcp.h>
28 #include <netinet/tcp_var.h>
29 #include <net/if.h>
30 #endif
31 
32 #ifdef HAVE_UNAME
33 #include <sys/utsname.h>
34 #endif
35 
36 #include "evpath.h"
37 #include "cm_internal.h"
38 #include "cod.h"
39 #include <fcntl.h>
40 
41 /*#define CPU_FREQ_SCALING_MAX_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"*/
42 /*#define CPU_FREQ_SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"*/
43 /*#define CPU_FREQ_SCALING_CUR_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"*/
44 /*#define CPU_FREQ_SCALING_AVAILABLE_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies"*/
45 
46 /*#define CPU_FREQ_SCALING_GOVERNOR "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"*/
47 /*#define CPU_FREQ_SCALING_AVAILABLE_GOVERNORS "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors"*/
48 
49 /*#define CPU_FREQ_AFFECTED_CPU "/sys/devices/system/cpu/cpu0/cpufreq/affected_cpus"*/
50 
51 /*#define CPU_FREQ_ONDEMAND_SAMPLING_RATE_MIN "/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate_min"*/
52 /*#define CPU_FREQ_ONDEMAND_SAMPLING_RATE_MAX "/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate_max"*/
53 /*#define CPU_FREQ_ONDEMAND_SAMPLING_RATE "/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate"*/
54 /*#define CPU_FREQ_ONDEMAND_UP_THRESHOLD "/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold"*/
55 /*#define CPU_FREQ_ONDEMAND_IGNORE_NICE_LOAD "/sys/devices/system/cpu/cpu0/cpufreq/ondemand/ignore_nice_load"*/
56 /*#define CPU_FREQ_ONDEMAND_POWERSAVE_BIAD "/sys/devices/system/cpu/cpu0/cpufreq/ondemand/powersave_bias"*/
57 
58 typedef struct sensor_slurp {
59 	const char *name;
60 	char buffer[8192];
61 } sensor_slurp, *sensor_slurp_ptr;
62 
63 /*sensor_slurp proc_stat    = { "/proc/stat" };*/
64 /*sensor_slurp proc_loadavg = { "/proc/loadavg" };*/
65 /*sensor_slurp proc_meminfo = { "/proc/meminfo" };*/
66 /*sensor_slurp proc_net_dev = { "/proc/net/dev" };*/
67 
skip_whitespace(const char * p)68 char * skip_whitespace (const char *p)
69 {
70     while (isspace((unsigned char)*p)) p++;
71     return (char *)p;
72 }
73 
skip_token(const char * p)74 char * skip_token (const char *p)
75 {
76     while (isspace((unsigned char)*p)) p++;
77     while (*p && !isspace((unsigned char)*p)) p++;
78     return (char *)p;
79 }
80 
slurpfile(const char * filename,char * buffer,int buflen)81 int slurpfile(const char *filename, char *buffer, int buflen)
82 {
83     int fd, read_len;
84 
85     fd = open(filename, O_RDONLY);
86     if(fd < 0) {
87 	printf("open() error on file %s \n", filename);
88 	exit(0);
89     }
90     read_len = read(fd, buffer, buflen);
91     if(read_len <= 0) {
92 	printf("read() error on file %s \n", filename);
93 	exit(0);
94     }
95     if (read_len == buflen) {
96 	--read_len;
97 	printf("slurpfile() read() buffer overflow on file %s", filename);
98     }
99     buffer[read_len] = '\0';
100     close(fd);
101     return read_len;
102 }
103 
update_file(struct sensor_slurp * sf)104 char *update_file(struct sensor_slurp *sf) {
105     (void) slurpfile(sf->name, &sf->buffer[0], 8192);
106     return sf->buffer;
107 }
108 
num_cpustates_func(void)109 unsigned int num_cpustates_func ( void ) {
110    char *p;
111    unsigned int i=0;
112 
113    sensor_slurp proc_stat    = { "/proc/stat" };
114    p = update_file(&proc_stat);
115 
116 /**
117 ** Skip initial "cpu" token
118 **/
119    p = skip_token(p);
120    p = skip_whitespace(p);
121 /*
122 ** Loop over file until next "cpu" token is found.
123 ** i=4 : Linux 2.4.x
124 ** i=7 : Linux 2.6.x
125 */
126    while (strncmp(p,"cpu",3)) {
127      p = skip_token(p);
128      p = skip_whitespace(p);
129      i++;
130      }
131 
132    return i;
133 }
134 
total_jiffies_func(void)135 unsigned long total_jiffies_func ( void ) {
136 
137    char *p;
138    unsigned long user_jiffies, nice_jiffies, system_jiffies, idle_jiffies,
139                  wio_jiffies, irq_jiffies, sirq_jiffies;
140 
141    sensor_slurp proc_stat = { "/proc/stat" };
142    p = update_file(&proc_stat);
143    p = skip_token(p);
144    p = skip_whitespace(p);
145    user_jiffies = (unsigned int)strtod( p, &p );
146    p = skip_whitespace(p);
147    nice_jiffies = (unsigned int)strtod( p, &p );
148    p = skip_whitespace(p);
149    system_jiffies = (unsigned int)strtod( p , &p );
150    p = skip_whitespace(p);
151    idle_jiffies = (unsigned int)strtod( p , &p );
152 
153    int num_cpustates = num_cpustates_func();
154    if(num_cpustates == 4) /*NUM_CPUSTATES_24X*/
155        return user_jiffies + nice_jiffies + system_jiffies + idle_jiffies;
156 
157    p = skip_whitespace(p);
158    wio_jiffies = (unsigned int)strtod( p , &p );
159    p = skip_whitespace(p);
160    irq_jiffies = (unsigned int)strtod( p , &p );
161    p = skip_whitespace(p);
162    sirq_jiffies = (unsigned int)strtod( p , &p );
163 
164    return user_jiffies + nice_jiffies + system_jiffies + idle_jiffies +
165           wio_jiffies + irq_jiffies + sirq_jiffies;
166 }
167 
cpu_and_core_usage_func(double usage[])168 void cpu_and_core_usage_func (double usage[])
169 {
170    char *p;
171    int n, numcores, i;
172    numcores = num_cpustates_func();
173    n = numcores + 1;
174    unsigned long user_jiffies[n], last_user_jiffies[n],  nice_jiffies[n], last_nice_jiffies[n], system_jiffies[n], last_system_jiffies[n], idle_jiffies[n], last_idle_jiffies[n],  wio_jiffies[n], last_wio_jiffies[n], irq_jiffies[n], last_irq_jiffies[n], sirq_jiffies[n], last_sirq_jiffies[n], delta_busy[n], delta_total[n];
175       sensor_slurp proc_stat = { "/proc/stat" };
176    p = update_file(&proc_stat);
177    p = skip_token(p);
178    p = skip_whitespace(p);
179    for(i=0;i<n;++i)
180    {
181 	user_jiffies[i] = (unsigned int)strtod( p, &p );
182 	p = skip_whitespace(p);
183 	nice_jiffies[i] = (unsigned int)strtod( p, &p );
184 	p = skip_whitespace(p);
185 	system_jiffies[i] = (unsigned int)strtod( p , &p );
186 	p = skip_whitespace(p);
187 	idle_jiffies[i] = (unsigned int)strtod( p , &p );
188 	p = skip_whitespace(p);
189 	wio_jiffies[i] = (unsigned int)strtod( p , &p );
190 	p = skip_whitespace(p);
191 	irq_jiffies[i] = (unsigned int)strtod( p , &p );
192 	p = skip_whitespace(p);
193 	sirq_jiffies[i] = (unsigned int)strtod( p , &p );
194 	p = skip_whitespace(p);
195 	delta_busy[i] = (user_jiffies[i] - last_user_jiffies[i]) + (nice_jiffies[i] - last_nice_jiffies[i]) + (system_jiffies[i] - last_system_jiffies[i]);
196 	delta_total[i] = delta_busy[i] + (idle_jiffies[i] - last_idle_jiffies[i]) + (wio_jiffies[i] - last_wio_jiffies[i]) + (irq_jiffies[i] - last_irq_jiffies[i]) + (sirq_jiffies[i] - last_sirq_jiffies[i]);
197 	usage[i] = (double) delta_busy[i] / (double) delta_total[i] ;
198 	last_user_jiffies[i] = user_jiffies[i];
199 	last_nice_jiffies[i] = nice_jiffies[i];
200 	last_system_jiffies[i] = system_jiffies[i];
201 	last_idle_jiffies[i] = idle_jiffies[i];
202 	last_wio_jiffies[i] = wio_jiffies[i];
203 	last_irq_jiffies[i] = irq_jiffies[i];
204 	last_sirq_jiffies[i] = sirq_jiffies[i];
205 	while (strncmp(p,"cpu",3)) {
206 	p = skip_token(p);
207 	p = skip_whitespace(p);
208 	}
209 	p = skip_token(p);
210         p = skip_whitespace(p);
211 
212    }
213 
214 }
215 
cpu_user_func(void)216 double cpu_user_func ( void )
217 {
218     char *p;
219     double val;
220     static double last_user_jiffies, last_total_jiffies;
221     double user_jiffies, total_jiffies, diff;
222 
223       sensor_slurp proc_stat    = { "/proc/stat" };
224     p = update_file(&proc_stat);
225 
226     p = skip_token(p);
227     user_jiffies  = strtod( p , (char **)NULL );
228     total_jiffies = (double) total_jiffies_func();
229 
230     diff = user_jiffies - last_user_jiffies;
231 
232     if ( diff )
233 	val = (diff/(total_jiffies - last_total_jiffies))*100;
234     else
235 	val = 0.0;
236 
237     last_user_jiffies  = user_jiffies;
238     last_total_jiffies = total_jiffies;
239 
240     return val;
241 }
242 
cpu_nice_func(void)243 double cpu_nice_func ( void )
244 {
245     char *p;
246     double val;
247     static double last_nice_jiffies, last_total_jiffies;
248     double nice_jiffies, total_jiffies, diff;
249 
250       sensor_slurp proc_stat    = { "/proc/stat" };
251     p = update_file(&proc_stat);
252 
253     p = skip_token(p);
254     p = skip_token(p);
255     nice_jiffies  = strtod( p , (char **)NULL );
256     total_jiffies = (double) total_jiffies_func();
257 
258     diff = (nice_jiffies  - last_nice_jiffies);
259 
260     if ( diff )
261 	val = (diff/(total_jiffies - last_total_jiffies))*100;
262     else
263 	val = 0.0;
264 
265     last_nice_jiffies  = nice_jiffies;
266     last_total_jiffies = total_jiffies;
267 
268     return val;
269 }
270 
cpu_system_func(void)271 double cpu_system_func ( void )
272 {
273     char *p;
274     static double val;
275     static double last_system_jiffies,  system_jiffies,
276 	last_total_jiffies, total_jiffies, diff;
277 
278       sensor_slurp proc_stat    = { "/proc/stat" };
279     p = update_file(&proc_stat);
280     p = skip_token(p);
281     p = skip_token(p);
282     p = skip_token(p);
283     system_jiffies = strtod( p , (char **)NULL );
284 	int num_cpustates = num_cpustates_func();
285     if (num_cpustates > 4 ) /*NUM_CPUSTATES_24X)*/ {
286 	p = skip_token(p);
287 	p = skip_token(p);
288 	p = skip_token(p);
289 	system_jiffies += strtod( p , (char **)NULL ); /* "intr" counted in system */
290 	p = skip_token(p);
291 	system_jiffies += strtod( p , (char **)NULL ); /* "sintr" counted in system */
292     }
293     total_jiffies  = (double) total_jiffies_func();
294 
295     diff = system_jiffies  - last_system_jiffies;
296 
297     if ( diff )
298 	val = (diff/(total_jiffies - last_total_jiffies))*100;
299     else
300 	val = 0.0;
301 
302     last_system_jiffies  = system_jiffies;
303     last_total_jiffies = total_jiffies;
304 
305     return val;
306 }
307 
cpu_idle_func(void)308 double cpu_idle_func ( void )
309 {
310     char *p;
311     static double val;
312     static double last_idle_jiffies,  idle_jiffies,
313 	last_total_jiffies, total_jiffies, diff;
314 
315       sensor_slurp proc_stat    = { "/proc/stat" };
316     p = update_file(&proc_stat);
317 
318     p = skip_token(p);
319     p = skip_token(p);
320     p = skip_token(p);
321     p = skip_token(p);
322     idle_jiffies  = strtod( p , (char **)NULL );
323     total_jiffies = (double) total_jiffies_func();
324 
325     diff = idle_jiffies - last_idle_jiffies;
326 
327     if ( diff )
328 	val = (diff/(total_jiffies - last_total_jiffies))*100;
329     else
330 	val = 0.0;
331     last_idle_jiffies = idle_jiffies;
332     last_total_jiffies = total_jiffies;
333     return val;
334 }
335 
336 /**************NET FUNCTIONS*****************/
received_bytes(char * interface)337 long received_bytes(char *interface)
338 {
339 	static long r_bytes=0;
340 #ifdef HAVE_MAC_SYSCTL
341 	char *buf = NULL, *lim, *next;
342 	static int mib[6];
343   	size_t mlen,vlen;
344 	struct if_msghdr *ifm;
345 	unsigned int ifindex;
346   	mib[0] = CTL_NET;
347   	mib[1] = PF_ROUTE;
348 	mib[2] = 0;
349 	mib[3] = 0;
350 	mib[4] = NET_RT_IFLIST;
351 	mib[5] = 0;
352 
353 	mlen = 6;
354 	ifindex = if_nametoindex(interface);
355 	sysctl(mib,mlen,NULL,&vlen,NULL,0);
356 	buf = malloc(vlen);
357 	sysctl(mib,mlen,buf,&vlen,NULL,0);
358 	lim = buf+vlen;
359 	for(next = buf; next < lim; )
360 	{
361 		ifm = (struct if_msghdr *)next;
362 		next += ifm->ifm_msglen;
363 	//	printf("Index %d, ifm index %d\n",ifindex,ifm->ifm_index);
364 	//	printf("ibytes %ld\n",ifm->ifm_data.ifi_ibytes);
365 		if(ifindex == ifm->ifm_index)
366 		{
367 			//printf("Correct interface\n");
368 			r_bytes = (long) ifm->ifm_data.ifi_ibytes;
369 			break;
370 		}
371 	}
372 	//printf("Received bytes %ld\n",r_bytes);
373 	free(buf);
374 
375 #else
376 	char *temp_if;
377 	char *p;
378 	if(interface == NULL)
379 	   temp_if = strdup("eth0");
380 	else
381 	   temp_if = strdup((const char *)interface);
382 	sensor_slurp proc_net = { "/proc/net/dev" };
383 	p = update_file(&proc_net);
384 	while (p && strncmp(p,temp_if,strlen(temp_if)))
385 	{
386 		p = skip_token(p);
387 		p = skip_whitespace(p);
388 	}
389 
390 	p = skip_token(p);
391 	p = skip_whitespace(p);
392 	r_bytes = strtol( p ,NULL,10);
393 	free(temp_if);
394 #endif // end HAVE_MAC_SYSCTL
395 	return r_bytes;
396 }
397 
sent_bytes(char * interface)398 long sent_bytes(char *interface)
399 {
400 	long s_bytes;
401 #ifdef HAVE_MAC_SYSCTL
402 
403 	char *buf = NULL, *lim, *next;
404 	static int mib[6];
405   	size_t mlen,vlen;
406 	struct if_msghdr *ifm;
407 	unsigned int ifindex;
408   	mib[0] = CTL_NET;
409   	mib[1] = PF_ROUTE;
410 	mib[2] = 0;
411 	mib[3] = 0;
412 	mib[4] = NET_RT_IFLIST;
413 	mib[5] = 0;
414 
415 	mlen = 6;
416 	ifindex = if_nametoindex(interface);
417 	sysctl(mib,mlen,NULL,&vlen,NULL,0);
418 	buf = malloc(vlen);
419 	sysctl(mib,mlen,buf,&vlen,NULL,0);
420 	lim = buf+vlen;
421 	for(next = buf; next < lim; )
422 	{
423 		ifm = (struct if_msghdr *)next;
424 		next += ifm->ifm_msglen;
425 		if(ifindex == ifm->ifm_index)
426 		{
427 		//	printf("Correct interface\n");
428 			s_bytes = (long) ifm->ifm_data.ifi_obytes;
429 			break;
430 		}
431 	}
432 //	printf("Sent bytes %ld\n",s_bytes);
433 	free(buf);
434 #else
435 
436         char *temp_if;
437         char *p;
438 	int  i=0;
439         if(interface == NULL)
440            temp_if = strdup("eth0");
441         else
442            temp_if = strdup((const char *)interface);
443         sensor_slurp proc_net = { "/proc/net/dev" };
444         p = update_file(&proc_net);
445 	while (p && strncmp(p,temp_if,strlen(temp_if)))
446         {
447                 p = skip_token(p);
448                 p = skip_whitespace(p);
449         }
450 	while(i <= 8) {
451 	 	p = skip_token(p);
452 		p = skip_whitespace(p);
453 		++i;
454 	}
455 	s_bytes = strtol (p, NULL,10);
456 	free(temp_if);
457 #endif // end HAVE_MAC_SYSCTL
458 	return s_bytes;
459 
460 
461 }
462 /*
463  * This function returns the bandwidth of the network(in bits per second) as sampled over a certain window of time.
464  * stage can be "start" where the network sampling begins, and at stage end the monitored network
465  * bandwidth is returned. On OS X the two calls have to be atleast 425 microseconds apart.
466  * */
467 
net_bw(char * interface,char * stage)468 double net_bw(char *interface, char *stage)
469 {
470 	static long old_s_bytes, new_s_bytes, old_r_bytes, new_r_bytes, start_time, end_time;
471 	long s_bytes, r_bytes;
472 	struct timeval t;
473 	double net_bw;
474 #ifdef HAVE_MAC_SYSCTL
475 	char *buf = NULL, *lim, *next;
476 	static int mib[6];
477   	size_t mlen,vlen;
478 	struct if_msghdr *ifm;
479 	unsigned int ifindex;
480   	mib[0] = CTL_NET;
481   	mib[1] = PF_ROUTE;
482 	mib[2] = 0;
483 	mib[3] = 0;
484 	mib[4] = NET_RT_IFLIST;
485 	mib[5] = 0;
486 
487 	mlen = 6;
488 	ifindex = if_nametoindex(interface);
489 	sysctl(mib,mlen,NULL,&vlen,NULL,0);
490 	buf = malloc(vlen);
491 	sysctl(mib,mlen,buf,&vlen,NULL,0);
492 	lim = buf+vlen;
493 	for(next = buf; next < lim; )
494 	{
495 		ifm = (struct if_msghdr *)next;
496 		next += ifm->ifm_msglen;
497 	//	printf("Index %d, ifm index %d\n",ifindex,ifm->ifm_index);
498 	//	printf("ibytes %ld\n",ifm->ifm_data.ifi_ibytes);
499 		if(ifindex == ifm->ifm_index)
500 		{
501 	//		printf("Correct interface\n");
502 			r_bytes = (long) ifm->ifm_data.ifi_ibytes;
503 			s_bytes = (long) ifm->ifm_data.ifi_obytes;
504 			break;
505 		}
506 	}
507 //	printf("Received bytes %ld Sent bytes %ld\n",r_bytes,s_bytes);
508 	free(buf);
509 
510 #else
511 
512 	int i=0;
513 	char *temp_if;
514 	char *p;
515 
516 	if(interface == NULL)
517 		temp_if = strdup("eth0");
518 	else
519 		temp_if = strdup((const char*)interface);
520 	sensor_slurp proc_net = { "/proc/net/dev" };
521         p = update_file(&proc_net);
522 	gettimeofday(&t,NULL);
523 
524         while (p && strncmp(p,temp_if,strlen(temp_if)))
525         {
526                 p = skip_token(p);
527                 p = skip_whitespace(p);
528         }
529 
530         p = skip_token(p);
531         p = skip_whitespace(p);
532         r_bytes = strtol( p ,NULL,10);
533 	while(i <= 7) {
534                 p = skip_token(p);
535                 p = skip_whitespace(p);
536                 ++i;
537         }
538 	s_bytes = strtol (p, NULL,10);
539 	free(temp_if);
540 #endif // end HAVE_MAC_SYSCTL
541 	if(strncmp(stage,"start",3)==0)
542 	{
543 		printf("Start %ld %ld \n",s_bytes,r_bytes);
544 
545 		old_s_bytes = s_bytes;
546 		old_r_bytes = r_bytes;
547 		start_time = t.tv_sec * 1000000 + t.tv_usec;
548 
549 		return 0.0;
550 	}
551 	printf("End %ld %ld \n",s_bytes,r_bytes);
552 	new_s_bytes = s_bytes;
553 	new_r_bytes = r_bytes;
554 	end_time = t.tv_sec * 1000000 + t.tv_usec;
555 	net_bw = (double) (((new_s_bytes - old_s_bytes) + (new_r_bytes - old_r_bytes)) / (double)(end_time - start_time))*1000000*8;
556 	printf("Bandwidth = %f\n",net_bw);
557 	return net_bw;
558 
559 }
560 
561 /**************TIMING FUNCTIONS**************/
562 
dgettimeofday(void)563 double dgettimeofday( void )
564 {
565 #ifdef HAVE_GETTIMEOFDAY
566     double timestamp;
567     struct timeval now;
568     gettimeofday(&now, NULL);
569     timestamp = now.tv_sec + now.tv_usec* 1.0e-6 ;
570     return timestamp;
571 #else
572     return -1;
573 #endif
574 }
575 
576 /**************OS FUNCTIONS**************/
os_type()577 char*  os_type() {
578   static struct utsname output;
579   static int first = 1;
580   if (first) {
581     uname(&output);
582     first = 0;
583   }
584   return strdup(output.sysname);
585 }
586 
os_release()587 char*  os_release() {
588   static struct utsname output;
589   static int first = 1;
590   if (first) {
591     uname(&output);
592     first = 0;
593   }
594   return strdup(output.release);
595 }
596 
597 /* Should probably test if gethostname & uname exist on box before using them.... */
hostname()598 char* hostname() {
599   static char val[256];
600   static int first = 1;
601   if (first) {
602     gethostname(&val[0],256);
603     first = 0;
604   }
605   return strdup(&val[0]);
606 }
607 
608 
609 /**************Stat FUNCTIONS**************/
stat_uptime()610 double  stat_uptime() {
611   double val=0;
612 #ifdef HAVE_SYSINFO
613   struct sysinfo info;
614   sysinfo(&info);
615   val = (double) info.uptime;
616 #else
617 #ifdef HAVE_MAC_SYSCTL
618   static int mib[4];
619   struct timeval boottime;
620   size_t mlen,vlen;
621   mlen = 2;
622   mib[0] = CTL_KERN;
623   mib[1] = KERN_BOOTTIME;
624   vlen = sizeof(struct timeval);
625   sysctl(mib,mlen,&boottime,&vlen,NULL,0);
626   val =  dgettimeofday() - (double) boottime.tv_sec - boottime.tv_usec* 1.0e-6;
627 
628 #endif // end HAVE_MAC_SYSCTL
629 #endif // end HAVE_SYSINFO
630 
631   return val;
632 
633 }
634 
635 /* double stat_cpu_user() { */
636 /* } */
637 
638 /* double stat_cpu_system() { */
639 /* } */
640 
stat_loadavg_one(void)641 double stat_loadavg_one ( void )
642 {
643   double val;
644 #ifdef HAVE_GETLOADAVG
645   double loadavg[3];
646   getloadavg(loadavg,3);
647   val = loadavg[0];
648 
649 #else
650   sensor_slurp proc_loadavg = { "/proc/loadavg" };
651   val = strtod( update_file(&proc_loadavg), (char **)NULL);
652 #endif //end HAVE_GETLOADAVG
653     return val;
654 }
655 
stat_loadavg_five(void)656 double stat_loadavg_five ( void )
657 {
658   double val;
659 #ifdef HAVE_GETLOADAVG
660   double loadavg[3];
661   getloadavg(loadavg,3);
662   val = loadavg[1];
663 
664 #else
665     char *p;
666 
667       sensor_slurp proc_loadavg = { "/proc/loadavg" };
668     p = update_file(&proc_loadavg);
669     p = skip_token(p);
670     val = strtod( p, (char **)NULL);
671 #endif //end HAVE_GETLOADAVG
672     return val;
673 }
674 
stat_loadavg_fifteen(void)675 double stat_loadavg_fifteen ( void )
676 {
677   double val;
678 #ifdef HAVE_GETLOADAVG
679   double loadavg[3];
680   getloadavg(loadavg,3);
681   val = loadavg[2];
682 
683 #else
684   char *p;
685   sensor_slurp proc_loadavg = { "/proc/loadavg" };
686   p = update_file(&proc_loadavg);
687 
688   p = skip_token(p);
689   p = skip_token(p);
690   val = strtod( p, (char **)NULL);
691 #endif //end HAVE_GETLOADAVG
692   return val;
693 }
694 
695 /**************MEMORY FUNCTIONS**************/
696 
vm_mem_total()697 unsigned long vm_mem_total() {
698   unsigned long val = 0;
699 #ifdef HAVE_MAC_SYSCTL
700   /* static int flag=0; */
701   static int mib[4];
702   size_t mlen,vlen;
703   mib[0] = CTL_HW;
704   mib[1] = HW_MEMSIZE;
705   mlen = 2;
706   /* if (flag == 0) { */
707   /*   sysctlnametomib("hw.memsize",mib,&mlen); */
708   /*   flag=1; */
709   /* } */
710   vlen = sizeof(unsigned long);
711   sysctl(mib,mlen,&val,&vlen,NULL,0);
712 
713 #else
714   char *p;
715 
716   sensor_slurp proc_meminfo = { "/proc/meminfo" };
717   p = strstr( update_file(&proc_meminfo), "MemTotal:" );
718   if(p) {
719     p = skip_token(p);
720     val = strtoul( p, NULL, 10 );
721   } else {
722     val = 0;
723   }
724 #endif //end of HAVE_MAC_SYSCTL
725   return val;
726 }
727 
728 
vm_mem_free()729 unsigned long vm_mem_free() {
730   unsigned long val = 0;
731 #ifdef HAVE_MAC_SYSCTL
732   /* static int flag=0; */
733   static int mib[2] = {CTL_VM, VM_SWAPUSAGE};
734   struct xsw_usage swapval;
735   size_t vlen;
736   /* mlen = 4; */
737   /* if (flag == 0) { */
738   /*   sysctlnametomib("vm.swapusage",mib,&mlen); */
739   /*   flag=1; */
740   /* } */
741   vlen = sizeof(struct xsw_usage);
742   sysctl(mib,2,&swapval,&vlen,NULL,0);
743   val = (unsigned long) swapval.xsu_avail;
744 
745 #else
746     char *p;
747 
748     sensor_slurp proc_meminfo = { "/proc/meminfo" };
749     p = strstr( update_file(&proc_meminfo), "MemFree:" );
750     if(p) {
751 	p = skip_token(p);
752 	val = strtoul( p, NULL, 10 );
753     } else {
754 	val = 0;
755     }
756 #endif //end of HAVE_MAC_SYSCTL
757 
758     return val;
759 }
760 
761 
vm_swap_total(void)762 unsigned long vm_swap_total ( void )
763 {
764   unsigned long val = 0;
765 #ifdef HAVE_MAC_SYSCTL
766   static int mib[2] = {CTL_VM, VM_SWAPUSAGE};
767   struct xsw_usage swapval;
768   size_t vlen;
769   vlen = sizeof(struct xsw_usage);
770   sysctl(mib,2,&swapval,&vlen,NULL,0);
771   val = (unsigned long) swapval.xsu_total;
772 
773 #else
774   char *p;
775 
776   sensor_slurp proc_meminfo = { "/proc/meminfo" };
777   p = strstr( update_file(&proc_meminfo), "SwapFree:" );
778   if(p) {
779     p = skip_token(p);
780     val =  strtoul( p, NULL, 10 );
781   } else {
782     val = 0;
783   }
784 #endif //end HAVE_MAC_SYSCTL
785   return val;
786 }
787 
vm_swap_free(void)788 unsigned long vm_swap_free ( void )
789 {
790   unsigned long val = 0;
791 #ifdef HAVE_MAC_SYSCTL
792   static int mib[2] = {CTL_VM, VM_SWAPUSAGE};
793   struct xsw_usage swapval;
794   size_t vlen;
795   vlen = sizeof(struct xsw_usage);
796   sysctl(mib,2,&swapval,&vlen,NULL,0);
797   val = (unsigned long) swapval.xsu_avail;
798 
799 #else
800     char *p;
801 
802       sensor_slurp proc_meminfo = { "/proc/meminfo" };
803     p = strstr( update_file(&proc_meminfo), "SwapFree:" );
804     if(p) {
805 	p = skip_token(p);
806 	val = strtoul( p, NULL, 10 );
807     } else {
808 	val = 0;
809     }
810 #endif //end HAVE_MAC_SYSCTL
811     return val;
812 }
813 
814 /**************HARDWARE FUNCTIONS**************/
hw_cpus()815 int hw_cpus () {
816   long val = -1;
817 #ifdef HAVE_MAC_SYSCTL
818   static int mib[2] = {CTL_HW, HW_NCPU};
819   size_t vlen;
820   vlen = sizeof(long);
821   sysctl(mib,2,&val,&vlen,NULL,0);
822 #else
823 #if defined(HAVE_SYSCONF)
824   val = (long) sysconf(_SC_NPROCESSORS_ONLN);
825 #else
826   val = 1; // if we don't know any better...
827 #endif // end HAVE_SYSCONFIG
828 #endif //end of HAVE_MAC_SYSCTL
829   return (int) val;
830 
831 }
832 
833 
hw_cpu_max_freq(void)834 long hw_cpu_max_freq( void )
835 {
836   long val = 0;
837 #ifdef HAVE_MAC_SYSCTL
838   size_t vlen;
839   vlen = sizeof(long);
840   sysctlbyname("hw.cpufrequency_max",&val,&vlen,NULL,0);
841   val = val/1e6;
842 #else
843   char *p;
844 
845   struct stat struct_stat;
846   char sys_devices_system_cpu[32];
847   const char *CPU_FREQ_SCALING_MAX_FREQ = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq";
848   if ( stat(CPU_FREQ_SCALING_MAX_FREQ, &struct_stat) == 0 ) {
849     if(slurpfile(CPU_FREQ_SCALING_MAX_FREQ, sys_devices_system_cpu, 32)) {
850       p = sys_devices_system_cpu;
851       val = (strtol( p, (char **)NULL , 10 ) / 1000 );
852     }
853   }
854 #endif // end HAVE_MAC_SYSCTL
855   return val;
856 }
857 
hw_cpu_min_freq(void)858 long hw_cpu_min_freq( void )
859 {
860   long val = -1;
861 #ifdef HAVE_MAC_SYSCTL
862   size_t vlen;
863   vlen = sizeof(long);
864   sysctlbyname("hw.cpufrequency_min",&val,&vlen,NULL,0);
865   val = val/1e6;
866 
867 #else
868   char *p;
869 
870   struct stat struct_stat;
871   char sys_devices_system_cpu[32];
872   const char *CPU_FREQ_SCALING_MIN_FREQ = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq";
873   if ( stat(CPU_FREQ_SCALING_MIN_FREQ, &struct_stat) == 0 ) {
874     if(slurpfile(CPU_FREQ_SCALING_MIN_FREQ, sys_devices_system_cpu, 32)) {
875       p = sys_devices_system_cpu;
876       val = (strtol( p, (char **)NULL , 10 ) / 1000 );
877     }
878   }
879 #endif //end HAVE_MAC_SYSCTL
880   return val;
881 }
882 
hw_cpu_curr_freq(void)883 long hw_cpu_curr_freq( void )
884 {
885   long val = 0;
886 #ifdef HAVE_MAC_SYSCTL
887   /* static int flag=0; */
888   static int mib[2] = {CTL_HW, HW_CPU_FREQ};
889   size_t vlen;
890   /* if (flag == 0) { */
891   /*   sysctlnametomib("hw.cpufrequency",mib,&mlen); */
892   /*   printf("\nmib = { %i, %i, %i, %i};\n",mib[0],mib[1],mib[2],mib[3]); */
893   /*   flag=1; */
894   /* } */
895   vlen = sizeof(long);
896   sysctl(mib,2,&val,&vlen,NULL,0);
897   val = val/1e6;
898 
899 #else
900   char *p;
901 
902   struct stat struct_stat;
903   char sys_devices_system_cpu[32];
904   const char *CPU_FREQ_SCALING_CUR_FREQ = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq";
905   if ( stat(CPU_FREQ_SCALING_CUR_FREQ, &struct_stat) == 0 ) {
906     if(slurpfile(CPU_FREQ_SCALING_CUR_FREQ, sys_devices_system_cpu, 32)) {
907       p = sys_devices_system_cpu;
908       val = (unsigned int) (strtoul( p, (char **)NULL , 10 ) / 1000 );
909     }
910   }
911 #endif //end HAVE_MAC_SYSCTL
912   return val;
913 }
914 
915 
916 void
add_metrics_routines(stone_type stone,cod_parse_context context)917 add_metrics_routines(stone_type stone, cod_parse_context context)
918 {
919     static char extern_string[] = "\
920        double    dgettimeofday();         \n		\
921 /* number of cpus */  \n				\
922        int           hw_cpus();           \n		\
923 /* minimum allowed frequency in MHz */ \n	\
924        long           hw_cpu_min_freq();    \n \
925 /* maximum allowed frequency in MHz  */ \n	\
926        long           hw_cpu_max_freq();   \n	\
927 /* current frequency  in Mhz */ \n	\
928        long           hw_cpu_curr_freq();  \n	\
929 /* a string to identify the local OS type -- ie Linux  */ \n 	\
930        char*       os_type();              \n	\
931 /* a string to identify the current release -- ie FC14 */  \n	\
932        char*       os_release();          \n\
933 /* a string to identify the hostname -- ie maquis1 */  \n	\
934        char*       hostname();          \n\
935 /* time in seconds that the computer has been up  */  \n	\
936        double    stat_uptime();           \n\
937 /* load average over the last one minute  */ \n	\
938        double    stat_loadavg_one();       \n	\
939 /* load average over the last five minutes  */ \n	\
940        double    stat_loadavg_five();      \n	\
941 /* load average over the last fifteen minute  */ \n	\
942        double    stat_loadavg_fifteen();   \n	\
943 /* total physical memory  */  \n	\
944        unsigned long    vm_mem_total();   \n	\
945 /* free physical memory   */ \n	\
946        unsigned long    vm_mem_free();    \n	\
947 /* total swap available */  \n	\
948        unsigned long    vm_swap_total();   \n	\
949 /* free swap  */  \n	\
950        unsigned long    vm_swap_free();     \n";
951 
952     static cod_extern_entry externs[] = {
953 	{"dgettimeofday", (void *) 0},	        // 0
954 	{"hw_cpus", (void *) 0},		// 1
955 	{"hw_cpu_min_freq", (void *) 0},	// 2
956 	{"hw_cpu_max_freq", (void *) 0},	// 3
957 	{"hw_cpu_curr_freq", (void *) 0},	// 4
958 	{"os_type", (void *) 0},		// 5
959 	{"os_release", (void *) 0},		// 6
960 	{"hostname", (void *) 0},               // 7
961 	{"stat_uptime", (void *) 0},		// 8
962 	{"stat_loadavg_one", (void *) 0},	// 9
963 	{"stat_loadavg_five", (void *) 0},	// 10
964 	{"stat_loadavg_fifteen", (void *) 0},	// 11
965 	{"vm_mem_total", (void *) 0},		// 12
966 	{"vm_mem_free", (void *) 0},		// 13
967 	{"vm_swap_total", (void *) 0},		// 14
968 	{"vm_swap_free", (void*) 0},		// 15
969 	{(void *) 0, (void *) 0}
970     };
971 
972     (void) stone;
973     /*
974      * some compilers think it isn't a static initialization to put this
975      * in the structure above, so do it explicitly.
976      */
977     externs[0].extern_value = (void *) (long) dgettimeofday;
978     externs[1].extern_value = (void *) (long) hw_cpus;
979     externs[2].extern_value = (void *) (long) hw_cpu_min_freq;
980     externs[3].extern_value = (void *) (long) hw_cpu_max_freq;
981     externs[4].extern_value = (void *) (long) hw_cpu_curr_freq;
982     externs[5].extern_value = (void *) (long) os_type;
983     externs[6].extern_value = (void *) (long) os_release;
984     externs[7].extern_value = (void *) (long) hostname;
985     externs[8].extern_value = (void *) (long) stat_uptime;
986     externs[9].extern_value = (void *) (long) stat_loadavg_one;
987     externs[10].extern_value = (void *) (long) stat_loadavg_five;
988     externs[11].extern_value = (void *) (long) stat_loadavg_fifteen;
989     externs[12].extern_value = (void *) (long) vm_mem_total;
990     externs[13].extern_value = (void *) (long) vm_mem_free;
991     externs[14].extern_value = (void *) (long) vm_swap_total;
992     externs[15].extern_value = (void *) (long) vm_swap_free;
993 
994     cod_assoc_externs(context, externs);
995     cod_parse_for_context(extern_string, context);
996 }
997 
998 
999 /*int main(int argc, char **argv) {
1000 	//num_cpustates_func();
1001 	printf (" CPU USER %  :  %lf \n", cpu_user_func());
1002 	printf (" CPU NICE %  :  %lf \n", cpu_nice_func());
1003 	printf (" CPU SYSTEM %  :  %lf \n", cpu_system_func());
1004 	printf (" CPU IDLE %  :  %lf \n", cpu_idle_func());
1005 
1006 	printf (" LOAD 1 %  :  %lf \n", load_one_func());
1007 	printf (" LOAD 5 %  :  %lf \n", load_five_func());
1008 	printf (" LOAD 15 %  :  %lf \n", load_fifteen_func());
1009 
1010 	printf (" MEM FREE %  :  %lf \n", mem_free_func());
1011 	printf (" MEM BUFF %  :  %lf \n", mem_buffers_func());
1012 	printf (" MEM CACHE %  :  %lf \n", mem_cached_func());
1013 
1014 	printf (" SWAP FREE %  :  %lf \n", swap_free_func());
1015 	printf (" GET TIMESTAMP %  :  %lf \n", gettimeofday_func());
1016 
1017 	printf (" CPU_MAX_FREQ %  :  %d \n", cpu_max_freq_func());
1018 	printf (" CPU_MIN_FREQ %  :  %d \n", cpu_min_freq_func());
1019 	printf (" CPU_CUR_FREQ %  :  %d \n", cpu_cur_freq_func());
1020 	int *val;
1021 	val = cpu_available_freq_func();
1022 	printf (" CPU_AVAILABLE_FREQ %  :  %d , %d , %d \n", val[0], val[1], val[2]);
1023 
1024 	printf (" CPU_FREQ_GOVERNOR %  :  %s \n", cpu_scaling_governor_func());
1025 	char **avail;
1026 	avail = cpu_scaling_available_governors_func();
1027 	printf (" CPU_FREQ_AVAILABLE_GOVERNORS %  :  %s , %s , %s \n", avail[0], avail[1], avail[2]);
1028 }*/
1029 
1030 /* Dead functions.
1031 
1032 char *cpu_scaling_governor_func( void )
1033 {
1034     char *p = NULL;
1035 	struct stat struct_stat;
1036 	char sys_devices_system_cpu[32];
1037 	const char *CPU_FREQ_SCALING_GOVERNOR = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor";
1038     if ( stat(CPU_FREQ_SCALING_GOVERNOR, &struct_stat) == 0 ) {
1039 		if(slurpfile(CPU_FREQ_SCALING_GOVERNOR, sys_devices_system_cpu, 32)) {
1040 			p = strdup(sys_devices_system_cpu);
1041 		}
1042     }
1043     return p;
1044 }
1045 
1046 char **cpu_scaling_available_governors_func( void )
1047 {
1048     static char *val[3];
1049     char *p;
1050 
1051 	struct stat struct_stat;
1052 	char sys_devices_system_cpu_available[128];
1053 	const char *CPU_FREQ_SCALING_AVAILABLE_GOVERNORS  = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors";
1054     if ( stat(CPU_FREQ_SCALING_AVAILABLE_GOVERNORS, &struct_stat) == 0 ) {
1055 		if(slurpfile(CPU_FREQ_SCALING_AVAILABLE_GOVERNORS, sys_devices_system_cpu_available, 128)) {
1056 			p = strdup(sys_devices_system_cpu_available);
1057 			val[0] = strtok(p, " ");
1058 			val[1] = strtok(NULL, " ");
1059 			val[2] = strtok(NULL, " ");
1060 		}
1061     }
1062     return val;
1063 }
1064 
1065 int *cpu_available_freq_func( void )
1066 {
1067     char *p;
1068     static int val[3];
1069 
1070 	struct stat struct_stat;
1071 	char sys_devices_system_cpu_available[128];
1072 	const char *CPU_FREQ_SCALING_AVAILABLE_FREQ = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies";
1073     if ( stat(CPU_FREQ_SCALING_AVAILABLE_FREQ, &struct_stat) == 0 ) {
1074 		if(slurpfile(CPU_FREQ_SCALING_AVAILABLE_FREQ, sys_devices_system_cpu_available, 128)) {
1075 			p = sys_devices_system_cpu_available;
1076 			val[0] = (strtol( p, (char **)NULL , 10 ) / 1000 );
1077 			p = skip_token(p);
1078 			val[1] = (strtol( p, (char **)NULL , 10 ) / 1000 );
1079 			p = skip_token(p);
1080 			val[2] = (strtol( p, (char **)NULL , 10 ) / 1000 );
1081 		}
1082     }
1083     return val;
1084 }
1085 
1086 double mem_cached_func ( void )
1087 {
1088     char *p;
1089     double val;
1090 
1091       sensor_slurp proc_meminfo = { "/proc/meminfo" };
1092     p = strstr( update_file(&proc_meminfo), "Cached:");
1093     if(p) {
1094 	p = skip_token(p);
1095 	val = atof( p );
1096     } else {
1097 	val = 0;
1098     }
1099    return val;
1100 }
1101 
1102 double mem_buffers_func ( void )
1103 {
1104     char *p;
1105     double val;
1106 
1107       sensor_slurp proc_meminfo = { "/proc/meminfo" };
1108     p = strstr( update_file(&proc_meminfo), "Buffers:" );
1109     if(p) {
1110 	p = skip_token(p);
1111 	val = atof( p );
1112     } else {
1113 	val = 0;
1114     }
1115 
1116     return val;
1117 }
1118 
1119 */
1120 
1121 #ifdef NVML_FOUND
1122 #include "nvml.h"
1123 
gpu_mon_init_func()1124 void gpu_mon_init_func()
1125 {
1126    nvmlInit();
1127 }
1128 
gpu_mon_cleanup_func()1129 void gpu_mon_cleanup_func()
1130 {
1131    nvmlShutdown();
1132 }
1133 
num_gpus_func()1134 unsigned int num_gpus_func()
1135 {
1136    unsigned int ret;
1137    nvmlDeviceGetCount(&ret);
1138    return ret;
1139 }
1140 
gpu_utilization_func(unsigned int * gpu_util_rates)1141 void gpu_utilization_func(unsigned int *gpu_util_rates)
1142 {
1143    unsigned int num_dev, i;
1144    unsigned int *util;
1145    nvmlUtilization_t nvmlUtil;
1146    nvmlDevice_t dev;
1147    num_dev = num_gpus_func();
1148  //  gpu_util_rates=(unsigned int *)malloc(sizeof(unsigned int)*num_dev);
1149    for(i=0;i<num_dev;++i)
1150    {
1151 	nvmlDeviceGetHandleByIndex(i,&dev);
1152 	nvmlDeviceGetUtilizationRates(dev,&nvmlUtil);
1153 	*(gpu_util_rates+i)=nvmlUtil.gpu;
1154    }
1155 
1156 }
1157 
gpu_free_mem_func(unsigned long long * gpu_free_mem)1158 void gpu_free_mem_func(unsigned long long *gpu_free_mem)
1159 {
1160    unsigned int num_dev,i;
1161    nvmlDevice_t dev;
1162    nvmlMemory_t mem;
1163    num_dev=num_gpus_func();
1164   // gpu_free_mem=(unsigned long long *)malloc(sizeof(unsigned long long)*num_dev);
1165    for(i=0;i<num_dev;++i)
1166    {
1167 	nvmlDeviceGetHandleByIndex(i,&dev);
1168 	nvmlDeviceGetMemoryInfo(dev,&mem);
1169 	*(gpu_free_mem+i)=mem.free;
1170    }
1171 }
1172 
gpu_total_mem_func(unsigned long long * gpu_total_mem)1173 void gpu_total_mem_func(unsigned long long *gpu_total_mem)
1174 {
1175    unsigned int num_dev,i;
1176    nvmlDevice_t dev;
1177    nvmlMemory_t mem;
1178    num_dev=num_gpus_func();
1179  //  gpu_total_mem=(unsigned long long *)malloc(sizeof(unsigned long long)*num_dev);
1180    for(i=0;i<num_dev;++i)
1181    {
1182         nvmlDeviceGetHandleByIndex(i,&dev);
1183         nvmlDeviceGetMemoryInfo(dev,&mem);
1184         *(gpu_total_mem+i)=mem.total;
1185    }
1186 }
1187 
gpu_used_mem_func(unsigned long long * gpu_used_mem)1188 void gpu_used_mem_func(unsigned long long *gpu_used_mem)
1189 {
1190    unsigned int num_dev,i;
1191    nvmlDevice_t dev;
1192    nvmlMemory_t mem;
1193    num_dev=num_gpus_func();
1194  //  gpu_used_mem=(unsigned long long *)malloc(sizeof(unsigned long long)*num_dev);
1195    for(i=0;i<num_dev;++i)
1196    {
1197         nvmlDeviceGetHandleByIndex(i,&dev);
1198         nvmlDeviceGetMemoryInfo(dev,&mem);
1199         *(gpu_used_mem+i)=mem.used;
1200    }
1201 }
1202 
gpu_temp_func(unsigned int * temp)1203 void gpu_temp_func(unsigned int *temp)
1204 {
1205    unsigned int num_dev,i,t;
1206    nvmlDevice_t dev;
1207    num_dev=num_gpus_func();
1208 //   temp=(unsigned int *)malloc(sizeof(unsigned int)*num_dev);
1209    for(i=0;i<num_dev;++i)
1210    {
1211 	nvmlDeviceGetHandleByIndex(i,&dev);
1212 	nvmlDeviceGetTemperature(dev,NVML_TEMPERATURE_GPU,&t);
1213 	*(temp+i)=t;
1214    }
1215 }
1216 
gpu_power_util_func(unsigned int * power)1217 void gpu_power_util_func(unsigned int *power)
1218 {
1219    unsigned int num_dev,i,p;
1220    nvmlDevice_t dev;
1221    num_dev=num_gpus_func();
1222 //   power=(unsigned int*)malloc(sizeof(unsigned int)*num_dev);
1223    for(i=0;i<num_dev;++i)
1224    {
1225 	nvmlDeviceGetHandleByIndex(i,&dev);
1226 	nvmlDeviceGetPowerUsage(dev,&p);
1227 	*(power+i)=p;
1228    }
1229 
1230 }
1231 
1232 #endif
1233