1/*
2* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*
5* This code is free software; you can redistribute it and/or modify it
6* under the terms of the GNU General Public License version 2 only, as
7* published by the Free Software Foundation.
8*
9* This code is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12* version 2 for more details (a copy is included in the LICENSE file that
13* accompanied this code).
14*
15* You should have received a copy of the GNU General Public License version
16* 2 along with this work; if not, write to the Free Software Foundation,
17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18*
19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20* or visit www.oracle.com if you need additional information or have any
21* questions.
22*
23*/
24
25#ifndef SHARE_UTILITIES_TICKS_HPP
26#define SHARE_UTILITIES_TICKS_HPP
27
28#include "jni.h"
29#include "memory/allocation.hpp"
30#include "utilities/macros.hpp"
31
32// Time sources
33class ElapsedCounterSource {
34 public:
35 typedef jlong Type;
36 static uint64_t frequency();
37 static Type now();
38 static double seconds(Type value);
39 static uint64_t milliseconds(Type value);
40 static uint64_t microseconds(Type value);
41 static uint64_t nanoseconds(Type value);
42};
43
44// Not guaranteed to be synchronized across hardware threads and
45// therefore software threads, and can be updated asynchronously
46// by software. now() can jump backwards as well as jump forward
47// when threads query different cores/sockets.
48// Very much not recommended for general use. Caveat emptor.
49class FastUnorderedElapsedCounterSource {
50 public:
51 typedef jlong Type;
52 static uint64_t frequency();
53 static Type now();
54 static double seconds(Type value);
55 static uint64_t milliseconds(Type value);
56 static uint64_t microseconds(Type value);
57 static uint64_t nanoseconds(Type value);
58};
59
60template <typename T1, typename T2>
61class PairRep {
62 public:
63 T1 val1;
64 T2 val2;
65
66 PairRep() : val1((T1)0), val2((T2)0) {}
67 void operator+=(const PairRep& rhs) {
68 val1 += rhs.val1;
69 val2 += rhs.val2;
70 }
71 void operator-=(const PairRep& rhs) {
72 val1 -= rhs.val1;
73 val2 -= rhs.val2;
74 }
75 bool operator==(const PairRep& rhs) const {
76 return val1 == rhs.val1;
77 }
78 bool operator!=(const PairRep& rhs) const {
79 return !operator==(rhs);
80 }
81 bool operator<(const PairRep& rhs) const {
82 return val1 < rhs.val1;
83 }
84 bool operator>(const PairRep& rhs) const {
85 return val1 > rhs.val1;
86 }
87};
88
89template <typename T1, typename T2>
90PairRep<T1, T2> operator-(const PairRep<T1, T2>& lhs, const PairRep<T1, T2>& rhs) {
91 PairRep<T1, T2> temp(lhs);
92 temp -= rhs;
93 return temp;
94}
95
96typedef PairRep<ElapsedCounterSource::Type, FastUnorderedElapsedCounterSource::Type> CompositeTime;
97
98class CompositeElapsedCounterSource {
99 public:
100 typedef CompositeTime Type;
101 static uint64_t frequency();
102 static Type now();
103 static double seconds(Type value);
104 static uint64_t milliseconds(Type value);
105 static uint64_t microseconds(Type value);
106 static uint64_t nanoseconds(Type value);
107};
108
109template <typename TimeSource>
110class Representation {
111 public:
112 typedef typename TimeSource::Type Type;
113 protected:
114 Type _rep;
115 Representation(const Representation<TimeSource>& end, const Representation<TimeSource>& start) : _rep(end._rep - start._rep) {}
116 Representation() : _rep() {}
117 public:
118 void operator+=(const Representation<TimeSource>& rhs) {
119 _rep += rhs._rep;
120 }
121 void operator-=(const Representation<TimeSource>& rhs) {
122 _rep -= rhs._rep;
123 }
124 bool operator==(const Representation<TimeSource>& rhs) const {
125 return _rep == rhs._rep;
126 }
127 bool operator!=(const Representation<TimeSource>& rhs) const {
128 return !operator==(rhs);
129 }
130 bool operator<(const Representation<TimeSource>& rhs) const {
131 return _rep < rhs._rep;
132 }
133 bool operator>(const Representation<TimeSource>& rhs) const {
134 return _rep > rhs._rep;
135 }
136 bool operator<=(const Representation<TimeSource>& rhs) const {
137 return !operator>(rhs);
138 }
139 bool operator>=(const Representation<TimeSource>& rhs) const {
140 return !operator<(rhs);
141 }
142 double seconds() const {
143 return TimeSource::seconds(_rep);
144 }
145 uint64_t milliseconds() const {
146 return TimeSource::milliseconds(_rep);
147 }
148 uint64_t microseconds() const {
149 return TimeSource::microseconds(_rep);
150 }
151 uint64_t nanoseconds() const {
152 return TimeSource::nanoseconds(_rep);
153 }
154};
155
156template <typename TimeSource>
157class CounterRepresentation : public Representation<TimeSource> {
158 protected:
159 CounterRepresentation(const CounterRepresentation& end, const CounterRepresentation& start) : Representation<TimeSource>(end, start) {}
160 explicit CounterRepresentation(jlong value) : Representation<TimeSource>() {
161 this->_rep = value;
162 }
163 public:
164 CounterRepresentation() : Representation<TimeSource>() {}
165 typename TimeSource::Type value() const { return this->_rep; }
166 operator typename TimeSource::Type() { return value(); }
167};
168
169template <typename TimeSource>
170class CompositeCounterRepresentation : public Representation<TimeSource> {
171 protected:
172 CompositeCounterRepresentation(const CompositeCounterRepresentation& end, const CompositeCounterRepresentation& start) :
173 Representation<TimeSource>(end, start) {}
174 explicit CompositeCounterRepresentation(jlong value) : Representation<TimeSource>() {
175 this->_rep.val1 = value;
176 this->_rep.val2 = value;
177 }
178 public:
179 CompositeCounterRepresentation() : Representation<TimeSource>() {}
180 ElapsedCounterSource::Type value() const { return this->_rep.val1; }
181 FastUnorderedElapsedCounterSource::Type ft_value() const { return this->_rep.val2; }
182};
183
184template <template <typename> class, typename>
185class TimeInstant;
186
187template <template <typename> class Rep, typename TimeSource>
188class TimeInterval : public Rep<TimeSource> {
189 template <template <typename> class, typename>
190 friend class TimeInstant;
191 TimeInterval(const TimeInstant<Rep, TimeSource>& end, const TimeInstant<Rep, TimeSource>& start) : Rep<TimeSource>(end, start) {}
192 public:
193 TimeInterval() : Rep<TimeSource>() {}
194 TimeInterval<Rep, TimeSource> operator+(const TimeInterval<Rep, TimeSource>& rhs) const {
195 TimeInterval<Rep, TimeSource> temp(*this);
196 temp += rhs;
197 return temp;
198 }
199 TimeInterval<Rep, TimeSource> operator-(const TimeInterval<Rep, TimeSource>& rhs) const {
200 TimeInterval<Rep, TimeSource> temp(*this);
201 temp -= rhs;
202 return temp;
203 }
204};
205
206template <template <typename> class Rep, typename TimeSource>
207class TimeInstant : public Rep<TimeSource> {
208 public:
209 TimeInstant() : Rep<TimeSource>() {}
210 TimeInstant<Rep, TimeSource>& operator+=(const TimeInterval<Rep, TimeSource>& rhs) {
211 Rep<TimeSource>::operator+=(rhs);
212 return *this;
213 }
214 TimeInstant<Rep, TimeSource>& operator-=(const TimeInterval<Rep, TimeSource>& rhs) {
215 Rep<TimeSource>::operator-=(rhs);
216 return *this;
217 }
218 TimeInterval<Rep, TimeSource> operator+(const TimeInstant<Rep, TimeSource>& end) const {
219 return TimeInterval<Rep, TimeSource>(end, *this);
220 }
221 TimeInterval<Rep, TimeSource> operator-(const TimeInstant<Rep, TimeSource>& start) const {
222 return TimeInterval<Rep, TimeSource>(*this, start);
223 }
224 void stamp() {
225 this->_rep = TimeSource::now();
226 }
227 static TimeInstant<Rep, TimeSource> now() {
228 TimeInstant<Rep, TimeSource> temp;
229 temp.stamp();
230 return temp;
231 }
232 private:
233 TimeInstant(jlong ticks) : Rep<TimeSource>(ticks) {}
234 friend class GranularTimer;
235 friend class ObjectSample;
236 // GC unit tests
237 friend class TimePartitionPhasesIteratorTest;
238 friend class GCTimerTest;
239};
240
241#if INCLUDE_JFR
242typedef TimeInstant<CompositeCounterRepresentation, CompositeElapsedCounterSource> Ticks;
243typedef TimeInterval<CompositeCounterRepresentation, CompositeElapsedCounterSource> Tickspan;
244#else
245typedef TimeInstant<CounterRepresentation, ElapsedCounterSource> Ticks;
246typedef TimeInterval<CounterRepresentation, ElapsedCounterSource> Tickspan;
247#endif
248
249#endif // SHARE_UTILITIES_TICKS_HPP
250