Mercurial > hg > truffle
comparison src/os/solaris/vm/os_solaris.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 | 2c2a99f6cf83 |
children | bb9356ec5967 |
comparison
equal
deleted
inserted
replaced
14474:de7f1b016d55 | 14475:6c9332549827 |
---|---|
330 osthread->set_saved_interrupt_thread_state(thread_state); | 330 osthread->set_saved_interrupt_thread_state(thread_state); |
331 thread->frame_anchor()->make_walkable(thread); | 331 thread->frame_anchor()->make_walkable(thread); |
332 ThreadStateTransition::transition(thread, thread_state, _thread_blocked); | 332 ThreadStateTransition::transition(thread, thread_state, _thread_blocked); |
333 } | 333 } |
334 | 334 |
335 // Version of setup_interruptible() for threads that are already in | |
336 // _thread_blocked. Used by os_sleep(). | |
337 void os::Solaris::setup_interruptible_already_blocked(JavaThread* thread) { | |
338 thread->frame_anchor()->make_walkable(thread); | |
339 } | |
340 | |
341 JavaThread* os::Solaris::setup_interruptible() { | 335 JavaThread* os::Solaris::setup_interruptible() { |
342 JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread(); | 336 JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread(); |
343 setup_interruptible(thread); | 337 setup_interruptible(thread); |
344 return thread; | 338 return thread; |
345 } | 339 } |
3421 | 3415 |
3422 bool os::can_execute_large_page_memory() { | 3416 bool os::can_execute_large_page_memory() { |
3423 return true; | 3417 return true; |
3424 } | 3418 } |
3425 | 3419 |
3426 static int os_sleep(jlong millis, bool interruptible) { | |
3427 const jlong limit = INT_MAX; | |
3428 jlong prevtime; | |
3429 int res; | |
3430 | |
3431 while (millis > limit) { | |
3432 if ((res = os_sleep(limit, interruptible)) != OS_OK) | |
3433 return res; | |
3434 millis -= limit; | |
3435 } | |
3436 | |
3437 // Restart interrupted polls with new parameters until the proper delay | |
3438 // has been completed. | |
3439 | |
3440 prevtime = getTimeMillis(); | |
3441 | |
3442 while (millis > 0) { | |
3443 jlong newtime; | |
3444 | |
3445 if (!interruptible) { | |
3446 // Following assert fails for os::yield_all: | |
3447 // assert(!thread->is_Java_thread(), "must not be java thread"); | |
3448 res = poll(NULL, 0, millis); | |
3449 } else { | |
3450 JavaThread *jt = JavaThread::current(); | |
3451 | |
3452 INTERRUPTIBLE_NORESTART_VM_ALWAYS(poll(NULL, 0, millis), res, jt, | |
3453 os::Solaris::clear_interrupted); | |
3454 } | |
3455 | |
3456 // INTERRUPTIBLE_NORESTART_VM_ALWAYS returns res == OS_INTRPT for | |
3457 // thread.Interrupt. | |
3458 | |
3459 // See c/r 6751923. Poll can return 0 before time | |
3460 // has elapsed if time is set via clock_settime (as NTP does). | |
3461 // res == 0 if poll timed out (see man poll RETURN VALUES) | |
3462 // using the logic below checks that we really did | |
3463 // sleep at least "millis" if not we'll sleep again. | |
3464 if( ( res == 0 ) || ((res == OS_ERR) && (errno == EINTR))) { | |
3465 newtime = getTimeMillis(); | |
3466 assert(newtime >= prevtime, "time moving backwards"); | |
3467 /* Doing prevtime and newtime in microseconds doesn't help precision, | |
3468 and trying to round up to avoid lost milliseconds can result in a | |
3469 too-short delay. */ | |
3470 millis -= newtime - prevtime; | |
3471 if(millis <= 0) | |
3472 return OS_OK; | |
3473 prevtime = newtime; | |
3474 } else | |
3475 return res; | |
3476 } | |
3477 | |
3478 return OS_OK; | |
3479 } | |
3480 | |
3481 // Read calls from inside the vm need to perform state transitions | 3420 // Read calls from inside the vm need to perform state transitions |
3482 size_t os::read(int fd, void *buf, unsigned int nBytes) { | 3421 size_t os::read(int fd, void *buf, unsigned int nBytes) { |
3483 INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); | 3422 INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); |
3484 } | 3423 } |
3485 | 3424 |
3486 size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { | 3425 size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { |
3487 INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); | 3426 INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); |
3488 } | |
3489 | |
3490 int os::sleep(Thread* thread, jlong millis, bool interruptible) { | |
3491 assert(thread == Thread::current(), "thread consistency check"); | |
3492 | |
3493 // TODO-FIXME: this should be removed. | |
3494 // On Solaris machines (especially 2.5.1) we found that sometimes the VM gets into a live lock | |
3495 // situation with a JavaThread being starved out of a lwp. The kernel doesn't seem to generate | |
3496 // a SIGWAITING signal which would enable the threads library to create a new lwp for the starving | |
3497 // thread. We suspect that because the Watcher thread keeps waking up at periodic intervals the kernel | |
3498 // is fooled into believing that the system is making progress. In the code below we block the | |
3499 // the watcher thread while safepoint is in progress so that it would not appear as though the | |
3500 // system is making progress. | |
3501 if (!Solaris::T2_libthread() && | |
3502 thread->is_Watcher_thread() && SafepointSynchronize::is_synchronizing() && !Arguments::has_profile()) { | |
3503 // We now try to acquire the threads lock. Since this lock is held by the VM thread during | |
3504 // the entire safepoint, the watcher thread will line up here during the safepoint. | |
3505 Threads_lock->lock_without_safepoint_check(); | |
3506 Threads_lock->unlock(); | |
3507 } | |
3508 | |
3509 if (thread->is_Java_thread()) { | |
3510 // This is a JavaThread so we honor the _thread_blocked protocol | |
3511 // even for sleeps of 0 milliseconds. This was originally done | |
3512 // as a workaround for bug 4338139. However, now we also do it | |
3513 // to honor the suspend-equivalent protocol. | |
3514 | |
3515 JavaThread *jt = (JavaThread *) thread; | |
3516 ThreadBlockInVM tbivm(jt); | |
3517 | |
3518 jt->set_suspend_equivalent(); | |
3519 // cleared by handle_special_suspend_equivalent_condition() or | |
3520 // java_suspend_self() via check_and_wait_while_suspended() | |
3521 | |
3522 int ret_code; | |
3523 if (millis <= 0) { | |
3524 thr_yield(); | |
3525 ret_code = 0; | |
3526 } else { | |
3527 // The original sleep() implementation did not create an | |
3528 // OSThreadWaitState helper for sleeps of 0 milliseconds. | |
3529 // I'm preserving that decision for now. | |
3530 OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); | |
3531 | |
3532 ret_code = os_sleep(millis, interruptible); | |
3533 } | |
3534 | |
3535 // were we externally suspended while we were waiting? | |
3536 jt->check_and_wait_while_suspended(); | |
3537 | |
3538 return ret_code; | |
3539 } | |
3540 | |
3541 // non-JavaThread from this point on: | |
3542 | |
3543 if (millis <= 0) { | |
3544 thr_yield(); | |
3545 return 0; | |
3546 } | |
3547 | |
3548 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); | |
3549 | |
3550 return os_sleep(millis, interruptible); | |
3551 } | 3427 } |
3552 | 3428 |
3553 void os::naked_short_sleep(jlong ms) { | 3429 void os::naked_short_sleep(jlong ms) { |
3554 assert(ms < 1000, "Un-interruptable sleep, short time use only"); | 3430 assert(ms < 1000, "Un-interruptable sleep, short time use only"); |
3555 | 3431 |
4189 // ignore | 4065 // ignore |
4190 } | 4066 } |
4191 | 4067 |
4192 errno = old_errno; | 4068 errno = old_errno; |
4193 } | 4069 } |
4194 | |
4195 | |
4196 void os::interrupt(Thread* thread) { | |
4197 assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); | |
4198 | |
4199 OSThread* osthread = thread->osthread(); | |
4200 | |
4201 int isInterrupted = osthread->interrupted(); | |
4202 if (!isInterrupted) { | |
4203 osthread->set_interrupted(true); | |
4204 OrderAccess::fence(); | |
4205 // os::sleep() is implemented with either poll (NULL,0,timeout) or | |
4206 // by parking on _SleepEvent. If the former, thr_kill will unwedge | |
4207 // the sleeper by SIGINTR, otherwise the unpark() will wake the sleeper. | |
4208 ParkEvent * const slp = thread->_SleepEvent ; | |
4209 if (slp != NULL) slp->unpark() ; | |
4210 } | |
4211 | |
4212 // For JSR166: unpark after setting status but before thr_kill -dl | |
4213 if (thread->is_Java_thread()) { | |
4214 ((JavaThread*)thread)->parker()->unpark(); | |
4215 } | |
4216 | |
4217 // Handle interruptible wait() ... | |
4218 ParkEvent * const ev = thread->_ParkEvent ; | |
4219 if (ev != NULL) ev->unpark() ; | |
4220 | |
4221 // When events are used everywhere for os::sleep, then this thr_kill | |
4222 // will only be needed if UseVMInterruptibleIO is true. | |
4223 | |
4224 if (!isInterrupted) { | |
4225 int status = thr_kill(osthread->thread_id(), os::Solaris::SIGinterrupt()); | |
4226 assert_status(status == 0, status, "thr_kill"); | |
4227 | |
4228 // Bump thread interruption counter | |
4229 RuntimeService::record_thread_interrupt_signaled_count(); | |
4230 } | |
4231 } | |
4232 | |
4233 | |
4234 bool os::is_interrupted(Thread* thread, bool clear_interrupted) { | |
4235 assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); | |
4236 | |
4237 OSThread* osthread = thread->osthread(); | |
4238 | |
4239 bool res = osthread->interrupted(); | |
4240 | |
4241 // NOTE that since there is no "lock" around these two operations, | |
4242 // there is the possibility that the interrupted flag will be | |
4243 // "false" but that the interrupt event will be set. This is | |
4244 // intentional. The effect of this is that Object.wait() will appear | |
4245 // to have a spurious wakeup, which is not harmful, and the | |
4246 // possibility is so rare that it is not worth the added complexity | |
4247 // to add yet another lock. It has also been recommended not to put | |
4248 // the interrupted flag into the os::Solaris::Event structure, | |
4249 // because it hides the issue. | |
4250 if (res && clear_interrupted) { | |
4251 osthread->set_interrupted(false); | |
4252 } | |
4253 return res; | |
4254 } | |
4255 | |
4256 | 4070 |
4257 void os::print_statistics() { | 4071 void os::print_statistics() { |
4258 } | 4072 } |
4259 | 4073 |
4260 int os::message_box(const char* title, const char* message) { | 4074 int os::message_box(const char* title, const char* message) { |