src/hotspot/share/gc/shenandoah/shenandoahEvacOOMHandler.cpp
changeset 59247 56bf71d64d51
parent 52925 9c18c9d839d3
child 59252 623722a6aeb9
equal deleted inserted replaced
59246:fcad92f425c5 59247:56bf71d64d51
    36 ShenandoahEvacOOMHandler::ShenandoahEvacOOMHandler() :
    36 ShenandoahEvacOOMHandler::ShenandoahEvacOOMHandler() :
    37   _threads_in_evac(0) {
    37   _threads_in_evac(0) {
    38 }
    38 }
    39 
    39 
    40 void ShenandoahEvacOOMHandler::wait_for_no_evac_threads() {
    40 void ShenandoahEvacOOMHandler::wait_for_no_evac_threads() {
    41   while ((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) != 0) {
    41   while ((Atomic::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) != 0) {
    42     os::naked_short_sleep(1);
    42     os::naked_short_sleep(1);
    43   }
    43   }
    44   // At this point we are sure that no threads can evacuate anything. Raise
    44   // At this point we are sure that no threads can evacuate anything. Raise
    45   // the thread-local oom_during_evac flag to indicate that any attempt
    45   // the thread-local oom_during_evac flag to indicate that any attempt
    46   // to evacuate should simply return the forwarding pointer instead (which is safe now).
    46   // to evacuate should simply return the forwarding pointer instead (which is safe now).
    47   ShenandoahThreadLocalData::set_oom_during_evac(Thread::current(), true);
    47   ShenandoahThreadLocalData::set_oom_during_evac(Thread::current(), true);
    48 }
    48 }
    49 
    49 
    50 void ShenandoahEvacOOMHandler::enter_evacuation() {
    50 void ShenandoahEvacOOMHandler::enter_evacuation() {
    51   jint threads_in_evac = OrderAccess::load_acquire(&_threads_in_evac);
    51   jint threads_in_evac = Atomic::load_acquire(&_threads_in_evac);
    52 
    52 
    53   assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity");
    53   assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity");
    54   assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set");
    54   assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set");
    55 
    55 
    56   if ((threads_in_evac & OOM_MARKER_MASK) != 0) {
    56   if ((threads_in_evac & OOM_MARKER_MASK) != 0) {
    77   }
    77   }
    78 }
    78 }
    79 
    79 
    80 void ShenandoahEvacOOMHandler::leave_evacuation() {
    80 void ShenandoahEvacOOMHandler::leave_evacuation() {
    81   if (!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current())) {
    81   if (!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current())) {
    82     assert((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) > 0, "sanity");
    82     assert((Atomic::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) > 0, "sanity");
    83     // NOTE: It's ok to simply decrement, even with mask set, because unmasked value is positive.
    83     // NOTE: It's ok to simply decrement, even with mask set, because unmasked value is positive.
    84     Atomic::dec(&_threads_in_evac);
    84     Atomic::dec(&_threads_in_evac);
    85   } else {
    85   } else {
    86     // If we get here, the current thread has already gone through the
    86     // If we get here, the current thread has already gone through the
    87     // OOM-during-evac protocol and has thus either never entered or successfully left
    87     // OOM-during-evac protocol and has thus either never entered or successfully left
    94 
    94 
    95 void ShenandoahEvacOOMHandler::handle_out_of_memory_during_evacuation() {
    95 void ShenandoahEvacOOMHandler::handle_out_of_memory_during_evacuation() {
    96   assert(ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity");
    96   assert(ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity");
    97   assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set");
    97   assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set");
    98 
    98 
    99   jint threads_in_evac = OrderAccess::load_acquire(&_threads_in_evac);
    99   jint threads_in_evac = Atomic::load_acquire(&_threads_in_evac);
   100   while (true) {
   100   while (true) {
   101     jint other = Atomic::cmpxchg((threads_in_evac - 1) | OOM_MARKER_MASK,
   101     jint other = Atomic::cmpxchg((threads_in_evac - 1) | OOM_MARKER_MASK,
   102                                   &_threads_in_evac, threads_in_evac);
   102                                   &_threads_in_evac, threads_in_evac);
   103     if (other == threads_in_evac) {
   103     if (other == threads_in_evac) {
   104       // Success: wait for other threads to get out of the protocol and return.
   104       // Success: wait for other threads to get out of the protocol and return.
   111   }
   111   }
   112 }
   112 }
   113 
   113 
   114 void ShenandoahEvacOOMHandler::clear() {
   114 void ShenandoahEvacOOMHandler::clear() {
   115   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at a safepoint");
   115   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at a safepoint");
   116   assert((OrderAccess::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) == 0, "sanity");
   116   assert((Atomic::load_acquire(&_threads_in_evac) & ~OOM_MARKER_MASK) == 0, "sanity");
   117   OrderAccess::release_store_fence<jint>(&_threads_in_evac, 0);
   117   Atomic::release_store_fence<jint>(&_threads_in_evac, 0);
   118 }
   118 }
   119 
   119 
   120 ShenandoahEvacOOMScope::ShenandoahEvacOOMScope() {
   120 ShenandoahEvacOOMScope::ShenandoahEvacOOMScope() {
   121   ShenandoahHeap::heap()->enter_evacuation();
   121   ShenandoahHeap::heap()->enter_evacuation();
   122 }
   122 }