< prev index next >

src/hotspot/share/runtime/interfaceSupport.inline.hpp

Print this page




 237   }
 238 };
 239 
 240 
 241 class ThreadBlockInVM : public ThreadStateTransition {
 242  public:
 243   ThreadBlockInVM(JavaThread *thread)
 244   : ThreadStateTransition(thread) {
 245     // Once we are blocked vm expects stack to be walkable
 246     thread->frame_anchor()->make_walkable(thread);
 247     trans(_thread_in_vm, _thread_blocked);
 248   }
 249   ~ThreadBlockInVM() {
 250     trans(_thread_blocked, _thread_in_vm);
 251     OrderAccess::cross_modify_fence();
 252     // We don't need to clear_walkable because it will happen automagically when we return to java
 253   }
 254 };
 255 
 256 // Unlike ThreadBlockInVM, this class is designed to avoid certain deadlock scenarios while making
 257 // transitions inside class Monitor in cases where we need to block for a safepoint or handshake. It
 258 // receives an extra argument compared to ThreadBlockInVM, the address of a pointer to the monitor we
 259 // are trying to acquire. This will be used to access and release the monitor if needed to avoid
 260 // said deadlocks.
 261 // It works like ThreadBlockInVM but differs from it in two ways:
 262 // - When transitioning in (constructor), it checks for safepoints without blocking, i.e., calls
 263 //   back if needed to allow a pending safepoint to continue but does not block in it.
 264 // - When transitioning back (destructor), if there is a pending safepoint or handshake it releases
 265 //   the monitor that is only partially acquired.
 266 class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition {
 267  private:
 268   Monitor** _in_flight_monitor_adr;
 269 
 270   void release_monitor() {
 271     assert(_in_flight_monitor_adr != NULL, "_in_flight_monitor_adr should have been set on constructor");
 272     Monitor* in_flight_monitor = *_in_flight_monitor_adr;
 273     if (in_flight_monitor != NULL) {
 274       in_flight_monitor->release_for_safepoint();
 275       *_in_flight_monitor_adr = NULL;
 276     }
 277   }
 278  public:
 279   ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Monitor** in_flight_monitor_adr)
 280   : ThreadStateTransition(thread), _in_flight_monitor_adr(in_flight_monitor_adr) {
 281     // Once we are blocked vm expects stack to be walkable
 282     thread->frame_anchor()->make_walkable(thread);
 283 
 284     // All unsafe states are treated the same by the VMThread
 285     // so we can skip the _thread_in_vm_trans state here. Since
 286     // we don't read poll, it's enough to order the stores.
 287     OrderAccess::storestore();
 288 
 289     thread->set_thread_state(_thread_blocked);
 290   }
 291   ~ThreadBlockInVMWithDeadlockCheck() {
 292     // Change to transition state and ensure it is seen by the VM thread.
 293     _thread->set_thread_state_fence((JavaThreadState)(_thread_blocked_trans));
 294 
 295     if (SafepointMechanism::should_block(_thread)) {
 296       release_monitor();
 297       SafepointMechanism::block_if_requested(_thread);
 298     }
 299 
 300     _thread->set_thread_state(_thread_in_vm);




 237   }
 238 };
 239 
 240 
 241 class ThreadBlockInVM : public ThreadStateTransition {
 242  public:
 243   ThreadBlockInVM(JavaThread *thread)
 244   : ThreadStateTransition(thread) {
 245     // Once we are blocked vm expects stack to be walkable
 246     thread->frame_anchor()->make_walkable(thread);
 247     trans(_thread_in_vm, _thread_blocked);
 248   }
 249   ~ThreadBlockInVM() {
 250     trans(_thread_blocked, _thread_in_vm);
 251     OrderAccess::cross_modify_fence();
 252     // We don't need to clear_walkable because it will happen automagically when we return to java
 253   }
 254 };
 255 
 256 // Unlike ThreadBlockInVM, this class is designed to avoid certain deadlock scenarios while making
 257 // transitions inside class Mutex in cases where we need to block for a safepoint or handshake. It
 258 // receives an extra argument compared to ThreadBlockInVM, the address of a pointer to the monitor we
 259 // are trying to acquire. This will be used to access and release the mutex if needed to avoid
 260 // said deadlocks.
 261 // It works like ThreadBlockInVM but differs from it in two ways:
 262 // - When transitioning in (constructor), it checks for safepoints without blocking, i.e., calls
 263 //   back if needed to allow a pending safepoint to continue but does not block in it.
 264 // - When transitioning back (destructor), if there is a pending safepoint or handshake it releases
 265 //   the monitor that is only partially acquired.
 266 class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition {
 267  private:
 268   Mutex** _in_flight_mutex_addr;
 269 
 270   void release_monitor() {
 271     assert(_in_flight_mutex_addr != NULL, "_in_flight_mutex_addr should have been set on constructor");
 272     Mutex* in_flight_mutex = *_in_flight_mutex_addr;
 273     if (in_flight_mutex != NULL) {
 274       in_flight_mutex->release_for_safepoint();
 275       *_in_flight_mutex_addr = NULL;
 276     }
 277   }
 278  public:
 279   ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Mutex** in_flight_mutex_addr)
 280   : ThreadStateTransition(thread), _in_flight_mutex_addr(in_flight_mutex_addr) {
 281     // Once we are blocked vm expects stack to be walkable
 282     thread->frame_anchor()->make_walkable(thread);
 283 
 284     // All unsafe states are treated the same by the VMThread
 285     // so we can skip the _thread_in_vm_trans state here. Since
 286     // we don't read poll, it's enough to order the stores.
 287     OrderAccess::storestore();
 288 
 289     thread->set_thread_state(_thread_blocked);
 290   }
 291   ~ThreadBlockInVMWithDeadlockCheck() {
 292     // Change to transition state and ensure it is seen by the VM thread.
 293     _thread->set_thread_state_fence((JavaThreadState)(_thread_blocked_trans));
 294 
 295     if (SafepointMechanism::should_block(_thread)) {
 296       release_monitor();
 297       SafepointMechanism::block_if_requested(_thread);
 298     }
 299 
 300     _thread->set_thread_state(_thread_in_vm);


< prev index next >