annotate src/hotspot/cpu/x86/rdtsc_x86.cpp @ 54526:ee29b516a36a

revert changes
author jlaskey
date Wed, 23 Jan 2019 16:09:20 -0400
parents
children 81becad91321
rev   line source
egahlin@50662 1 /*
egahlin@50662 2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
egahlin@50662 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
egahlin@50662 4 *
egahlin@50662 5 * This code is free software; you can redistribute it and/or modify it
egahlin@50662 6 * under the terms of the GNU General Public License version 2 only, as
egahlin@50662 7 * published by the Free Software Foundation.
egahlin@50662 8 *
egahlin@50662 9 * This code is distributed in the hope that it will be useful, but WITHOUT
egahlin@50662 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
egahlin@50662 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
egahlin@50662 12 * version 2 for more details (a copy is included in the LICENSE file that
egahlin@50662 13 * accompanied this code).
egahlin@50662 14 *
egahlin@50662 15 * You should have received a copy of the GNU General Public License version
egahlin@50662 16 * 2 along with this work; if not, write to the Free Software Foundation,
egahlin@50662 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
egahlin@50662 18 *
egahlin@50662 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
egahlin@50662 20 * or visit www.oracle.com if you need additional information or have any
egahlin@50662 21 * questions.
egahlin@50662 22 *
egahlin@50662 23 */
egahlin@50662 24
egahlin@50662 25 #include "precompiled.hpp"
egahlin@50662 26 #include "rdtsc_x86.hpp"
egahlin@50662 27 #include "runtime/thread.inline.hpp"
egahlin@50662 28 #include "vm_version_ext_x86.hpp"
egahlin@50662 29
egahlin@50662 30 // The following header contains the implementations of rdtsc()
egahlin@50662 31 #include OS_CPU_HEADER_INLINE(os)
egahlin@50662 32
egahlin@50662 33 static jlong _epoch = 0;
egahlin@50662 34 static bool rdtsc_elapsed_counter_enabled = false;
egahlin@50662 35 static jlong tsc_frequency = 0;
egahlin@50662 36
egahlin@50662 37 static jlong set_epoch() {
egahlin@50662 38 assert(0 == _epoch, "invariant");
egahlin@50662 39 _epoch = os::rdtsc();
egahlin@50662 40 return _epoch;
egahlin@50662 41 }
egahlin@50662 42
egahlin@50662 43 // Base loop to estimate ticks frequency for tsc counter from user mode.
egahlin@50662 44 // Volatiles and sleep() are used to prevent compiler from applying optimizations.
egahlin@50662 45 static void do_time_measurements(volatile jlong& time_base,
egahlin@50662 46 volatile jlong& time_fast,
egahlin@50662 47 volatile jlong& time_base_elapsed,
egahlin@50662 48 volatile jlong& time_fast_elapsed) {
egahlin@50662 49 static const unsigned int FT_SLEEP_MILLISECS = 1;
egahlin@50662 50 const unsigned int loopcount = 3;
egahlin@50662 51
egahlin@50662 52 volatile jlong start = 0;
egahlin@50662 53 volatile jlong fstart = 0;
egahlin@50662 54 volatile jlong end = 0;
egahlin@50662 55 volatile jlong fend = 0;
egahlin@50662 56
egahlin@50662 57 // Figure out the difference between rdtsc and os provided timer.
egahlin@50662 58 // base algorithm adopted from JRockit.
egahlin@50662 59 for (unsigned int times = 0; times < loopcount; times++) {
egahlin@50662 60 start = os::elapsed_counter();
egahlin@50662 61 OrderAccess::fence();
egahlin@50662 62 fstart = os::rdtsc();
egahlin@50662 63
egahlin@50662 64 // use sleep to prevent compiler from optimizing
egahlin@50662 65 os::sleep(Thread::current(), FT_SLEEP_MILLISECS, true);
egahlin@50662 66
egahlin@50662 67 end = os::elapsed_counter();
egahlin@50662 68 OrderAccess::fence();
egahlin@50662 69 fend = os::rdtsc();
egahlin@50662 70
egahlin@50662 71 time_base += end - start;
egahlin@50662 72 time_fast += fend - fstart;
egahlin@50662 73
egahlin@50662 74 // basis for calculating the os tick start
egahlin@50662 75 // to fast time tick start offset
egahlin@50662 76 time_base_elapsed += end;
egahlin@50662 77 time_fast_elapsed += (fend - _epoch);
egahlin@50662 78 }
egahlin@50662 79
egahlin@50662 80 time_base /= loopcount;
egahlin@50662 81 time_fast /= loopcount;
egahlin@50662 82 time_base_elapsed /= loopcount;
egahlin@50662 83 time_fast_elapsed /= loopcount;
egahlin@50662 84 }
egahlin@50662 85
egahlin@50662 86 static jlong initialize_frequency() {
egahlin@50662 87 assert(0 == tsc_frequency, "invariant");
egahlin@50662 88 assert(0 == _epoch, "invariant");
egahlin@50662 89 const jlong initial_counter = set_epoch();
egahlin@50662 90 if (initial_counter == 0) {
egahlin@50662 91 return 0;
egahlin@50662 92 }
egahlin@50662 93 // os time frequency
egahlin@50662 94 static double os_freq = (double)os::elapsed_frequency();
egahlin@50662 95 assert(os_freq > 0, "os_elapsed frequency corruption!");
egahlin@50662 96
egahlin@50662 97 double tsc_freq = .0;
egahlin@50662 98 double os_to_tsc_conv_factor = 1.0;
egahlin@50662 99
egahlin@50662 100 // if platform supports invariant tsc,
egahlin@50662 101 // apply higher resolution and granularity for conversion calculations
egahlin@50662 102 if (VM_Version_Ext::supports_tscinv_ext()) {
egahlin@50662 103 // for invariant tsc platforms, take the maximum qualified cpu frequency
egahlin@50662 104 tsc_freq = (double)VM_Version_Ext::maximum_qualified_cpu_frequency();
egahlin@50662 105 os_to_tsc_conv_factor = tsc_freq / os_freq;
egahlin@50662 106 } else {
egahlin@50662 107 // use measurements to estimate
egahlin@50662 108 // a conversion factor and the tsc frequency
egahlin@50662 109
egahlin@50662 110 volatile jlong time_base = 0;
egahlin@50662 111 volatile jlong time_fast = 0;
egahlin@50662 112 volatile jlong time_base_elapsed = 0;
egahlin@50662 113 volatile jlong time_fast_elapsed = 0;
egahlin@50662 114
egahlin@50662 115 // do measurements to get base data
egahlin@50662 116 // on os timer and fast ticks tsc time relation.
egahlin@50662 117 do_time_measurements(time_base, time_fast, time_base_elapsed, time_fast_elapsed);
egahlin@50662 118
egahlin@50662 119 // if invalid measurements, cannot proceed
egahlin@50662 120 if (time_fast == 0 || time_base == 0) {
egahlin@50662 121 return 0;
egahlin@50662 122 }
egahlin@50662 123
egahlin@50662 124 os_to_tsc_conv_factor = (double)time_fast / (double)time_base;
egahlin@50662 125 if (os_to_tsc_conv_factor > 1) {
egahlin@50662 126 // estimate on tsc counter frequency
egahlin@50662 127 tsc_freq = os_to_tsc_conv_factor * os_freq;
egahlin@50662 128 }
egahlin@50662 129 }
egahlin@50662 130
egahlin@50662 131 if ((tsc_freq < 0) || (tsc_freq > 0 && tsc_freq <= os_freq) || (os_to_tsc_conv_factor <= 1)) {
egahlin@50662 132 // safer to run with normal os time
egahlin@50662 133 tsc_freq = .0;
egahlin@50662 134 }
egahlin@50662 135
egahlin@50662 136 // frequency of the tsc_counter
egahlin@50662 137 return (jlong)tsc_freq;
egahlin@50662 138 }
egahlin@50662 139
egahlin@50662 140 static bool initialize_elapsed_counter() {
egahlin@50662 141 tsc_frequency = initialize_frequency();
egahlin@50662 142 return tsc_frequency != 0 && _epoch != 0;
egahlin@50662 143 }
egahlin@50662 144
egahlin@50662 145 static bool ergonomics() {
egahlin@50662 146 const bool invtsc_support = Rdtsc::is_supported();
egahlin@50662 147 if (FLAG_IS_DEFAULT(UseFastUnorderedTimeStamps) && invtsc_support) {
egahlin@50662 148 FLAG_SET_ERGO(bool, UseFastUnorderedTimeStamps, true);
egahlin@50662 149 }
egahlin@50662 150
egahlin@50662 151 bool ft_enabled = UseFastUnorderedTimeStamps && invtsc_support;
egahlin@50662 152
egahlin@50662 153 if (!ft_enabled) {
egahlin@50662 154 if (UseFastUnorderedTimeStamps && VM_Version::supports_tsc()) {
egahlin@50662 155 warning("\nThe hardware does not support invariant tsc (INVTSC) register and/or cannot guarantee tsc synchronization between sockets at startup.\n"\
egahlin@50662 156 "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");
egahlin@50662 157 ft_enabled = true;
egahlin@50662 158 }
egahlin@50662 159 }
egahlin@50662 160
egahlin@50662 161 if (!ft_enabled) {
egahlin@50662 162 // Warn if unable to support command-line flag
egahlin@50662 163 if (UseFastUnorderedTimeStamps && !VM_Version::supports_tsc()) {
egahlin@50662 164 warning("Ignoring UseFastUnorderedTimeStamps, hardware does not support normal tsc");
egahlin@50662 165 }
egahlin@50662 166 }
egahlin@50662 167
egahlin@50662 168 return ft_enabled;
egahlin@50662 169 }
egahlin@50662 170
egahlin@50662 171 bool Rdtsc::is_supported() {
egahlin@50662 172 return VM_Version_Ext::supports_tscinv_ext();
egahlin@50662 173 }
egahlin@50662 174
egahlin@50662 175 bool Rdtsc::is_elapsed_counter_enabled() {
egahlin@50662 176 return rdtsc_elapsed_counter_enabled;
egahlin@50662 177 }
egahlin@50662 178
egahlin@50662 179 jlong Rdtsc::frequency() {
egahlin@50662 180 return tsc_frequency;
egahlin@50662 181 }
egahlin@50662 182
egahlin@50662 183 jlong Rdtsc::elapsed_counter() {
egahlin@50662 184 return os::rdtsc() - _epoch;
egahlin@50662 185 }
egahlin@50662 186
egahlin@50662 187 jlong Rdtsc::epoch() {
egahlin@50662 188 return _epoch;
egahlin@50662 189 }
egahlin@50662 190
egahlin@50662 191 jlong Rdtsc::raw() {
egahlin@50662 192 return os::rdtsc();
egahlin@50662 193 }
egahlin@50662 194
egahlin@50662 195 bool Rdtsc::initialize() {
egahlin@50662 196 static bool initialized = false;
egahlin@50662 197 if (!initialized) {
egahlin@50662 198 assert(!rdtsc_elapsed_counter_enabled, "invariant");
egahlin@50662 199 VM_Version_Ext::initialize();
egahlin@50662 200 assert(0 == tsc_frequency, "invariant");
egahlin@50662 201 assert(0 == _epoch, "invariant");
egahlin@50662 202 bool result = initialize_elapsed_counter(); // init hw
egahlin@50662 203 if (result) {
egahlin@50662 204 result = ergonomics(); // check logical state
egahlin@50662 205 }
egahlin@50662 206 rdtsc_elapsed_counter_enabled = result;
egahlin@50662 207 initialized = true;
egahlin@50662 208 }
egahlin@50662 209 return rdtsc_elapsed_counter_enabled;
egahlin@50662 210 }