Mercurial > hg > truffle
comparison src/share/vm/runtime/thread.cpp @ 6939:c284cf4781f0
7127792: Add the ability to change an existing PeriodicTask's execution interval
Summary: Enables dynamic enrollment / disenrollment from the PeriodicTasks in WatcherThread.
Reviewed-by: dholmes, mgronlun
author | rbackman |
---|---|
date | Thu, 04 Oct 2012 14:55:57 +0200 |
parents | a1b8cf9cf970 |
children | e522a00b91aa d9a84e246cce 070d523b96a7 |
comparison
equal
deleted
inserted
replaced
6938:8940ddc1036f | 6939:c284cf4781f0 |
---|---|
1215 // The watcher thread exists to simulate timer interrupts. It should | 1215 // The watcher thread exists to simulate timer interrupts. It should |
1216 // be replaced by an abstraction over whatever native support for | 1216 // be replaced by an abstraction over whatever native support for |
1217 // timer interrupts exists on the platform. | 1217 // timer interrupts exists on the platform. |
1218 | 1218 |
1219 WatcherThread* WatcherThread::_watcher_thread = NULL; | 1219 WatcherThread* WatcherThread::_watcher_thread = NULL; |
1220 bool WatcherThread::_startable = false; | |
1220 volatile bool WatcherThread::_should_terminate = false; | 1221 volatile bool WatcherThread::_should_terminate = false; |
1221 | 1222 |
1222 WatcherThread::WatcherThread() : Thread() { | 1223 WatcherThread::WatcherThread() : Thread() { |
1223 assert(watcher_thread() == NULL, "we can only allocate one WatcherThread"); | 1224 assert(watcher_thread() == NULL, "we can only allocate one WatcherThread"); |
1224 if (os::create_thread(this, os::watcher_thread)) { | 1225 if (os::create_thread(this, os::watcher_thread)) { |
1235 os::start_thread(this); | 1236 os::start_thread(this); |
1236 } | 1237 } |
1237 } | 1238 } |
1238 } | 1239 } |
1239 | 1240 |
1241 int WatcherThread::sleep() const { | |
1242 MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); | |
1243 | |
1244 // remaining will be zero if there are no tasks, | |
1245 // causing the WatcherThread to sleep until a task is | |
1246 // enrolled | |
1247 int remaining = PeriodicTask::time_to_wait(); | |
1248 int time_slept = 0; | |
1249 | |
1250 // we expect this to timeout - we only ever get unparked when | |
1251 // we should terminate or when a new task has been enrolled | |
1252 OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */); | |
1253 | |
1254 jlong time_before_loop = os::javaTimeNanos(); | |
1255 | |
1256 for (;;) { | |
1257 bool timedout = PeriodicTask_lock->wait(Mutex::_no_safepoint_check_flag, remaining); | |
1258 jlong now = os::javaTimeNanos(); | |
1259 | |
1260 if (remaining == 0) { | |
1261 // if we didn't have any tasks we could have waited for a long time | |
1262 // consider the time_slept zero and reset time_before_loop | |
1263 time_slept = 0; | |
1264 time_before_loop = now; | |
1265 } else { | |
1266 // need to recalulate since we might have new tasks in _tasks | |
1267 time_slept = (int) ((now - time_before_loop) / 1000000); | |
1268 } | |
1269 | |
1270 // Change to task list or spurious wakeup of some kind | |
1271 if (timedout || _should_terminate) { | |
1272 break; | |
1273 } | |
1274 | |
1275 remaining = PeriodicTask::time_to_wait(); | |
1276 if (remaining == 0) { | |
1277 // Last task was just disenrolled so loop around and wait until | |
1278 // another task gets enrolled | |
1279 continue; | |
1280 } | |
1281 | |
1282 remaining -= time_slept; | |
1283 if (remaining <= 0) | |
1284 break; | |
1285 } | |
1286 | |
1287 return time_slept; | |
1288 } | |
1289 | |
1240 void WatcherThread::run() { | 1290 void WatcherThread::run() { |
1241 assert(this == watcher_thread(), "just checking"); | 1291 assert(this == watcher_thread(), "just checking"); |
1242 | 1292 |
1243 this->record_stack_base_and_size(); | 1293 this->record_stack_base_and_size(); |
1244 this->initialize_thread_local_storage(); | 1294 this->initialize_thread_local_storage(); |
1247 assert(watcher_thread() == Thread::current(), "thread consistency check"); | 1297 assert(watcher_thread() == Thread::current(), "thread consistency check"); |
1248 assert(watcher_thread() == this, "thread consistency check"); | 1298 assert(watcher_thread() == this, "thread consistency check"); |
1249 | 1299 |
1250 // Calculate how long it'll be until the next PeriodicTask work | 1300 // Calculate how long it'll be until the next PeriodicTask work |
1251 // should be done, and sleep that amount of time. | 1301 // should be done, and sleep that amount of time. |
1252 size_t time_to_wait = PeriodicTask::time_to_wait(); | 1302 int time_waited = sleep(); |
1253 | |
1254 // we expect this to timeout - we only ever get unparked when | |
1255 // we should terminate | |
1256 { | |
1257 OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */); | |
1258 | |
1259 jlong prev_time = os::javaTimeNanos(); | |
1260 for (;;) { | |
1261 int res= _SleepEvent->park(time_to_wait); | |
1262 if (res == OS_TIMEOUT || _should_terminate) | |
1263 break; | |
1264 // spurious wakeup of some kind | |
1265 jlong now = os::javaTimeNanos(); | |
1266 time_to_wait -= (now - prev_time) / 1000000; | |
1267 if (time_to_wait <= 0) | |
1268 break; | |
1269 prev_time = now; | |
1270 } | |
1271 } | |
1272 | 1303 |
1273 if (is_error_reported()) { | 1304 if (is_error_reported()) { |
1274 // A fatal error has happened, the error handler(VMError::report_and_die) | 1305 // A fatal error has happened, the error handler(VMError::report_and_die) |
1275 // should abort JVM after creating an error log file. However in some | 1306 // should abort JVM after creating an error log file. However in some |
1276 // rare cases, the error handler itself might deadlock. Here we try to | 1307 // rare cases, the error handler itself might deadlock. Here we try to |
1296 // ShowMessageBoxOnError when it is ready to abort. | 1327 // ShowMessageBoxOnError when it is ready to abort. |
1297 os::sleep(this, 5 * 1000, false); | 1328 os::sleep(this, 5 * 1000, false); |
1298 } | 1329 } |
1299 } | 1330 } |
1300 | 1331 |
1301 PeriodicTask::real_time_tick(time_to_wait); | 1332 PeriodicTask::real_time_tick(time_waited); |
1302 | |
1303 // If we have no more tasks left due to dynamic disenrollment, | |
1304 // shut down the thread since we don't currently support dynamic enrollment | |
1305 if (PeriodicTask::num_tasks() == 0) { | |
1306 _should_terminate = true; | |
1307 } | |
1308 } | 1333 } |
1309 | 1334 |
1310 // Signal that it is terminated | 1335 // Signal that it is terminated |
1311 { | 1336 { |
1312 MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); | 1337 MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); |
1317 // Thread destructor usually does this.. | 1342 // Thread destructor usually does this.. |
1318 ThreadLocalStorage::set_thread(NULL); | 1343 ThreadLocalStorage::set_thread(NULL); |
1319 } | 1344 } |
1320 | 1345 |
1321 void WatcherThread::start() { | 1346 void WatcherThread::start() { |
1322 if (watcher_thread() == NULL) { | 1347 assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); |
1348 | |
1349 if (watcher_thread() == NULL && _startable) { | |
1323 _should_terminate = false; | 1350 _should_terminate = false; |
1324 // Create the single instance of WatcherThread | 1351 // Create the single instance of WatcherThread |
1325 new WatcherThread(); | 1352 new WatcherThread(); |
1326 } | 1353 } |
1327 } | 1354 } |
1328 | 1355 |
1356 void WatcherThread::make_startable() { | |
1357 assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); | |
1358 _startable = true; | |
1359 } | |
1360 | |
1329 void WatcherThread::stop() { | 1361 void WatcherThread::stop() { |
1362 { | |
1363 MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); | |
1364 _should_terminate = true; | |
1365 OrderAccess::fence(); // ensure WatcherThread sees update in main loop | |
1366 | |
1367 WatcherThread* watcher = watcher_thread(); | |
1368 if (watcher != NULL) | |
1369 watcher->unpark(); | |
1370 } | |
1371 | |
1330 // it is ok to take late safepoints here, if needed | 1372 // it is ok to take late safepoints here, if needed |
1331 MutexLocker mu(Terminator_lock); | 1373 MutexLocker mu(Terminator_lock); |
1332 _should_terminate = true; | |
1333 OrderAccess::fence(); // ensure WatcherThread sees update in main loop | |
1334 | |
1335 Thread* watcher = watcher_thread(); | |
1336 if (watcher != NULL) | |
1337 watcher->_SleepEvent->unpark(); | |
1338 | 1374 |
1339 while(watcher_thread() != NULL) { | 1375 while(watcher_thread() != NULL) { |
1340 // This wait should make safepoint checks, wait without a timeout, | 1376 // This wait should make safepoint checks, wait without a timeout, |
1341 // and wait as a suspend-equivalent condition. | 1377 // and wait as a suspend-equivalent condition. |
1342 // | 1378 // |
1348 // suspend-equivalent condition solves that timeout problem. | 1384 // suspend-equivalent condition solves that timeout problem. |
1349 // | 1385 // |
1350 Terminator_lock->wait(!Mutex::_no_safepoint_check_flag, 0, | 1386 Terminator_lock->wait(!Mutex::_no_safepoint_check_flag, 0, |
1351 Mutex::_as_suspend_equivalent_flag); | 1387 Mutex::_as_suspend_equivalent_flag); |
1352 } | 1388 } |
1389 } | |
1390 | |
1391 void WatcherThread::unpark() { | |
1392 MutexLockerEx ml(PeriodicTask_lock->owned_by_self() ? NULL : PeriodicTask_lock, Mutex::_no_safepoint_check_flag); | |
1393 PeriodicTask_lock->notify(); | |
1353 } | 1394 } |
1354 | 1395 |
1355 void WatcherThread::print_on(outputStream* st) const { | 1396 void WatcherThread::print_on(outputStream* st) const { |
1356 st->print("\"%s\" ", name()); | 1397 st->print("\"%s\" ", name()); |
1357 Thread::print_on(st); | 1398 Thread::print_on(st); |
3656 if (HAS_PENDING_EXCEPTION) { | 3697 if (HAS_PENDING_EXCEPTION) { |
3657 CLEAR_PENDING_EXCEPTION; | 3698 CLEAR_PENDING_EXCEPTION; |
3658 } | 3699 } |
3659 } | 3700 } |
3660 | 3701 |
3661 // Start up the WatcherThread if there are any periodic tasks | 3702 { |
3662 // NOTE: All PeriodicTasks should be registered by now. If they | 3703 MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); |
3663 // aren't, late joiners might appear to start slowly (we might | 3704 // Make sure the watcher thread can be started by WatcherThread::start() |
3664 // take a while to process their first tick). | 3705 // or by dynamic enrollment. |
3665 if (PeriodicTask::num_tasks() > 0) { | 3706 WatcherThread::make_startable(); |
3666 WatcherThread::start(); | 3707 // Start up the WatcherThread if there are any periodic tasks |
3708 // NOTE: All PeriodicTasks should be registered by now. If they | |
3709 // aren't, late joiners might appear to start slowly (we might | |
3710 // take a while to process their first tick). | |
3711 if (PeriodicTask::num_tasks() > 0) { | |
3712 WatcherThread::start(); | |
3713 } | |
3667 } | 3714 } |
3668 | 3715 |
3669 // Give os specific code one last chance to start | 3716 // Give os specific code one last chance to start |
3670 os::init_3(); | 3717 os::init_3(); |
3671 | 3718 |