1 /*
2 * Copyright (C) 2016 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #if defined(HAVE_SETITIMER)
26 # include <sys/time.h>
27 # ifndef ITIMER_REAL
28 # define ITIMER_REAL 0
29 # endif
30 # ifndef ITIMER_VIRTUAL
31 # define ITIMER_VIRTUAL 1
32 # endif
33 # ifndef ITIMER_PROF
34 # define ITIMER_PROF 2
35 # endif
36 # define MAXITIMER 999
37 #endif
38
39 #if defined(HAVE_GETRUSAGE)
40 # include <sys/types.h>
41 # ifdef HAVE_SYS_RESOURCE_H
42 # include <sys/resource.h>
43 # endif
44 # ifdef HAVE_SYS_RUSAGE_H
45 # include <sys/rusage.h>
46 # endif
47 # ifndef RUSAGE_SELF
48 # define RUSAGE_SELF 0
49 # endif
50 #endif
51
52 #if defined(HAVE_GETTIMEOFDAY)
53 # include <sys/time.h>
54 #else
55 # include <time.h>
56 #endif
57
58 #include <stdlib.h>
59 #include <inttypes.h>
60 // #include <syslog.h>
61
62 #if defined(HAVE_SETITIMER)
63 static struct itimerval it_set;
64 static uint32_t addsec,addusec;
65 #endif
66
67 #if defined(HAVE_GETRUSAGE)
68 static uint64_t lastautime;
69 static uint64_t lastastime;
70 #endif
71
72 static uint64_t lastget;
73
cpu_init(void)74 void cpu_init (void) {
75 #if defined(HAVE_SETITIMER)
76 struct itimerval rc,uc,pc;
77 #endif
78 #if defined(HAVE_GETRUSAGE)
79 struct rusage rus;
80 #endif
81 #if defined(HAVE_GETTIMEOFDAY)
82 struct timeval tod;
83 #endif
84
85 #if defined(HAVE_GETTIMEOFDAY)
86 gettimeofday(&tod,NULL);
87 lastget = tod.tv_sec;
88 lastget *= UINT64_C(1000000);
89 lastget += tod.tv_usec;
90 #else
91 lastget = time(NULL);
92 lastget *= UINT64_C(1000000);
93 #endif
94
95 #if defined(HAVE_SETITIMER)
96 addsec = 0;
97 addusec = 0;
98 it_set.it_interval.tv_sec = 0;
99 it_set.it_interval.tv_usec = 0;
100 it_set.it_value.tv_sec = MAXITIMER;
101 it_set.it_value.tv_usec = 999999;
102 setitimer(ITIMER_REAL,&it_set,&rc); // real time
103 setitimer(ITIMER_VIRTUAL,&it_set,&uc); // user time
104 setitimer(ITIMER_PROF,&it_set,&pc); // user time + system time
105 #endif
106
107 #if defined(HAVE_GETRUSAGE)
108 getrusage(RUSAGE_SELF,&rus);
109
110 lastautime = (uint64_t)rus.ru_utime.tv_sec;
111 lastautime *= UINT64_C(1000000);
112 lastautime += (uint64_t)rus.ru_utime.tv_usec;
113
114 lastastime = (uint64_t)rus.ru_stime.tv_sec;
115 lastastime *= UINT64_C(1000000);
116 lastastime += (uint64_t)rus.ru_stime.tv_usec;
117 #endif
118 }
119
cpu_used(uint64_t * scpu,uint64_t * ucpu)120 void cpu_used (uint64_t *scpu,uint64_t *ucpu) {
121 #if defined(HAVE_SETITIMER)
122 struct itimerval rc,uc,pc;
123 uint64_t ucusec,pcusec;
124 #endif
125 #if defined(HAVE_GETRUSAGE)
126 struct rusage rus;
127 uint64_t autime,astime;
128 #endif
129 uint64_t rdiff,now;
130 #if defined(HAVE_GETTIMEOFDAY)
131 struct timeval tod;
132 #endif
133 uint64_t systime,usertime;
134
135 #if defined(HAVE_GETTIMEOFDAY)
136 gettimeofday(&tod,NULL);
137 now = tod.tv_sec;
138 now *= UINT64_C(1000000);
139 now += tod.tv_usec;
140 #else
141 now = time(NULL);
142 now *= UINT64_C(1000000);
143 #endif
144
145 if (now>lastget) {
146 rdiff = now-lastget;
147 lastget = now;
148 } else {
149 rdiff = 0;
150 }
151
152 systime = 0;
153 usertime = 0;
154
155 // syslog(LOG_NOTICE,"rdiff1: %"PRIu64,rdiff);
156 #if defined(HAVE_SETITIMER)
157 /* method 1 - use itimers - usually worse */
158 setitimer(ITIMER_REAL,&it_set,&rc); // real time
159 setitimer(ITIMER_VIRTUAL,&it_set,&uc); // user time
160 setitimer(ITIMER_PROF,&it_set,&pc); // user time + system time
161
162 rc.it_value.tv_sec = MAXITIMER-rc.it_value.tv_sec;
163 rc.it_value.tv_usec = 999999-rc.it_value.tv_usec;
164 uc.it_value.tv_sec = MAXITIMER-uc.it_value.tv_sec;
165 uc.it_value.tv_usec = 999999-uc.it_value.tv_usec;
166 pc.it_value.tv_sec = MAXITIMER-pc.it_value.tv_sec;
167 pc.it_value.tv_usec = 999999-pc.it_value.tv_usec;
168 addsec += rc.it_value.tv_sec;
169 addusec += rc.it_value.tv_usec;
170 while (addusec>1000000) {
171 addusec-=1000000;
172 addsec++;
173 }
174
175 if (rc.it_value.tv_sec>=0 && rc.it_value.tv_usec>=0) {
176 rdiff = (uint64_t)rc.it_value.tv_sec;
177 rdiff *= UINT64_C(1000000);
178 rdiff += (uint64_t)rc.it_value.tv_usec;
179 }
180 if (uc.it_value.tv_sec>=0 && pc.it_value.tv_sec>=0 && uc.it_value.tv_usec>=0 && pc.it_value.tv_usec>=0) {
181 ucusec = (uint64_t)uc.it_value.tv_sec;
182 ucusec *= UINT64_C(1000000);
183 ucusec += (uint64_t)uc.it_value.tv_usec;
184 pcusec = (uint64_t)pc.it_value.tv_sec;
185 pcusec *= UINT64_C(1000000);
186 pcusec += (uint64_t)pc.it_value.tv_usec;
187 } else {
188 ucusec = 0;
189 pcusec = 0;
190 }
191
192 if (pcusec>ucusec) {
193 pcusec-=ucusec;
194 } else {
195 pcusec=0;
196 }
197 usertime = ucusec;
198 systime = pcusec;
199 #endif
200
201 // syslog(LOG_NOTICE,"rdiff2: %"PRIu64,rdiff);
202 // syslog(LOG_NOTICE,"usertime1: %"PRIu64",systime1: %"PRIu64,usertime,systime);
203
204 #if defined(HAVE_GETRUSAGE)
205 /* method 2 - use getrusage - usually better (if both are available, overwrites data set by itimer method) */
206 getrusage(RUSAGE_SELF,&rus);
207
208 autime = (uint64_t)rus.ru_utime.tv_sec;
209 autime *= UINT64_C(1000000);
210 autime += (uint64_t)rus.ru_utime.tv_usec;
211
212 astime = (uint64_t)rus.ru_stime.tv_sec;
213 astime *= UINT64_C(1000000);
214 astime += (uint64_t)rus.ru_stime.tv_usec;
215
216 if (autime>lastautime) {
217 usertime = autime - lastautime;
218 lastautime = autime;
219 }
220
221 if (astime>lastastime) {
222 systime = astime - lastastime;
223 lastastime = astime;
224 }
225 #endif
226
227 // syslog(LOG_NOTICE,"usertime2: %"PRIu64",systime2: %"PRIu64,usertime,systime);
228
229 if (rdiff>0) {
230 *scpu = (systime*UINT64_C(1000000000)) / rdiff;
231 *ucpu = (usertime*UINT64_C(1000000000)) / rdiff;
232 } else {
233 *scpu = 0;
234 *ucpu = 0;
235 }
236
237 // syslog(LOG_NOTICE,"scpu: %"PRIu32",ucpu: %"PRIu32,*scpu,*ucpu);
238 }
239