Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #include <stdio.h>
32 : : #include <string.h>
33 : : #include <stdlib.h>
34 : : #include <signal.h>
35 : : #include <sys/mman.h>
36 : : #include <sys/types.h>
37 : : #include <sys/stat.h>
38 : : #include <fcntl.h>
39 : : #include <unistd.h>
40 : : #include <errno.h>
41 : : #include "compiler.h"
42 : : #include "cpumond.h"
43 : :
44 : : #ifndef DEBUG
45 : : #define NDEBUG
46 : : #endif
47 : : #include <assert.h>
48 : :
49 : : int run;
50 : :
51 : 0 : void sighandler(int signo){
52 : 0 : if (signo == SIGINT)
53 : 0 : run = 0;
54 : 0 : }
55 : :
56 : 0 : void cpumond_destroy(cpumond_entry_t *cpumond_entry){
57 : : assert(cpumond_entry);
58 : :
59 : 0 : if ((cpumond_entry->mm != NULL) && (cpumond_entry->mm != MAP_FAILED))
60 : 0 : if (munmap(cpumond_entry->mm, sizeof(cpumond_t)) == -1)
61 : 0 : perror("munmap");
62 : :
63 : 0 : if (cpumond_entry->fd >= 0)
64 : 0 : if (close(cpumond_entry->fd) == -1)
65 : 0 : perror("close");
66 : :
67 : 0 : if (cpumond_entry->path){
68 : 0 : if (shm_unlink(cpumond_entry->path) == -1)
69 : 0 : perror("shm_unlink");
70 : 0 : free(cpumond_entry->path);
71 : : }
72 : :
73 : 0 : free(cpumond_entry);
74 : :
75 : 0 : return;
76 : : }
77 : :
78 : 0 : cpumond_entry_t *cpumond_create(char *path){
79 : : cpumond_entry_t *cpumond_entry;
80 : :
81 : : assert(path);
82 : :
83 : 0 : cpumond_entry = calloc(1, sizeof(cpumond_entry_t));
84 : 0 : if (!cpumond_entry){
85 : 0 : perror("calloc");
86 : 0 : goto err;
87 : : }
88 : :
89 : 0 : cpumond_entry->fd = shm_open(path, O_RDWR|O_CREAT|O_EXCL,
90 : : S_IRUSR|S_IRGRP|S_IROTH);
91 : 0 : if (cpumond_entry->fd == -1){
92 : 0 : perror("shm_open");
93 : 0 : goto err;
94 : : }
95 : :
96 : 0 : cpumond_entry->path = strdup(path);
97 : 0 : if (!cpumond_entry->path){
98 : 0 : perror("strcpy");
99 : 0 : goto err;
100 : : }
101 : :
102 : 0 : if (ftruncate(cpumond_entry->fd, sizeof(cpumond_t)) == -1){
103 : 0 : perror("ftruncate");
104 : 0 : goto err;
105 : : }
106 : :
107 : 0 : cpumond_entry->mm = mmap(NULL, sizeof(cpumond_t), PROT_READ | PROT_WRITE,
108 : : MAP_SHARED, cpumond_entry->fd, 0);
109 : 0 : if (cpumond_entry->mm == MAP_FAILED){
110 : 0 : perror("mmap");
111 : 0 : goto err;
112 : : }
113 : :
114 : : return cpumond_entry;
115 : :
116 : : err:
117 : 0 : if (cpumond_entry)
118 : 0 : cpumond_destroy(cpumond_entry);
119 : :
120 : : return NULL;
121 : : }
122 : :
123 : 0 : static int statread(int statfd, long long *total, long long *idle){
124 : : long long val[10];
125 : : char buf[256];
126 : 0 : int i, err = 0;
127 : :
128 : 0 : if (lseek(statfd, 0, SEEK_SET) == -1){
129 : 0 : err = (errno)?errno:-1;
130 : 0 : perror("lseek");
131 : : goto out;
132 : : }
133 : :
134 : : memset(buf, 0, sizeof(buf));
135 : 0 : if (read(statfd, buf, sizeof(buf)-1) <= 0){
136 : 0 : err = (errno)?errno:-1;
137 : 0 : perror("read");
138 : : goto out;
139 : : }
140 : 0 : if (sscanf(buf, "cpu %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
141 : : &val[0], &val[1], &val[2], &val[3], &val[4], &val[5], &val[6],
142 : : &val[7], &val[8], &val[9]) != 10){
143 : 0 : err = (errno)?errno:-1;
144 : 0 : perror("sscanf");
145 : : goto out;
146 : : }
147 : :
148 : 0 : *idle = val[3];
149 : 0 : *total = 0;
150 : 0 : for (i=0; i<10; i++)
151 : 0 : *total += val[i];
152 : :
153 : : out:
154 : 0 : return err;
155 : : }
156 : :
157 : 0 : int cpumond_loop(cpumond_entry_t *cpumond_entry){
158 : 0 : long long idle1 = 0, idle2;
159 : 0 : long long total1 = 0, total2;
160 : : int statfd;
161 : 0 : int err = 0;
162 : :
163 : 0 : statfd = open("/proc/stat", O_RDONLY);
164 : 0 : if (statfd == -1){
165 : 0 : err = errno;
166 : 0 : perror("open");
167 : : goto out;
168 : : }
169 : :
170 : 0 : while(run){
171 : 0 : if (statread(statfd, &total2, &idle2) != 0)
172 : : goto out;
173 : :
174 : 0 : if (unlikely(total2 == total1)) {
175 : 0 : sleep(1);
176 : 0 : continue;
177 : : }
178 : :
179 : 0 : cpumond_entry->mm->curr = 100.0 *
180 : 0 : ((total2-total1)-(idle2-idle1))/(total2-total1);
181 : :
182 : 0 : cpumond_entry->mm->idle = 100 - cpumond_entry->mm->curr;
183 : :
184 : : #ifdef DEBUG
185 : : printf("total2: %lld, total1: %lld, idle2: %lld, idle1: %lld, " \
186 : : "cpumond_entry->mm->idle: %f\n", total2, total1, idle2, idle1,
187 : : cpumond_entry->mm->idle);
188 : : #endif
189 : :
190 : 0 : total1 = total2;
191 : 0 : idle1 = idle2;
192 : :
193 : 0 : sleep(1);
194 : : }
195 : :
196 : 0 : memset(cpumond_entry->mm, 0, sizeof(*(cpumond_entry->mm)));
197 : :
198 : : out:
199 : 0 : if (statfd != -1)
200 : 0 : close(statfd);
201 : 0 : return err;
202 : : }
203 : :
204 : 0 : int main(int argc, char **argv){
205 : : cpumond_entry_t *cpumond_entry;
206 : 0 : int err = EXIT_SUCCESS;
207 : :
208 : 0 : signal(SIGINT, sighandler);
209 : :
210 : 0 : cpumond_entry = cpumond_create(CPUMOND_PATH);
211 : 0 : if (!cpumond_entry){
212 : : err = EXIT_FAILURE;
213 : : goto out;
214 : : }
215 : :
216 : 0 : run = 1;
217 : 0 : if (cpumond_loop(cpumond_entry) != 0)
218 : 0 : err = EXIT_FAILURE;
219 : :
220 : : out:
221 : 0 : if (cpumond_entry)
222 : 0 : cpumond_destroy(cpumond_entry);
223 : :
224 : 0 : return err;
225 : : }
|