Mercurial > hg > truffle
comparison src/os/posix/vm/os_posix.cpp @ 14475:6c9332549827
6546236: Thread interrupt() of Thread.sleep() can be lost on Solaris due to race with signal handler
Reviewed-by: dholmes, dcubed
author | fparain |
---|---|
date | Wed, 19 Feb 2014 16:22:15 +0000 |
parents | c250880a6673 |
children | bb9356ec5967 |
comparison
equal
deleted
inserted
replaced
14474:de7f1b016d55 | 14475:6c9332549827 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "prims/jvm.h" | 25 #include "prims/jvm.h" |
26 #include "runtime/frame.inline.hpp" | 26 #include "runtime/frame.inline.hpp" |
27 #include "runtime/interfaceSupport.hpp" | |
27 #include "runtime/os.hpp" | 28 #include "runtime/os.hpp" |
28 #include "utilities/vmError.hpp" | 29 #include "utilities/vmError.hpp" |
29 | 30 |
30 #include <unistd.h> | 31 #include <unistd.h> |
31 #include <sys/resource.h> | 32 #include <sys/resource.h> |
305 strncat(agent_entry_name, lib_name, name_len); | 306 strncat(agent_entry_name, lib_name, name_len); |
306 } | 307 } |
307 return agent_entry_name; | 308 return agent_entry_name; |
308 } | 309 } |
309 | 310 |
311 int os::sleep(Thread* thread, jlong millis, bool interruptible) { | |
312 assert(thread == Thread::current(), "thread consistency check"); | |
313 | |
314 ParkEvent * const slp = thread->_SleepEvent ; | |
315 slp->reset() ; | |
316 OrderAccess::fence() ; | |
317 | |
318 if (interruptible) { | |
319 jlong prevtime = javaTimeNanos(); | |
320 | |
321 for (;;) { | |
322 if (os::is_interrupted(thread, true)) { | |
323 return OS_INTRPT; | |
324 } | |
325 | |
326 jlong newtime = javaTimeNanos(); | |
327 | |
328 if (newtime - prevtime < 0) { | |
329 // time moving backwards, should only happen if no monotonic clock | |
330 // not a guarantee() because JVM should not abort on kernel/glibc bugs | |
331 assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected in os::sleep(interruptible)"); | |
332 } else { | |
333 millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; | |
334 } | |
335 | |
336 if (millis <= 0) { | |
337 return OS_OK; | |
338 } | |
339 | |
340 prevtime = newtime; | |
341 | |
342 { | |
343 assert(thread->is_Java_thread(), "sanity check"); | |
344 JavaThread *jt = (JavaThread *) thread; | |
345 ThreadBlockInVM tbivm(jt); | |
346 OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); | |
347 | |
348 jt->set_suspend_equivalent(); | |
349 // cleared by handle_special_suspend_equivalent_condition() or | |
350 // java_suspend_self() via check_and_wait_while_suspended() | |
351 | |
352 slp->park(millis); | |
353 | |
354 // were we externally suspended while we were waiting? | |
355 jt->check_and_wait_while_suspended(); | |
356 } | |
357 } | |
358 } else { | |
359 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); | |
360 jlong prevtime = javaTimeNanos(); | |
361 | |
362 for (;;) { | |
363 // It'd be nice to avoid the back-to-back javaTimeNanos() calls on | |
364 // the 1st iteration ... | |
365 jlong newtime = javaTimeNanos(); | |
366 | |
367 if (newtime - prevtime < 0) { | |
368 // time moving backwards, should only happen if no monotonic clock | |
369 // not a guarantee() because JVM should not abort on kernel/glibc bugs | |
370 assert(!os::supports_monotonic_clock(), "unexpected time moving backwards detected on os::sleep(!interruptible)"); | |
371 } else { | |
372 millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; | |
373 } | |
374 | |
375 if (millis <= 0) break ; | |
376 | |
377 prevtime = newtime; | |
378 slp->park(millis); | |
379 } | |
380 return OS_OK ; | |
381 } | |
382 } | |
383 | |
384 //////////////////////////////////////////////////////////////////////////////// | |
385 // interrupt support | |
386 | |
387 void os::interrupt(Thread* thread) { | |
388 assert(Thread::current() == thread || Threads_lock->owned_by_self(), | |
389 "possibility of dangling Thread pointer"); | |
390 | |
391 OSThread* osthread = thread->osthread(); | |
392 | |
393 if (!osthread->interrupted()) { | |
394 osthread->set_interrupted(true); | |
395 // More than one thread can get here with the same value of osthread, | |
396 // resulting in multiple notifications. We do, however, want the store | |
397 // to interrupted() to be visible to other threads before we execute unpark(). | |
398 OrderAccess::fence(); | |
399 ParkEvent * const slp = thread->_SleepEvent ; | |
400 if (slp != NULL) slp->unpark() ; | |
401 } | |
402 | |
403 // For JSR166. Unpark even if interrupt status already was set | |
404 if (thread->is_Java_thread()) | |
405 ((JavaThread*)thread)->parker()->unpark(); | |
406 | |
407 ParkEvent * ev = thread->_ParkEvent ; | |
408 if (ev != NULL) ev->unpark() ; | |
409 | |
410 } | |
411 | |
412 bool os::is_interrupted(Thread* thread, bool clear_interrupted) { | |
413 assert(Thread::current() == thread || Threads_lock->owned_by_self(), | |
414 "possibility of dangling Thread pointer"); | |
415 | |
416 OSThread* osthread = thread->osthread(); | |
417 | |
418 bool interrupted = osthread->interrupted(); | |
419 | |
420 // NOTE that since there is no "lock" around the interrupt and | |
421 // is_interrupted operations, there is the possibility that the | |
422 // interrupted flag (in osThread) will be "false" but that the | |
423 // low-level events will be in the signaled state. This is | |
424 // intentional. The effect of this is that Object.wait() and | |
425 // LockSupport.park() will appear to have a spurious wakeup, which | |
426 // is allowed and not harmful, and the possibility is so rare that | |
427 // it is not worth the added complexity to add yet another lock. | |
428 // For the sleep event an explicit reset is performed on entry | |
429 // to os::sleep, so there is no early return. It has also been | |
430 // recommended not to put the interrupted flag into the "event" | |
431 // structure because it hides the issue. | |
432 if (interrupted && clear_interrupted) { | |
433 osthread->set_interrupted(false); | |
434 // consider thread->_SleepEvent->reset() ... optional optimization | |
435 } | |
436 | |
437 return interrupted; | |
438 } | |
439 | |
310 os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { | 440 os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { |
311 assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); | 441 assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); |
312 } | 442 } |
313 | 443 |
314 /* | 444 /* |