Strip off version numbers from dir name
[dockapps.git] / wmcpuload / src / cpu_linux.c
blobc0ec52324203548988de48b69e9b1a6ecfcc0aba
1 /*
2 * cpu_linux.c - module to get cpu usage, for GNU/Linux
4 * Copyright (C) 2001, 2002 Seiichi SATO <ssato@sh.rim.or.jp>
6 * licensed under the GPL
7 */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "cpu.h"
19 #include <dirent.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <linux/limits.h>
24 #ifdef USE_SMP
25 #include <linux/threads.h>
26 #endif
28 static void set_pidlist_from_namelist(int names, char **name_list);
29 static int get_cpuusage_bypid(pid_t pid);
31 static int *pid_list;
32 static int pids;
34 void cpu_init(void)
36 /* You don't need initialization under GNU/Linux */
37 return;
40 /* returns current cpu usage in percent */
41 int
42 cpu_get_usage(cpu_options *opts)
44 static int pre_used, pre_total;
45 static int pre_ig_used;
46 int usage;
47 int cpu, nice, system, idle;
48 int used = 0, total = 0;
49 int ig_used = 0;
50 int i;
52 FILE *fp;
53 if (!(fp = fopen("/proc/stat", "r"))) {
54 perror("can't open /proc/stat");
55 exit(1);
58 fscanf(fp, "%*s %d %d %d %d", &cpu, &nice, &system, &idle);
60 #ifdef USE_SMP
61 if (opts->cpu_number >= 0) {
62 char cpu_name[20];
63 if (opts->cpu_number > NR_CPUS - 1) {
64 fprintf (stderr, "MAX CPU number that can be running in SMP is %d\n", NR_CPUS - 1);
65 exit(1);
68 for (i = 0; i <= opts->cpu_number; i++) {
69 fscanf(fp, "%s %d %d %d %d", cpu_name, &cpu, &nice, &system, &idle);
70 if (strncmp(cpu_name, "cpu", 3)){
71 fprintf (stderr, "can't find cpu%d!\n", opts->cpu_number);
72 exit (1);
76 #endif /* USE_SMP */
78 fclose(fp);
79 used = cpu + system;
80 if (!opts->ignore_nice)
81 used += nice;
82 total = cpu + nice + system + idle;
84 /* get CPU usage of processes which specified by name with '-p' option */
85 if (opts->ignore_procs) {
86 pids = 0;
87 if (!(pid_list = malloc(sizeof(pid_t)))) {
88 perror("malloc");
89 exit(1);
91 set_pidlist_from_namelist(opts->ignore_procs, opts->ignore_proc_list);
92 for (i = 0; i < pids; i++)
93 ig_used += get_cpuusage_bypid(pid_list[i]);
94 free(pid_list);
97 /* calc CPU usage */
98 if ((pre_total == 0) || !(total - pre_total > 0)) {
99 usage = 0;
100 } else if (ig_used - pre_ig_used > 0) {
101 usage = (100 * (double)(used - pre_used - ig_used + pre_ig_used)) /
102 (double)(total - pre_total);
103 } else {
104 usage = (100 * (double)(used - pre_used)) / (double)(total - pre_total);
107 /* save current values for next calculation */
108 pre_ig_used = ig_used;
109 pre_used = used;
110 pre_total = total;
112 return usage;
115 /* set pid list table from command names */
116 static void
117 set_pidlist_from_namelist(int names, char **name_list)
119 DIR *dir;
120 struct dirent *de;
121 FILE *fp;
122 char path[PATH_MAX + 1];
123 char comm[COMM_LEN];
124 pid_t pid;
125 int i;
127 if (!(dir = opendir("/proc"))) {
128 perror("can't open /proc");
129 exit(1);
132 /* search specified process from all processes */
133 chdir("/proc");
134 while ((de = readdir(dir)) != NULL) {
135 if ((de->d_name[0] != '.') &&
136 ((de->d_name[0] >= '0') && (de->d_name[0] <= '9'))) {
137 pid = (pid_t) atoi(de->d_name);
138 sprintf(path, "%d/stat", pid);
139 if ((fp = fopen(path, "r")) != NULL) {
140 fscanf(fp, "%*d (%[^)]", comm);
141 for (i = 0; i < names; i++) {
142 if (strcmp(comm, name_list[i]) == 0) {
143 /* add process id to list */
144 pids++;
145 if (!(pid_list=realloc(pid_list, pids*sizeof(pid_t)))){
146 perror("realloc() failed");
147 exit(1);
149 pid_list[pids - 1] = pid;
152 fclose(fp);
156 closedir(dir);
159 static int
160 get_cpuusage_bypid(pid_t pid)
162 FILE *fp;
163 char path[PATH_MAX];
164 int utime = 0, stime = 0;
165 int ret = 0;
167 sprintf(path, "/proc/%d/stat", pid);
168 if ((fp = fopen(path, "r")) != NULL) {
169 fscanf(fp, "%*d %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d ",
170 &utime, &stime);
171 fclose(fp);
174 ret = utime + stime;
175 return ret;