1 /*
   2 * Copyright (c) 2013, 2018, 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_VM_UTILITIES_TICKS_HPP
  26 #define SHARE_VM_UTILITIES_TICKS_HPP
  27 
  28 #include "jni.h"
  29 #include "memory/allocation.hpp"
  30 #include "utilities/macros.hpp"
  31 
  32 // Time sources
  33 class 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.
  49 class 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 
  60 template <typename T1, typename T2>
  61 class 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 
  89 template <typename T1, typename T2>
  90 PairRep<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 
  96 typedef PairRep<ElapsedCounterSource::Type, FastUnorderedElapsedCounterSource::Type> CompositeTime;
  97 
  98 class 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 
 109 template <typename TimeSource>
 110 class 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 
 156 template <typename TimeSource>
 157 class 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 
 169 template <typename TimeSource>
 170 class 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 
 184 template <template <typename> class, typename>
 185 class TimeInstant;
 186 
 187 template <template <typename> class Rep, typename TimeSource>
 188 class 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 
 206 template <template <typename> class Rep, typename TimeSource>
 207 class 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 VM tests
 237   friend class TimePartitionPhasesIteratorTest;
 238   friend class GCTimerTest;
 239 };
 240 
 241 #if INCLUDE_JFR
 242 typedef TimeInstant<CompositeCounterRepresentation, CompositeElapsedCounterSource> Ticks;
 243 typedef TimeInterval<CompositeCounterRepresentation, CompositeElapsedCounterSource> Tickspan;
 244 #else
 245 typedef TimeInstant<CounterRepresentation, ElapsedCounterSource> Ticks;
 246 typedef TimeInterval<CounterRepresentation, ElapsedCounterSource> Tickspan;
 247 #endif
 248 
 249 #endif // SHARE_VM_UTILITIES_TICKS_HPP