1 //  boost process_cpu_clocks.cpp  -----------------------------------------------------------//
2 
3 //  Copyright Beman Dawes 1994, 2006, 2008
4 //  Copyright Vicente J. Botet Escriba 2009
5 
6 //  Distributed under the Boost Software License, Version 1.0.
7 //  See http://www.boost.org/LICENSE_1_0.txt
8 
9 //  See http://www.boost.org/libs/chrono for documentation.
10 
11 //--------------------------------------------------------------------------------------//
12 
13 #include <boost/chrono/config.hpp>
14 #include <boost/chrono/process_cpu_clocks.hpp>
15 #include <boost/assert.hpp>
16 
17 #include <sys/time.h> //for gettimeofday and timeval
18 #include <sys/times.h> //for times
19 # include <unistd.h>
20 
21 namespace boost
22 {
23   namespace chrono
24   {
25     namespace chrono_detail
26     {
27 
tick_factor()28       inline long tick_factor() // multiplier to convert ticks
29       //  to nanoseconds; -1 if unknown
30       {
31         static long factor = 0;
32         if (!factor)
33         {
34           if ((factor = ::sysconf(_SC_CLK_TCK)) <= 0)
35             factor = -1;
36           else
37           {
38             BOOST_ASSERT(factor <= 1000000000l); // doesn't handle large ticks
39             factor = 1000000000l / factor; // compute factor
40             if (!factor)
41               factor = -1;
42           }
43         }
44         return factor;
45       }
46     }
47 
48 
now()49     process_real_cpu_clock::time_point process_real_cpu_clock::now() BOOST_NOEXCEPT
50     {
51 #if 1
52       tms tm;
53       clock_t c = ::times(&tm);
54       if (c == clock_t(-1)) // error
55       {
56         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
57       } else
58       {
59         long factor = chrono_detail::tick_factor();
60         if (factor != -1)
61         {
62           return time_point(nanoseconds(c * factor));
63         } else
64         {
65           BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
66         }
67       }
68       return time_point();
69 #else
70       clock_t c = ::clock();
71       if (c == clock_t(-1)) // error
72       {
73         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
74       } else
75       {
76         long factor = chrono_detail::tick_factor();
77         if (factor != -1)
78         {
79           return time_point(nanoseconds(c * factor));
80         } else
81         {
82           BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
83         }
84       }
85       return time_point();
86 #endif
87     }
88 
89 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
now(system::error_code & ec)90     process_real_cpu_clock::time_point process_real_cpu_clock::now(system::error_code & ec)
91     {
92 
93 #if 1
94       tms tm;
95       clock_t c = ::times(&tm);
96       if (c == clock_t(-1)) // error
97       {
98         if (BOOST_CHRONO_IS_THROWS(ec))
99         {
100           boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_real_cpu_clock"));
101         } else
102         {
103           ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
104           return time_point();
105         }
106       } else
107       {
108         long factor = chrono_detail::tick_factor();
109         if (factor != -1)
110         {
111           if (!BOOST_CHRONO_IS_THROWS(ec))
112           {
113             ec.clear();
114           }
115           return time_point(nanoseconds(c * factor));
116         } else
117         {
118           if (BOOST_CHRONO_IS_THROWS(ec))
119           {
120             boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_real_cpu_clock"));
121           } else
122           {
123             ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
124             return time_point();
125           }
126         }
127       }
128 #else
129       clock_t c = ::clock();
130       if (c == clock_t(-1)) // error
131       {
132         if (BOOST_CHRONO_IS_THROWS(ec))
133         {
134           boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_real_cpu_clock"));
135         } else
136         {
137           ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
138           return time_point();
139         }
140       } else
141       {
142         long factor = chrono_detail::tick_factor();
143         if (factor != -1)
144         {
145           if (!BOOST_CHRONO_IS_THROWS(ec))
146           {
147             ec.clear();
148           }
149           return time_point(nanoseconds(c * factor));
150         } else
151         {
152           if (BOOST_CHRONO_IS_THROWS(ec))
153           {
154             boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_real_cpu_clock"));
155           } else
156           {
157             ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
158             return time_point();
159           }
160         }
161       }
162 #endif
163 
164     }
165 #endif
166 
167 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
now(system::error_code & ec)168     process_user_cpu_clock::time_point process_user_cpu_clock::now(system::error_code & ec)
169     {
170       tms tm;
171       clock_t c = ::times(&tm);
172       if (c == clock_t(-1)) // error
173       {
174         if (BOOST_CHRONO_IS_THROWS(ec))
175         {
176           boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_user_cpu_clock"));
177         } else
178         {
179           ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
180           return time_point();
181         }
182       } else
183       {
184         long factor = chrono_detail::tick_factor();
185         if (factor != -1)
186         {
187           if (!BOOST_CHRONO_IS_THROWS(ec))
188           {
189             ec.clear();
190           }
191           return time_point(nanoseconds((tm.tms_utime + tm.tms_cutime) * factor));
192         } else
193         {
194           if (BOOST_CHRONO_IS_THROWS(ec))
195           {
196             boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_user_cpu_clock"));
197           } else
198           {
199             ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
200             return time_point();
201           }
202         }
203       }
204     }
205 #endif
206 
now()207     process_user_cpu_clock::time_point process_user_cpu_clock::now() BOOST_NOEXCEPT
208     {
209       tms tm;
210       clock_t c = ::times(&tm);
211       if (c == clock_t(-1)) // error
212       {
213         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
214       } else
215       {
216         long factor = chrono_detail::tick_factor();
217         if (factor != -1)
218         {
219           return time_point(nanoseconds((tm.tms_utime + tm.tms_cutime)
220               * factor));
221         } else
222         {
223           BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
224         }
225       }
226       return time_point();
227     }
now()228     process_system_cpu_clock::time_point process_system_cpu_clock::now() BOOST_NOEXCEPT
229     {
230       tms tm;
231       clock_t c = ::times(&tm);
232       if (c == clock_t(-1)) // error
233       {
234         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
235       } else
236       {
237         long factor = chrono_detail::tick_factor();
238         if (factor != -1)
239         {
240           return time_point(nanoseconds((tm.tms_stime + tm.tms_cstime)
241               * factor));
242         } else
243         {
244           BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
245         }
246       }
247       return time_point();
248     }
249 
250 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
now(system::error_code & ec)251     process_system_cpu_clock::time_point process_system_cpu_clock::now(system::error_code & ec)
252     {
253       tms tm;
254       clock_t c = ::times(&tm);
255       if (c == clock_t(-1)) // error
256       {
257         if (BOOST_CHRONO_IS_THROWS(ec))
258         {
259           boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_system_cpu_clock"));
260         } else
261         {
262           ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
263           return time_point();
264         }
265       } else
266       {
267         long factor = chrono_detail::tick_factor();
268         if (factor != -1)
269         {
270           if (!BOOST_CHRONO_IS_THROWS(ec))
271           {
272             ec.clear();
273           }
274           return time_point(nanoseconds((tm.tms_stime + tm.tms_cstime) * factor));
275         } else
276         {
277           if (BOOST_CHRONO_IS_THROWS(ec))
278           {
279             boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_system_cpu_clock"));
280           } else
281           {
282             ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
283             return time_point();
284           }
285         }
286       }
287     }
288 #endif
289 
now()290     process_cpu_clock::time_point process_cpu_clock::now() BOOST_NOEXCEPT
291     {
292       tms tm;
293       clock_t c = ::times(&tm);
294       if (c == clock_t(-1)) // error
295       {
296         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
297       } else
298       {
299         long factor = chrono_detail::tick_factor();
300         if (factor != -1)
301         {
302           time_point::rep
303               r(c * factor, (tm.tms_utime + tm.tms_cutime) * factor, (tm.tms_stime
304                   + tm.tms_cstime) * factor);
305           return time_point(duration(r));
306         } else
307         {
308           BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
309         }
310       }
311       return time_point();
312     }
313 
314 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
now(system::error_code & ec)315     process_cpu_clock::time_point process_cpu_clock::now(system::error_code & ec)
316     {
317 
318       tms tm;
319       clock_t c = ::times(&tm);
320       if (c == clock_t(-1)) // error
321       {
322         if (BOOST_CHRONO_IS_THROWS(ec))
323         {
324           boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_clock"));
325         } else
326         {
327           ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
328           return time_point();
329         }
330       } else
331       {
332         long factor = chrono_detail::tick_factor();
333         if (factor != -1)
334         {
335           time_point::rep
336               r(c * factor, (tm.tms_utime + tm.tms_cutime) * factor, (tm.tms_stime
337                   + tm.tms_cstime) * factor);
338           return time_point(duration(r));
339         } else
340         {
341           if (BOOST_CHRONO_IS_THROWS(ec))
342           {
343             boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_clock"));
344           } else
345           {
346             ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY);
347             return time_point();
348           }
349         }
350       }
351 
352     }
353 #endif
354 
355   }
356 }
357