Skip to content
Permalink
Browse files

8235741: Inappropriate uses of os::javaTimeMillis()

Reviewed-by: rehn, kbarrett, egahlin, shade
  • Loading branch information
David Holmes
David Holmes committed Jan 17, 2020
1 parent d517220 commit 7c27f9f5ddc3cd7343f0905825baf7e6ee598891
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -371,19 +371,21 @@ static int get_boot_time(uint64_t* time) {

static int perf_context_switch_rate(double* rate) {
static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
static uint64_t lastTime;
static uint64_t bootTime;
static uint64_t lastTimeNanos;
static uint64_t lastSwitches;
static double lastRate;

uint64_t lt = 0;
uint64_t bt = 0;
int res = 0;

if (lastTime == 0) {
// First time through bootTime will be zero.
if (bootTime == 0) {
uint64_t tmp;
if (get_boot_time(&tmp) < 0) {
return OS_ERR;
}
lt = tmp * 1000;
bt = tmp * 1000;
}

res = OS_OK;
@@ -394,20 +396,29 @@ static int perf_context_switch_rate(double* rate) {
uint64_t sw;
s8 t, d;

if (lastTime == 0) {
lastTime = lt;
if (bootTime == 0) {
// First interval is measured from boot time which is
// seconds since the epoch. Thereafter we measure the
// elapsed time using javaTimeNanos as it is monotonic-
// non-decreasing.
lastTimeNanos = os::javaTimeNanos();
t = os::javaTimeMillis();
d = t - bt;
// keep bootTime zero for now to use as a first-time-through flag
} else {
t = os::javaTimeNanos();
d = nanos_to_millis(t - lastTimeNanos);
}

t = os::javaTimeMillis();
d = t - lastTime;

if (d == 0) {
*rate = lastRate;
} else if (!get_noof_context_switches(&sw)) {
} else if (get_noof_context_switches(&sw) == 0) {
*rate = ( (double)(sw - lastSwitches) / d ) * 1000;
lastRate = *rate;
lastSwitches = sw;
lastTime = t;
if (bootTime != 0) {
lastTimeNanos = t;
}
} else {
*rate = 0;
res = OS_ERR;
@@ -416,6 +427,10 @@ static int perf_context_switch_rate(double* rate) {
*rate = 0;
lastRate = 0;
}

if (bootTime == 0) {
bootTime = bt;
}
}
pthread_mutex_unlock(&contextSwitchLock);

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,17 +76,17 @@ bool OSXSemaphore::timedwait(int64_t millis) {
// kernel semaphores take a relative timeout
mach_timespec_t waitspec;
int secs = millis / MILLIUNITS;
int nsecs = (millis % MILLIUNITS) * NANOSECS_PER_MILLISEC;
int nsecs = millis_to_nanos(millis % MILLIUNITS);
waitspec.tv_sec = secs;
waitspec.tv_nsec = nsecs;

int64_t starttime = os::javaTimeMillis() * NANOSECS_PER_MILLISEC;
int64_t starttime = os::javaTimeNanos();

kr = semaphore_timedwait(_semaphore, waitspec);
while (kr == KERN_ABORTED) {
// reduce the timout and try again
int64_t totalwait = millis * NANOSECS_PER_MILLISEC;
int64_t current = os::javaTimeMillis() * NANOSECS_PER_MILLISEC;
int64_t totalwait = millis_to_nanos(millis);
int64_t current = os::javaTimeNanos();
int64_t passedtime = current - starttime;

if (passedtime >= totalwait) {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -431,19 +431,21 @@ static int get_boot_time(uint64_t* time) {

static int perf_context_switch_rate(double* rate) {
static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
static uint64_t lastTime;
static uint64_t bootTime;
static uint64_t lastTimeNanos;
static uint64_t lastSwitches;
static double lastRate;

uint64_t lt = 0;
uint64_t bt = 0;
int res = 0;

if (lastTime == 0) {
// First time through bootTime will be zero.
if (bootTime == 0) {
uint64_t tmp;
if (get_boot_time(&tmp) < 0) {
return OS_ERR;
}
lt = tmp * 1000;
bt = tmp * 1000;
}

res = OS_OK;
@@ -454,20 +456,29 @@ static int perf_context_switch_rate(double* rate) {
uint64_t sw;
s8 t, d;

if (lastTime == 0) {
lastTime = lt;
if (bootTime == 0) {
// First interval is measured from boot time which is
// seconds since the epoch. Thereafter we measure the
// elapsed time using javaTimeNanos as it is monotonic-
// non-decreasing.
lastTimeNanos = os::javaTimeNanos();
t = os::javaTimeMillis();
d = t - bt;
// keep bootTime zero for now to use as a first-time-through flag
} else {
t = os::javaTimeNanos();
d = nanos_to_millis(t - lastTimeNanos);
}

t = os::javaTimeMillis();
d = t - lastTime;

if (d == 0) {
*rate = lastRate;
} else if (!get_noof_context_switches(&sw)) {
} else if (get_noof_context_switches(&sw) == 0) {
*rate = ( (double)(sw - lastSwitches) / d ) * 1000;
lastRate = *rate;
lastSwitches = sw;
lastTime = t;
if (bootTime != 0) {
lastTimeNanos = t;
}
} else {
*rate = 0;
res = OS_ERR;
@@ -476,6 +487,10 @@ static int perf_context_switch_rate(double* rate) {
*rate = 0;
lastRate = 0;
}

if (bootTime == 0) {
bootTime = bt;
}
}
pthread_mutex_unlock(&contextSwitchLock);

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -681,7 +681,7 @@ void os::naked_short_nanosleep(jlong ns) {

void os::naked_short_sleep(jlong ms) {
assert(ms < MILLIUNITS, "Un-interruptable sleep, short time use only");
os::naked_short_nanosleep(ms * (NANOUNITS / MILLIUNITS));
os::naked_short_nanosleep(millis_to_nanos(ms));
return;
}

@@ -1833,18 +1833,18 @@ static void unpack_abs_time(timespec* abstime, jlong deadline, jlong now_sec) {
abstime->tv_nsec = 0;
} else {
abstime->tv_sec = seconds;
abstime->tv_nsec = millis * (NANOUNITS / MILLIUNITS);
abstime->tv_nsec = millis_to_nanos(millis);
}
}

static jlong millis_to_nanos(jlong millis) {
static jlong millis_to_nanos_bounded(jlong millis) {
// We have to watch for overflow when converting millis to nanos,
// but if millis is that large then we will end up limiting to
// MAX_SECS anyway, so just do that here.
if (millis / MILLIUNITS > MAX_SECS) {
millis = jlong(MAX_SECS) * MILLIUNITS;
}
return millis * (NANOUNITS / MILLIUNITS);
return millis_to_nanos(millis);
}

static void to_abstime(timespec* abstime, jlong timeout,
@@ -1897,7 +1897,7 @@ static void to_abstime(timespec* abstime, jlong timeout,
// Create an absolute time 'millis' milliseconds in the future, using the
// real-time (time-of-day) clock. Used by PosixSemaphore.
void os::Posix::to_RTC_abstime(timespec* abstime, int64_t millis) {
to_abstime(abstime, millis_to_nanos(millis),
to_abstime(abstime, millis_to_nanos_bounded(millis),
false /* not absolute */,
true /* use real-time clock */);
}
@@ -1992,7 +1992,7 @@ int os::PlatformEvent::park(jlong millis) {

if (v == 0) { // Do this the hard way by blocking ...
struct timespec abst;
to_abstime(&abst, millis_to_nanos(millis), false, false);
to_abstime(&abst, millis_to_nanos_bounded(millis), false, false);

int ret = OS_TIMEOUT;
int status = pthread_mutex_lock(_mutex);
@@ -2318,7 +2318,7 @@ int os::PlatformMonitor::wait(jlong millis) {
if (millis / MILLIUNITS > MAX_SECS) {
millis = jlong(MAX_SECS) * MILLIUNITS;
}
to_abstime(&abst, millis * (NANOUNITS / MILLIUNITS), false, false);
to_abstime(&abst, millis_to_nanos(millis), false, false);

int ret = OS_TIMEOUT;
int status = pthread_cond_timedwait(cond(), mutex(), &abst);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -97,7 +97,7 @@ static const int min_update_interval_millis = 500;
*/
typedef struct {
HQUERY query;
s8 lastUpdate; // Last time query was updated (current millis).
s8 lastUpdate; // Last time query was updated.
} UpdateQueryS, *UpdateQueryP;


@@ -287,8 +287,8 @@ static OSReturn add_process_counter(MultiCounterQueryP query, int slot_index, co

static int collect_query_data(UpdateQueryP update_query) {
assert(update_query != NULL, "invariant");
const s8 now = os::javaTimeMillis();
if (now - update_query->lastUpdate > min_update_interval_millis) {
const s8 now = os::javaTimeNanos();
if (nanos_to_millis(now - update_query->lastUpdate) > min_update_interval_millis) {
if (PdhDll::PdhCollectQueryData(update_query->query) != ERROR_SUCCESS) {
return OS_ERR;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -289,14 +289,14 @@ class CounterDecay : public AllStatic {
public:
static void decay();
static bool is_decay_needed() {
return (os::javaTimeMillis() - _last_timestamp) > CounterDecayMinIntervalLength;
return nanos_to_millis(os::javaTimeNanos() - _last_timestamp) > CounterDecayMinIntervalLength;
}
};

jlong CounterDecay::_last_timestamp = 0;

void CounterDecay::decay() {
_last_timestamp = os::javaTimeMillis();
_last_timestamp = os::javaTimeNanos();

// This operation is going to be performed only at the end of a safepoint
// and hence GC's will not be going on, all Java mutators are suspended
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -304,7 +304,7 @@ void TieredThresholdPolicy::initialize() {
#endif

set_increase_threshold_at_ratio();
set_start_time(os::javaTimeMillis());
set_start_time(nanos_to_millis(os::javaTimeNanos()));
}


@@ -404,7 +404,7 @@ CompileTask* TieredThresholdPolicy::select_task(CompileQueue* compile_queue) {
CompileTask *max_blocking_task = NULL;
CompileTask *max_task = NULL;
Method* max_method = NULL;
jlong t = os::javaTimeMillis();
jlong t = nanos_to_millis(os::javaTimeNanos());
// Iterate through the queue and find a method with a maximum rate.
for (CompileTask* task = compile_queue->first(); task != NULL;) {
CompileTask* next_task = task->next();
@@ -596,7 +596,7 @@ void TieredThresholdPolicy::compile(const methodHandle& mh, int bci, CompLevel l
print_event(COMPILE, mh(), mh(), bci, level);
}
int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count();
update_rate(os::javaTimeMillis(), mh());
update_rate(nanos_to_millis(os::javaTimeNanos()), mh());
CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, thread);
}
}
@@ -616,7 +616,7 @@ void TieredThresholdPolicy::update_rate(jlong t, Method* m) {

// We don't update the rate if we've just came out of a safepoint.
// delta_s is the time since last safepoint in milliseconds.
jlong delta_s = t - SafepointTracing::end_of_last_safepoint_epoch_ms();
jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms();
jlong delta_t = t - (m->prev_time() != 0 ? m->prev_time() : start_time()); // milliseconds since the last measurement
// How many events were there since the last time?
int event_count = m->invocation_count() + m->backedge_count();
@@ -641,7 +641,7 @@ void TieredThresholdPolicy::update_rate(jlong t, Method* m) {
// Check if this method has been stale for a given number of milliseconds.
// See select_task().
bool TieredThresholdPolicy::is_stale(jlong t, jlong timeout, Method* m) {
jlong delta_s = t - SafepointTracing::end_of_last_safepoint_epoch_ms();
jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms();
jlong delta_t = t - m->prev_time();
if (delta_t > timeout && delta_s > timeout) {
int event_count = m->invocation_count() + m->backedge_count();
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Red Hat, Inc. All rights reserved.
* Copyright (c) 2016, 2020, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@ ShenandoahHeapRegionCounters::~ShenandoahHeapRegionCounters() {

void ShenandoahHeapRegionCounters::update() {
if (ShenandoahRegionSampling) {
jlong current = os::javaTimeMillis();
jlong current = nanos_to_millis(os::javaTimeNanos());
jlong last = _last_sample_millis;
if (current - last > ShenandoahRegionSamplingRate &&
Atomic::cmpxchg(&_last_sample_millis, last, current) == last) {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,8 @@ static const u2 JFR_VERSION_MINOR = 1;
// strictly monotone
static jlong nanos_now() {
static jlong last = 0;
// We use javaTimeMillis so this can be correlated with
// external timestamps.
const jlong now = os::javaTimeMillis() * JfrTimeConverter::NANOS_PER_MILLISEC;
if (now > last) {
last = now;

0 comments on commit 7c27f9f

Please sign in to comment.