Skip to content

Commit 99c17fb

Browse files
author
David Holmes
committed
6313903: Thread.sleep(3) might wake up immediately on windows
Reviewed-by: rehn, dcubed, rriggs
1 parent 4dc79c2 commit 99c17fb

File tree

3 files changed

+134
-155
lines changed

3 files changed

+134
-155
lines changed

src/hotspot/os/posix/os_posix.cpp

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -624,78 +624,6 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name,
624624
return agent_entry_name;
625625
}
626626

627-
int os::sleep(Thread* thread, jlong millis, bool interruptible) {
628-
assert(thread == Thread::current(), "thread consistency check");
629-
630-
ParkEvent * const slp = thread->_SleepEvent ;
631-
slp->reset() ;
632-
OrderAccess::fence() ;
633-
634-
if (interruptible) {
635-
jlong prevtime = javaTimeNanos();
636-
637-
for (;;) {
638-
if (os::is_interrupted(thread, true)) {
639-
return OS_INTRPT;
640-
}
641-
642-
jlong newtime = javaTimeNanos();
643-
644-
if (newtime - prevtime < 0) {
645-
// time moving backwards, should only happen if no monotonic clock
646-
// not a guarantee() because JVM should not abort on kernel/glibc bugs
647-
assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected in os::sleep(interruptible)");
648-
} else {
649-
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
650-
}
651-
652-
if (millis <= 0) {
653-
return OS_OK;
654-
}
655-
656-
prevtime = newtime;
657-
658-
{
659-
assert(thread->is_Java_thread(), "sanity check");
660-
JavaThread *jt = (JavaThread *) thread;
661-
ThreadBlockInVM tbivm(jt);
662-
OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
663-
664-
jt->set_suspend_equivalent();
665-
// cleared by handle_special_suspend_equivalent_condition() or
666-
// java_suspend_self() via check_and_wait_while_suspended()
667-
668-
slp->park(millis);
669-
670-
// were we externally suspended while we were waiting?
671-
jt->check_and_wait_while_suspended();
672-
}
673-
}
674-
} else {
675-
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
676-
jlong prevtime = javaTimeNanos();
677-
678-
for (;;) {
679-
// It'd be nice to avoid the back-to-back javaTimeNanos() calls on
680-
// the 1st iteration ...
681-
jlong newtime = javaTimeNanos();
682-
683-
if (newtime - prevtime < 0) {
684-
// time moving backwards, should only happen if no monotonic clock
685-
// not a guarantee() because JVM should not abort on kernel/glibc bugs
686-
assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected on os::sleep(!interruptible)");
687-
} else {
688-
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
689-
}
690-
691-
if (millis <= 0) break ;
692-
693-
prevtime = newtime;
694-
slp->park(millis);
695-
}
696-
return OS_OK ;
697-
}
698-
}
699627

700628
void os::naked_short_nanosleep(jlong ns) {
701629
struct timespec req;

src/hotspot/os/windows/os_windows.cpp

Lines changed: 51 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,10 @@ static OSThread* create_os_thread(Thread* thread, HANDLE thread_handle,
497497
OSThread* osthread = new OSThread(NULL, NULL);
498498
if (osthread == NULL) return NULL;
499499

500-
// Initialize support for Java interrupts
500+
// Initialize the JDK library's interrupt event.
501+
// This should really be done when OSThread is constructed,
502+
// but there is no way for a constructor to report failure to
503+
// allocate the event.
501504
HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL);
502505
if (interrupt_event == NULL) {
503506
delete osthread;
@@ -599,7 +602,10 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
599602
return false;
600603
}
601604

602-
// Initialize support for Java interrupts
605+
// Initialize the JDK library's interrupt event.
606+
// This should really be done when OSThread is constructed,
607+
// but there is no way for a constructor to report failure to
608+
// allocate the event.
603609
HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL);
604610
if (interrupt_event == NULL) {
605611
delete osthread;
@@ -3480,87 +3486,7 @@ void os::pd_start_thread(Thread* thread) {
34803486
assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back
34813487
}
34823488

3483-
class HighResolutionInterval : public CHeapObj<mtThread> {
3484-
// The default timer resolution seems to be 10 milliseconds.
3485-
// (Where is this written down?)
3486-
// If someone wants to sleep for only a fraction of the default,
3487-
// then we set the timer resolution down to 1 millisecond for
3488-
// the duration of their interval.
3489-
// We carefully set the resolution back, since otherwise we
3490-
// seem to incur an overhead (3%?) that we don't need.
3491-
// CONSIDER: if ms is small, say 3, then we should run with a high resolution time.
3492-
// Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod().
3493-
// Alternatively, we could compute the relative error (503/500 = .6%) and only use
3494-
// timeBeginPeriod() if the relative error exceeded some threshold.
3495-
// timeBeginPeriod() has been linked to problems with clock drift on win32 systems and
3496-
// to decreased efficiency related to increased timer "tick" rates. We want to minimize
3497-
// (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high
3498-
// resolution timers running.
3499-
private:
3500-
jlong resolution;
3501-
public:
3502-
HighResolutionInterval(jlong ms) {
3503-
resolution = ms % 10L;
3504-
if (resolution != 0) {
3505-
MMRESULT result = timeBeginPeriod(1L);
3506-
}
3507-
}
3508-
~HighResolutionInterval() {
3509-
if (resolution != 0) {
3510-
MMRESULT result = timeEndPeriod(1L);
3511-
}
3512-
resolution = 0L;
3513-
}
3514-
};
3515-
3516-
int os::sleep(Thread* thread, jlong ms, bool interruptable) {
3517-
jlong limit = (jlong) MAXDWORD;
3518-
3519-
while (ms > limit) {
3520-
int res;
3521-
if ((res = sleep(thread, limit, interruptable)) != OS_TIMEOUT) {
3522-
return res;
3523-
}
3524-
ms -= limit;
3525-
}
3526-
3527-
assert(thread == Thread::current(), "thread consistency check");
3528-
OSThread* osthread = thread->osthread();
3529-
OSThreadWaitState osts(osthread, false /* not Object.wait() */);
3530-
int result;
3531-
if (interruptable) {
3532-
assert(thread->is_Java_thread(), "must be java thread");
3533-
JavaThread *jt = (JavaThread *) thread;
3534-
ThreadBlockInVM tbivm(jt);
3535-
3536-
jt->set_suspend_equivalent();
3537-
// cleared by handle_special_suspend_equivalent_condition() or
3538-
// java_suspend_self() via check_and_wait_while_suspended()
3539-
3540-
HANDLE events[1];
3541-
events[0] = osthread->interrupt_event();
3542-
HighResolutionInterval *phri=NULL;
3543-
if (!ForceTimeHighResolution) {
3544-
phri = new HighResolutionInterval(ms);
3545-
}
3546-
if (WaitForMultipleObjects(1, events, FALSE, (DWORD)ms) == WAIT_TIMEOUT) {
3547-
result = OS_TIMEOUT;
3548-
} else {
3549-
ResetEvent(osthread->interrupt_event());
3550-
osthread->set_interrupted(false);
3551-
result = OS_INTRPT;
3552-
}
3553-
delete phri; //if it is NULL, harmless
35543489

3555-
// were we externally suspended while we were waiting?
3556-
jt->check_and_wait_while_suspended();
3557-
} else {
3558-
assert(!thread->is_Java_thread(), "must not be java thread");
3559-
Sleep((long) ms);
3560-
result = OS_TIMEOUT;
3561-
}
3562-
return result;
3563-
}
35643490

35653491
// Short sleep, direct OS call.
35663492
//
@@ -3687,6 +3613,9 @@ void os::interrupt(Thread* thread) {
36873613

36883614
ParkEvent * ev = thread->_ParkEvent;
36893615
if (ev != NULL) ev->unpark();
3616+
3617+
ev = thread->_SleepEvent;
3618+
if (ev != NULL) ev->unpark();
36903619
}
36913620

36923621

@@ -5170,6 +5099,40 @@ bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
51705099
return success;
51715100
}
51725101

5102+
5103+
class HighResolutionInterval : public CHeapObj<mtThread> {
5104+
// The default timer resolution seems to be 10 milliseconds.
5105+
// (Where is this written down?)
5106+
// If someone wants to sleep for only a fraction of the default,
5107+
// then we set the timer resolution down to 1 millisecond for
5108+
// the duration of their interval.
5109+
// We carefully set the resolution back, since otherwise we
5110+
// seem to incur an overhead (3%?) that we don't need.
5111+
// CONSIDER: if ms is small, say 3, then we should run with a high resolution time.
5112+
// Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod().
5113+
// Alternatively, we could compute the relative error (503/500 = .6%) and only use
5114+
// timeBeginPeriod() if the relative error exceeded some threshold.
5115+
// timeBeginPeriod() has been linked to problems with clock drift on win32 systems and
5116+
// to decreased efficiency related to increased timer "tick" rates. We want to minimize
5117+
// (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high
5118+
// resolution timers running.
5119+
private:
5120+
jlong resolution;
5121+
public:
5122+
HighResolutionInterval(jlong ms) {
5123+
resolution = ms % 10L;
5124+
if (resolution != 0) {
5125+
MMRESULT result = timeBeginPeriod(1L);
5126+
}
5127+
}
5128+
~HighResolutionInterval() {
5129+
if (resolution != 0) {
5130+
MMRESULT result = timeEndPeriod(1L);
5131+
}
5132+
resolution = 0L;
5133+
}
5134+
};
5135+
51735136
// An Event wraps a win32 "CreateEvent" kernel handle.
51745137
//
51755138
// We have a number of choices regarding "CreateEvent" win32 handle leakage:
@@ -5205,7 +5168,7 @@ bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
52055168
// 1. Reconcile Doug's JSR166 j.u.c park-unpark with the objectmonitor implementation.
52065169
// 2. Consider wrapping the WaitForSingleObject(Ex) calls in SEH try/finally blocks
52075170
// to recover from (or at least detect) the dreaded Windows 841176 bug.
5208-
// 3. Collapse the interrupt_event, the JSR166 parker event, and the objectmonitor ParkEvent
5171+
// 3. Collapse the JSR166 parker event, and the objectmonitor ParkEvent
52095172
// into a single win32 CreateEvent() handle.
52105173
//
52115174
// Assumption:
@@ -5278,11 +5241,16 @@ int os::PlatformEvent::park(jlong Millis) {
52785241
if (Millis > MAXTIMEOUT) {
52795242
prd = MAXTIMEOUT;
52805243
}
5244+
HighResolutionInterval *phri = NULL;
5245+
if (!ForceTimeHighResolution) {
5246+
phri = new HighResolutionInterval(prd);
5247+
}
52815248
rv = ::WaitForSingleObject(_ParkHandle, prd);
52825249
assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed");
52835250
if (rv == WAIT_TIMEOUT) {
52845251
Millis -= prd;
52855252
}
5253+
delete phri; // if it is NULL, harmless
52865254
}
52875255
v = _Event;
52885256
_Event = 0;

src/hotspot/share/runtime/os.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,3 +1836,86 @@ os::SuspendResume::State os::SuspendResume::switch_state(os::SuspendResume::Stat
18361836
return result;
18371837
}
18381838
#endif
1839+
1840+
int os::sleep(Thread* thread, jlong millis, bool interruptible) {
1841+
assert(thread == Thread::current(), "thread consistency check");
1842+
1843+
ParkEvent * const slp = thread->_SleepEvent;
1844+
// Because there can be races with thread interruption sending an unpark()
1845+
// to the event, we explicitly reset it here to avoid an immediate return.
1846+
// The actual interrupt state will be checked before we park().
1847+
slp->reset();
1848+
// Thread interruption establishes a happens-before ordering in the
1849+
// Java Memory Model, so we need to ensure we synchronize with the
1850+
// interrupt state.
1851+
OrderAccess::fence();
1852+
1853+
if (interruptible) {
1854+
jlong prevtime = javaTimeNanos();
1855+
1856+
assert(thread->is_Java_thread(), "sanity check");
1857+
JavaThread *jt = (JavaThread *) thread;
1858+
1859+
for (;;) {
1860+
// interruption has precedence over timing out
1861+
if (os::is_interrupted(thread, true)) {
1862+
return OS_INTRPT;
1863+
}
1864+
1865+
jlong newtime = javaTimeNanos();
1866+
1867+
if (newtime - prevtime < 0) {
1868+
// time moving backwards, should only happen if no monotonic clock
1869+
// not a guarantee() because JVM should not abort on kernel/glibc bugs
1870+
assert(!os::supports_monotonic_clock(),
1871+
"unexpected time moving backwards detected in os::sleep(interruptible)");
1872+
} else {
1873+
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
1874+
}
1875+
1876+
if (millis <= 0) {
1877+
return OS_OK;
1878+
}
1879+
1880+
prevtime = newtime;
1881+
1882+
{
1883+
ThreadBlockInVM tbivm(jt);
1884+
OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */);
1885+
1886+
jt->set_suspend_equivalent();
1887+
// cleared by handle_special_suspend_equivalent_condition() or
1888+
// java_suspend_self() via check_and_wait_while_suspended()
1889+
1890+
slp->park(millis);
1891+
1892+
// were we externally suspended while we were waiting?
1893+
jt->check_and_wait_while_suspended();
1894+
}
1895+
}
1896+
} else {
1897+
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
1898+
jlong prevtime = javaTimeNanos();
1899+
1900+
for (;;) {
1901+
// It'd be nice to avoid the back-to-back javaTimeNanos() calls on
1902+
// the 1st iteration ...
1903+
jlong newtime = javaTimeNanos();
1904+
1905+
if (newtime - prevtime < 0) {
1906+
// time moving backwards, should only happen if no monotonic clock
1907+
// not a guarantee() because JVM should not abort on kernel/glibc bugs
1908+
assert(!os::supports_monotonic_clock(),
1909+
"unexpected time moving backwards detected on os::sleep(!interruptible)");
1910+
} else {
1911+
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
1912+
}
1913+
1914+
if (millis <= 0) break ;
1915+
1916+
prevtime = newtime;
1917+
slp->park(millis);
1918+
}
1919+
return OS_OK ;
1920+
}
1921+
}

0 commit comments

Comments
 (0)