Exemplo n.º 1
0
void GC_locker::jni_lock_slow() {
  MutexLocker mu(JNICritical_lock);
  // Block entering threads if we know at least one thread is in a
  // JNI critical region and we need a GC.
  // We check that at least one thread is in a critical region before
  // blocking because blocked threads are woken up by a thread exiting
  // a JNI critical region.
  while ((is_jni_active() && needs_gc()) || _doing_gc) {
    JNICritical_lock->wait();
  }
  jni_lock();
}
Exemplo n.º 2
0
void GC_locker::jni_unlock_slow() {
  MutexLocker mu(JNICritical_lock);
  jni_unlock();
  if (needs_gc() && !is_jni_active()) {
    // We're the last thread out. Cause a GC to occur.
    // GC will also check is_active, so this check is not
    // strictly needed. It's added here to make it clear that
    // the GC will NOT be performed if any other caller
    // of GC_locker::lock() still needs GC locked.
    if (!is_active()) {
      _doing_gc = true;
      {
        // Must give up the lock while at a safepoint
        MutexUnlocker munlock(JNICritical_lock);
        Universe::heap()->collect(GCCause::_gc_locker);
      }
      _doing_gc = false;
    }
    clear_needs_gc();
    JNICritical_lock->notify_all();
  }
}
void GC_locker::jni_lock_slow() {
  ThreadBlockInVM tbinvm(JavaThread::current(),"JNICritical_lock");
  MutexLocker mu(JNICritical_lock);
  // Block entering threads if we know at least one thread is in a
  // JNI critical region and we need a GC.
  // We check that at least one thread is in a critical region before
  // blocking because blocked threads are woken up by a thread exiting
  // a JNI critical region.
  while (1) {
    jlong old_state = lock_state(); 
  
    if ( (is_jni_active(old_state) && needs_gc(old_state)) || doing_gc(old_state) ) {
      JNICritical_lock.wait();
    } else {
      jlong new_state = increment_lock_count(old_state);
      if ( old_state == Atomic::cmpxchg(new_state, state_addr(), old_state) ) {
        // lock successful
        break;
      }
 
      // lock failed, loop around and try again.
    }
  }
}
void GC_locker::jni_unlock_slow() {
  // There isn't a slow path jni_unlock with GPGC or PGC.
  assert0((!UseGenPauselessGC));

  MutexLocker mu(JNICritical_lock);

  jlong old_state;
  jlong new_state;

  bool  do_a_gc;
  bool  do_a_notify;

  while (1) {
    do_a_gc     = false;
    do_a_notify = false;

    old_state = lock_state();
    new_state = decrement_lock_count(old_state);

    if ( needs_gc(new_state) && !is_jni_active(new_state) ) {
      do_a_notify = true;
      // GC will also check is_active, so this check is not
      // strictly needed. It's added here to make it clear that
      // the GC will NOT be performed if any other caller
      // of GC_locker::lock() still needs GC locked.
      if ( (!doing_gc(new_state)) && (!is_active()) ) {
        do_a_gc = true;
        new_state = set_doing_gc(new_state);
      } else {
        new_state = clear_needs_gc(new_state);
      }
    }

    if ((old_state = Atomic::cmpxchg(new_state, state_addr(), old_state))) {
      // unlocked successful
      break;
    }

    // unlock failed, loop around and try again.
  } 

  if ( do_a_gc ) {
    {
      // Must give up the lock while at a safepoint
      MutexUnlocker munlock(JNICritical_lock);
      Universe::heap()->collect(GCCause::_gc_locker);
    }

    // Now that the lock is reaquired, unset _doing_gc and _needs_gc:
    while (1) {
      old_state = lock_state();
      new_state = clear_needs_gc(clear_doing_gc(old_state));

      if ((old_state = Atomic::cmpxchg(new_state, state_addr(), old_state))) {
        // clear successful
        break;
      }

      // clear failed, loop around and try again.
    }
  }

  if ( do_a_notify ) {
JNICritical_lock.notify_all();
  }
}