1*a9fa9459Szrj // timer.cc -- helper class for time accounting
2*a9fa9459Szrj 
3*a9fa9459Szrj // Copyright (C) 2009-2016 Free Software Foundation, Inc.
4*a9fa9459Szrj // Written by Rafael Avila de Espindola <espindola@google.com>.
5*a9fa9459Szrj 
6*a9fa9459Szrj // This file is part of gold.
7*a9fa9459Szrj 
8*a9fa9459Szrj // This program is free software; you can redistribute it and/or modify
9*a9fa9459Szrj // it under the terms of the GNU General Public License as published by
10*a9fa9459Szrj // the Free Software Foundation; either version 3 of the License, or
11*a9fa9459Szrj // (at your option) any later version.
12*a9fa9459Szrj 
13*a9fa9459Szrj // This program is distributed in the hope that it will be useful,
14*a9fa9459Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*a9fa9459Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*a9fa9459Szrj // GNU General Public License for more details.
17*a9fa9459Szrj 
18*a9fa9459Szrj // You should have received a copy of the GNU General Public License
19*a9fa9459Szrj // along with this program; if not, write to the Free Software
20*a9fa9459Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*a9fa9459Szrj // MA 02110-1301, USA.
22*a9fa9459Szrj 
23*a9fa9459Szrj #include "gold.h"
24*a9fa9459Szrj 
25*a9fa9459Szrj #include <unistd.h>
26*a9fa9459Szrj 
27*a9fa9459Szrj #ifdef HAVE_TIMES
28*a9fa9459Szrj #include <sys/times.h>
29*a9fa9459Szrj #endif
30*a9fa9459Szrj 
31*a9fa9459Szrj #include "libiberty.h"
32*a9fa9459Szrj 
33*a9fa9459Szrj #include "timer.h"
34*a9fa9459Szrj 
35*a9fa9459Szrj namespace gold
36*a9fa9459Szrj {
37*a9fa9459Szrj 
38*a9fa9459Szrj // Class Timer
39*a9fa9459Szrj 
Timer()40*a9fa9459Szrj Timer::Timer()
41*a9fa9459Szrj {
42*a9fa9459Szrj   this->start_time_.wall = 0;
43*a9fa9459Szrj   this->start_time_.user = 0;
44*a9fa9459Szrj   this->start_time_.sys = 0;
45*a9fa9459Szrj }
46*a9fa9459Szrj 
47*a9fa9459Szrj // Start counting the time.
48*a9fa9459Szrj void
start()49*a9fa9459Szrj Timer::start()
50*a9fa9459Szrj {
51*a9fa9459Szrj   this->get_time(&this->start_time_);
52*a9fa9459Szrj }
53*a9fa9459Szrj 
54*a9fa9459Szrj // Record the time used by pass N (0 <= N <= 2).
55*a9fa9459Szrj void
stamp(int n)56*a9fa9459Szrj Timer::stamp(int n)
57*a9fa9459Szrj {
58*a9fa9459Szrj   gold_assert(n >= 0 && n <= 2);
59*a9fa9459Szrj   TimeStats& thispass = this->pass_times_[n];
60*a9fa9459Szrj   this->get_time(&thispass);
61*a9fa9459Szrj }
62*a9fa9459Szrj 
63*a9fa9459Szrj #if HAVE_SYSCONF && defined _SC_CLK_TCK
64*a9fa9459Szrj # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
65*a9fa9459Szrj #else
66*a9fa9459Szrj # ifdef CLK_TCK
67*a9fa9459Szrj #  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
68*a9fa9459Szrj # else
69*a9fa9459Szrj #  ifdef HZ
70*a9fa9459Szrj #   define TICKS_PER_SECOND HZ  /* traditional UNIX */
71*a9fa9459Szrj #  else
72*a9fa9459Szrj #   define TICKS_PER_SECOND 100 /* often the correct value */
73*a9fa9459Szrj #  endif
74*a9fa9459Szrj # endif
75*a9fa9459Szrj #endif
76*a9fa9459Szrj 
77*a9fa9459Szrj // times returns statistics in clock_t units.  This variable will hold the
78*a9fa9459Szrj // conversion factor to seconds.  We use a variable that is initialized once
79*a9fa9459Szrj // because sysconf can be slow.
80*a9fa9459Szrj static long ticks_per_sec;
81*a9fa9459Szrj class Timer_init
82*a9fa9459Szrj {
83*a9fa9459Szrj  public:
Timer_init()84*a9fa9459Szrj   Timer_init()
85*a9fa9459Szrj   {
86*a9fa9459Szrj     ticks_per_sec = TICKS_PER_SECOND;
87*a9fa9459Szrj   }
88*a9fa9459Szrj };
89*a9fa9459Szrj Timer_init timer_init;
90*a9fa9459Szrj 
91*a9fa9459Szrj // Write the current time information.
92*a9fa9459Szrj void
get_time(TimeStats * now)93*a9fa9459Szrj Timer::get_time(TimeStats *now)
94*a9fa9459Szrj {
95*a9fa9459Szrj #ifdef HAVE_TIMES
96*a9fa9459Szrj   tms t;
97*a9fa9459Szrj   now->wall = (times(&t) * 1000) / ticks_per_sec;
98*a9fa9459Szrj   now->user = (t.tms_utime * 1000) / ticks_per_sec;
99*a9fa9459Szrj   now->sys  = (t.tms_stime * 1000) / ticks_per_sec;
100*a9fa9459Szrj #else
101*a9fa9459Szrj   now->wall = get_run_time() / 1000;
102*a9fa9459Szrj   now->user = 0;
103*a9fa9459Szrj   now->sys = 0;
104*a9fa9459Szrj #endif
105*a9fa9459Szrj }
106*a9fa9459Szrj 
107*a9fa9459Szrj // Return the stats since start was called.
108*a9fa9459Szrj Timer::TimeStats
get_elapsed_time()109*a9fa9459Szrj Timer::get_elapsed_time()
110*a9fa9459Szrj {
111*a9fa9459Szrj   TimeStats now;
112*a9fa9459Szrj   this->get_time(&now);
113*a9fa9459Szrj   TimeStats delta;
114*a9fa9459Szrj   delta.wall = now.wall - this->start_time_.wall;
115*a9fa9459Szrj   delta.user = now.user - this->start_time_.user;
116*a9fa9459Szrj   delta.sys = now.sys - this->start_time_.sys;
117*a9fa9459Szrj   return delta;
118*a9fa9459Szrj }
119*a9fa9459Szrj 
120*a9fa9459Szrj // Return the stats for pass N (0 <= N <= 2).
121*a9fa9459Szrj Timer::TimeStats
get_pass_time(int n)122*a9fa9459Szrj Timer::get_pass_time(int n)
123*a9fa9459Szrj {
124*a9fa9459Szrj   gold_assert(n >= 0 && n <= 2);
125*a9fa9459Szrj   TimeStats thispass = this->pass_times_[n];
126*a9fa9459Szrj   TimeStats& lastpass = n > 0 ? this->pass_times_[n-1] : this->start_time_;
127*a9fa9459Szrj   thispass.wall -= lastpass.wall;
128*a9fa9459Szrj   thispass.user -= lastpass.user;
129*a9fa9459Szrj   thispass.sys -= lastpass.sys;
130*a9fa9459Szrj   return thispass;
131*a9fa9459Szrj }
132*a9fa9459Szrj 
133*a9fa9459Szrj }
134