aboutsummaryrefslogtreecommitdiff
path: root/gold/timer.cc
blob: 6df9b68dad0d107b39fea3b7d26708413a6c1c45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// timer.cc -- helper class for time accounting

// Copyright (C) 2009-2023 Free Software Foundation, Inc.
// Written by Rafael Avila de Espindola <espindola@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#include "gold.h"

#include <unistd.h>

#ifdef HAVE_TIMES
#include <sys/times.h>
#endif

#include "libiberty.h"

#include "timer.h"

namespace gold
{

// Class Timer

Timer::Timer()
{
  this->start_time_.wall = 0;
  this->start_time_.user = 0;
  this->start_time_.sys = 0;
}

// Start counting the time.
void
Timer::start()
{
  this->get_time(&this->start_time_);
}

// Record the time used by pass N (0 <= N <= 2).
void
Timer::stamp(int n)
{
  gold_assert(n >= 0 && n <= 2);
  TimeStats& thispass = this->pass_times_[n];
  this->get_time(&thispass);
}

#if HAVE_SYSCONF && defined _SC_CLK_TCK
# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
#else
# ifdef CLK_TCK
#  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
# else
#  ifdef HZ
#   define TICKS_PER_SECOND HZ  /* traditional UNIX */
#  else
#   define TICKS_PER_SECOND 100 /* often the correct value */
#  endif
# endif
#endif

// times returns statistics in clock_t units.  This variable will hold the
// conversion factor to seconds.  We use a variable that is initialized once
// because sysconf can be slow.
static long ticks_per_sec;
class Timer_init
{
 public:
  Timer_init()
  {
    ticks_per_sec = TICKS_PER_SECOND;
  }
};
Timer_init timer_init;

// Write the current time information.
void
Timer::get_time(TimeStats *now)
{
#ifdef HAVE_TIMES
  tms t;
  now->wall = (times(&t) * 1000) / ticks_per_sec;
  now->user = (t.tms_utime * 1000) / ticks_per_sec;
  now->sys  = (t.tms_stime * 1000) / ticks_per_sec;
#else
  now->wall = get_run_time() / 1000;
  now->user = 0;
  now->sys = 0;
#endif
}

// Return the stats since start was called.
Timer::TimeStats
Timer::get_elapsed_time()
{
  TimeStats now;
  this->get_time(&now);
  TimeStats delta;
  delta.wall = now.wall - this->start_time_.wall;
  delta.user = now.user - this->start_time_.user;
  delta.sys = now.sys - this->start_time_.sys;
  return delta;
}

// Return the stats for pass N (0 <= N <= 2).
Timer::TimeStats
Timer::get_pass_time(int n)
{
  gold_assert(n >= 0 && n <= 2);
  TimeStats thispass = this->pass_times_[n];
  TimeStats& lastpass = n > 0 ? this->pass_times_[n-1] : this->start_time_;
  thispass.wall -= lastpass.wall;
  thispass.user -= lastpass.user;
  thispass.sys -= lastpass.sys;
  return thispass;
}

}