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