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 #include "precompiled.hpp"
  26 
  27 //#include "os_linux_x86.inline.hpp"
  28 #ifdef TARGET_OS_ARCH_linux_x86
  29 # include "os_linux_x86.inline.hpp"
  30 #endif
  31 #ifdef TARGET_OS_ARCH_bsd_x86
  32 # include "os_bsd_x86.inline.hpp"
  33 #endif
  34 #ifdef TARGET_OS_ARCH_windows_x86
  35 # include "os_windows_x86.inline.hpp"
  36 #endif
  37 #ifdef TARGET_OS_ARCH_solaris_x86
  38 # include "os_solaris_x86.inline.hpp"
  39 #endif
  40 
  41 #include "rdtsc_x86.hpp"
  42 #include "runtime/thread.inline.hpp"
  43 #include "vm_version_ext_x86.hpp"
  44 #include "runtime/os.hpp"
  45 
  46 // The following header contains the implementations of rdtsc()
  47 
  48 static jlong _epoch = 0;
  49 static bool rdtsc_elapsed_counter_enabled = false;
  50 static jlong tsc_frequency = 0;
  51 
  52 static jlong set_epoch() {
  53   assert(0 == _epoch, "invariant");
  54   _epoch = os::rdtsc();
  55   return _epoch;
  56 }
  57 
  58 // Base loop to estimate ticks frequency for tsc counter from user mode.
  59 // Volatiles and sleep() are used to prevent compiler from applying optimizations.
  60 static void do_time_measurements(volatile jlong& time_base,
  61                                  volatile jlong& time_fast,
  62                                  volatile jlong& time_base_elapsed,
  63                                  volatile jlong& time_fast_elapsed) {
  64   static const unsigned int FT_SLEEP_MILLISECS = 1;
  65   const unsigned int loopcount = 3;
  66 
  67   volatile jlong start = 0;
  68   volatile jlong fstart = 0;
  69   volatile jlong end = 0;
  70   volatile jlong fend = 0;
  71 
  72   // Figure out the difference between rdtsc and os provided timer.
  73   // base algorithm adopted from JRockit.
  74   for (unsigned int times = 0; times < loopcount; times++) {
  75     start = os::elapsed_counter();
  76     OrderAccess::fence();
  77     fstart = os::rdtsc();
  78 
  79     // use sleep to prevent compiler from optimizing
  80     os::sleep(Thread::current(), FT_SLEEP_MILLISECS, true);
  81 
  82     end = os::elapsed_counter();
  83     OrderAccess::fence();
  84     fend = os::rdtsc();
  85 
  86     time_base += end - start;
  87     time_fast += fend - fstart;
  88 
  89     // basis for calculating the os tick start
  90     // to fast time tick start offset
  91     time_base_elapsed += end;
  92     time_fast_elapsed += (fend - _epoch);
  93   }
  94 
  95   time_base /= loopcount;
  96   time_fast /= loopcount;
  97   time_base_elapsed /= loopcount;
  98   time_fast_elapsed /= loopcount;
  99 }
 100 
 101 static jlong initialize_frequency() {
 102   assert(0 == tsc_frequency, "invariant");
 103   assert(0 == _epoch, "invariant");
 104   const jlong initial_counter = set_epoch();
 105   if (initial_counter == 0) {
 106     return 0;
 107   }
 108   // os time frequency
 109   static double os_freq = (double)os::elapsed_frequency();
 110   assert(os_freq > 0, "os_elapsed frequency corruption!");
 111 
 112   double tsc_freq = .0;
 113   double os_to_tsc_conv_factor = 1.0;
 114 
 115   // if platform supports invariant tsc,
 116   // apply higher resolution and granularity for conversion calculations
 117   if (VM_Version_Ext::supports_tscinv_ext()) {
 118     // for invariant tsc platforms, take the maximum qualified cpu frequency
 119     tsc_freq = (double)VM_Version_Ext::maximum_qualified_cpu_frequency();
 120     os_to_tsc_conv_factor = tsc_freq / os_freq;
 121   } else {
 122     // use measurements to estimate
 123     // a conversion factor and the tsc frequency
 124 
 125     volatile jlong time_base = 0;
 126     volatile jlong time_fast = 0;
 127     volatile jlong time_base_elapsed = 0;
 128     volatile jlong time_fast_elapsed = 0;
 129 
 130     // do measurements to get base data
 131     // on os timer and fast ticks tsc time relation.
 132     do_time_measurements(time_base, time_fast, time_base_elapsed, time_fast_elapsed);
 133 
 134     // if invalid measurements, cannot proceed
 135     if (time_fast == 0 || time_base == 0) {
 136       return 0;
 137     }
 138 
 139     os_to_tsc_conv_factor = (double)time_fast / (double)time_base;
 140     if (os_to_tsc_conv_factor > 1) {
 141       // estimate on tsc counter frequency
 142       tsc_freq = os_to_tsc_conv_factor * os_freq;
 143     }
 144   }
 145 
 146   if ((tsc_freq < 0) || (tsc_freq > 0 && tsc_freq <= os_freq) || (os_to_tsc_conv_factor <= 1)) {
 147     // safer to run with normal os time
 148     tsc_freq = .0;
 149   }
 150 
 151   // frequency of the tsc_counter
 152   return (jlong)tsc_freq;
 153 }
 154 
 155 static bool initialize_elapsed_counter() {
 156   tsc_frequency = initialize_frequency();
 157   return tsc_frequency != 0 && _epoch != 0;
 158 }
 159 
 160 static bool ergonomics() {
 161   const bool invtsc_support = Rdtsc::is_supported();
 162   if (FLAG_IS_DEFAULT(UseFastUnorderedTimeStamps) && invtsc_support) {
 163     FLAG_SET_ERGO(bool, UseFastUnorderedTimeStamps, true);
 164   }
 165 
 166   bool ft_enabled = UseFastUnorderedTimeStamps && invtsc_support;
 167 
 168   if (!ft_enabled) {
 169     if (UseFastUnorderedTimeStamps && VM_Version::supports_tsc()) {
 170       warning("\nThe hardware does not support invariant tsc (INVTSC) register and/or cannot guarantee tsc synchronization between sockets at startup.\n"\
 171         "Values returned via rdtsc() are not guaranteed to be accurate, esp. when comparing values from cross sockets reads. Enabling UseFastUnorderedTimeStamps on non-invariant tsc hardware should be considered experimental.\n");
 172       ft_enabled = true;
 173     }
 174   }
 175 
 176   if (!ft_enabled) {
 177     // Warn if unable to support command-line flag
 178     if (UseFastUnorderedTimeStamps && !VM_Version::supports_tsc()) {
 179       warning("Ignoring UseFastUnorderedTimeStamps, hardware does not support normal tsc");
 180     }
 181   }
 182 
 183   return ft_enabled;
 184 }
 185 
 186 bool Rdtsc::is_supported() {
 187   return VM_Version_Ext::supports_tscinv_ext();
 188 }
 189 
 190 bool Rdtsc::is_elapsed_counter_enabled() {
 191   return rdtsc_elapsed_counter_enabled;
 192 }
 193 
 194 jlong Rdtsc::frequency() {
 195   return tsc_frequency;
 196 }
 197 
 198 jlong Rdtsc::elapsed_counter() {
 199   return os::rdtsc() - _epoch;
 200 }
 201 
 202 jlong Rdtsc::epoch() {
 203   return _epoch;
 204 }
 205 
 206 jlong Rdtsc::raw() {
 207   return os::rdtsc();
 208 }
 209 
 210 bool Rdtsc::initialize() {
 211   static bool initialized = false;
 212   if (!initialized) {
 213     assert(!rdtsc_elapsed_counter_enabled, "invariant");
 214     VM_Version_Ext::initialize();
 215     assert(0 == tsc_frequency, "invariant");
 216     assert(0 == _epoch, "invariant");
 217     bool result = initialize_elapsed_counter(); // init hw
 218     if (result) {
 219       result = ergonomics(); // check logical state
 220     }
 221     rdtsc_elapsed_counter_enabled = result;
 222     initialized = true;
 223   }
 224   return rdtsc_elapsed_counter_enabled;
 225 }