< prev index next >

src/hotspot/share/runtime/synchronizer.cpp

Print this page

        

*** 255,289 **** return false; // revert to slow-path } // ----------------------------------------------------------------------------- ! // Fast Monitor Enter/Exit ! // This the fast monitor enter. The interpreter and compiler use ! // some assembly copies of this code. Make sure update those code ! // if the following function is changed. The implementation is ! // extremely sensitive to race condition. Be careful. ! void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, ! bool attempt_rebias, TRAPS) { if (UseBiasedLocking) { if (!SafepointSynchronize::is_at_safepoint()) { ! BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD); ! if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) { ! return; ! } } else { - assert(!attempt_rebias, "can not rebias toward VM thread"); BiasedLocking::revoke_at_safepoint(obj); } - assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } ! slow_enter(obj, lock, THREAD); } ! void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) { markWord mark = object->mark(); // We cannot check for Biased Locking if we are racing an inflation. assert(mark == markWord::INFLATING() || !mark.has_bias_pattern(), "should not see bias pattern here"); --- 255,306 ---- return false; // revert to slow-path } // ----------------------------------------------------------------------------- ! // Monitor Enter/Exit ! // The interpreter and compiler use some assembly copies of this code. Make sure ! // update those code if the following function is changed. The implementation ! // is extremely sensitive to race condition. Be careful. ! void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) { if (UseBiasedLocking) { if (!SafepointSynchronize::is_at_safepoint()) { ! BiasedLocking::revoke(obj, THREAD); } else { BiasedLocking::revoke_at_safepoint(obj); } } ! markWord mark = obj->mark(); ! assert(!mark.has_bias_pattern(), "should not see bias pattern here"); ! ! if (mark.is_neutral()) { ! // Anticipate successful CAS -- the ST of the displaced mark must ! // be visible <= the ST performed by the CAS. ! lock->set_displaced_header(mark); ! if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) { ! return; ! } ! // Fall through to inflate() ... ! } else if (mark.has_locker() && ! THREAD->is_lock_owned((address)mark.locker())) { ! assert(lock != mark.locker(), "must not re-lock the same lock"); ! assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock"); ! lock->set_displaced_header(markWord::from_pointer(NULL)); ! return; ! } ! ! // The object header will never be displaced to this lock, ! // so it does not matter what the value is, except that it ! // must be non-zero to avoid looking like a re-entrant lock, ! // and must not look locked either. ! lock->set_displaced_header(markWord::unused_mark()); ! inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD); } ! void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) { markWord mark = object->mark(); // We cannot check for Biased Locking if we are racing an inflation. assert(mark == markWord::INFLATING() || !mark.has_bias_pattern(), "should not see bias pattern here");
*** 329,379 **** // We have to take the slow-path of possible inflation and then exit. inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD); } // ----------------------------------------------------------------------------- - // Interpreter/Compiler Slow Case - // This routine is used to handle interpreter/compiler slow case - // We don't need to use fast path here, because it must have been - // failed in the interpreter/compiler code. - void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) { - markWord mark = obj->mark(); - assert(!mark.has_bias_pattern(), "should not see bias pattern here"); - - if (mark.is_neutral()) { - // Anticipate successful CAS -- the ST of the displaced mark must - // be visible <= the ST performed by the CAS. - lock->set_displaced_header(mark); - if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) { - return; - } - // Fall through to inflate() ... - } else if (mark.has_locker() && - THREAD->is_lock_owned((address)mark.locker())) { - assert(lock != mark.locker(), "must not re-lock the same lock"); - assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock"); - lock->set_displaced_header(markWord::from_pointer(NULL)); - return; - } - - // The object header will never be displaced to this lock, - // so it does not matter what the value is, except that it - // must be non-zero to avoid looking like a re-entrant lock, - // and must not look locked either. - lock->set_displaced_header(markWord::unused_mark()); - inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD); - } - - // This routine is used to handle interpreter/compiler slow case - // We don't need to use fast path here, because it must have - // failed in the interpreter/compiler code. Simply use the heavy - // weight monitor should be ok, unless someone find otherwise. - void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) { - fast_exit(object, lock, THREAD); - } - - // ----------------------------------------------------------------------------- // Class Loader support to workaround deadlocks on the class loader lock objects // Also used by GC // complete_exit()/reenter() are used to wait on a nested lock // i.e. to give up an outer lock completely and then re-enter // Used when holding nested locks - lock acquisition order: lock1 then lock2 --- 346,355 ----
*** 383,393 **** // 4) reenter lock1 with original recursion count // 5) lock lock2 // NOTE: must use heavy weight monitor to handle complete_exit/reenter() intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal); --- 359,369 ---- // 4) reenter lock1 with original recursion count // 5) lock lock2 // NOTE: must use heavy weight monitor to handle complete_exit/reenter() intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
*** 395,405 **** } // NOTE: must use heavy weight monitor to handle complete_exit/reenter() void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal); --- 371,381 ---- } // NOTE: must use heavy weight monitor to handle complete_exit/reenter() void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
*** 409,419 **** // JNI locks on java objects // NOTE: must use heavy weight monitor to handle jni monitor enter void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { // the current locking is from JNI instead of Java code if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } THREAD->set_current_pending_monitor_is_from_java(false); inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD); THREAD->set_current_pending_monitor_is_from_java(true); --- 385,395 ---- // JNI locks on java objects // NOTE: must use heavy weight monitor to handle jni monitor enter void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { // the current locking is from JNI instead of Java code if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } THREAD->set_current_pending_monitor_is_from_java(false); inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD); THREAD->set_current_pending_monitor_is_from_java(true);
*** 421,431 **** // NOTE: must use heavy weight monitor to handle jni monitor exit void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) { if (UseBiasedLocking) { Handle h_obj(THREAD, obj); ! BiasedLocking::revoke_and_rebias(h_obj, false, THREAD); obj = h_obj(); } assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit); --- 397,407 ---- // NOTE: must use heavy weight monitor to handle jni monitor exit void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) { if (UseBiasedLocking) { Handle h_obj(THREAD, obj); ! BiasedLocking::revoke(h_obj, THREAD); obj = h_obj(); } assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
*** 445,471 **** _thread = thread; _thread->check_for_valid_safepoint_state(false); _obj = obj; if (_dolock) { ! ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread); } } ObjectLocker::~ObjectLocker() { if (_dolock) { ! ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread); } } // ----------------------------------------------------------------------------- // Wait/Notify/NotifyAll // NOTE: must use heavy weight monitor to handle wait() int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } --- 421,447 ---- _thread = thread; _thread->check_for_valid_safepoint_state(false); _obj = obj; if (_dolock) { ! ObjectSynchronizer::enter(_obj, &_lock, _thread); } } ObjectLocker::~ObjectLocker() { if (_dolock) { ! ObjectSynchronizer::exit(_obj(), &_lock, _thread); } } // ----------------------------------------------------------------------------- // Wait/Notify/NotifyAll // NOTE: must use heavy weight monitor to handle wait() int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); }
*** 481,502 **** return dtrace_waited_probe(monitor, obj, THREAD); } void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } inflate(THREAD, obj(), inflate_cause_wait)->wait(millis, false, THREAD); } void ObjectSynchronizer::notify(Handle obj, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } markWord mark = obj->mark(); if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) { --- 457,478 ---- return dtrace_waited_probe(monitor, obj, THREAD); } void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } if (millis < 0) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } inflate(THREAD, obj(), inflate_cause_wait)->wait(millis, false, THREAD); } void ObjectSynchronizer::notify(Handle obj, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } markWord mark = obj->mark(); if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
*** 506,516 **** } // NOTE: see comment of notify() void ObjectSynchronizer::notifyall(Handle obj, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(obj, false, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } markWord mark = obj->mark(); if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) { --- 482,492 ---- } // NOTE: see comment of notify() void ObjectSynchronizer::notifyall(Handle obj, TRAPS) { if (UseBiasedLocking) { ! BiasedLocking::revoke(obj, THREAD); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } markWord mark = obj->mark(); if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
*** 693,703 **** Handle hobj(Self, obj); // Relaxing assertion for bug 6320749. assert(Universe::verify_in_progress() || !SafepointSynchronize::is_at_safepoint(), "biases should not be seen by VM thread here"); ! BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current()); obj = hobj(); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } } --- 669,679 ---- Handle hobj(Self, obj); // Relaxing assertion for bug 6320749. assert(Universe::verify_in_progress() || !SafepointSynchronize::is_at_safepoint(), "biases should not be seen by VM thread here"); ! BiasedLocking::revoke(hobj, JavaThread::current()); obj = hobj(); assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now"); } }
*** 792,802 **** bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread, Handle h_obj) { if (UseBiasedLocking) { ! BiasedLocking::revoke_and_rebias(h_obj, false, thread); assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now"); } assert(thread == JavaThread::current(), "Can only be called on current thread"); oop obj = h_obj(); --- 768,778 ---- bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread, Handle h_obj) { if (UseBiasedLocking) { ! BiasedLocking::revoke(h_obj, thread); assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now"); } assert(thread == JavaThread::current(), "Can only be called on current thread"); oop obj = h_obj();
*** 831,841 **** // Possible mark states: neutral, biased, stack-locked, inflated if (UseBiasedLocking && h_obj()->mark().has_bias_pattern()) { // CASE: biased ! BiasedLocking::revoke_and_rebias(h_obj, false, self); assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now"); } assert(self == JavaThread::current(), "Can only be called on current thread"); --- 807,817 ---- // Possible mark states: neutral, biased, stack-locked, inflated if (UseBiasedLocking && h_obj()->mark().has_bias_pattern()) { // CASE: biased ! BiasedLocking::revoke(h_obj, self); assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now"); } assert(self == JavaThread::current(), "Can only be called on current thread");
*** 867,877 **** JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) { if (UseBiasedLocking) { if (SafepointSynchronize::is_at_safepoint()) { BiasedLocking::revoke_at_safepoint(h_obj); } else { ! BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current()); } assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now"); } oop obj = h_obj(); --- 843,853 ---- JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) { if (UseBiasedLocking) { if (SafepointSynchronize::is_at_safepoint()) { BiasedLocking::revoke_at_safepoint(h_obj); } else { ! BiasedLocking::revoke(h_obj, JavaThread::current()); } assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now"); } oop obj = h_obj();
*** 1461,1472 **** // If we know we're inflating for entry it's better to inflate by swinging a // pre-locked objectMonitor pointer into the object header. A successful // CAS inflates the object *and* confers ownership to the inflating thread. // In the current implementation we use a 2-step mechanism where we CAS() // to inflate and then CAS() again to try to swing _owner from NULL to Self. ! // An inflateTry() method that we could call from fast_enter() and slow_enter() ! // would be useful. // Catch if the object's header is not neutral (not locked and // not marked is what we care about here). assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); ObjectMonitor * m = omAlloc(Self); --- 1437,1447 ---- // If we know we're inflating for entry it's better to inflate by swinging a // pre-locked objectMonitor pointer into the object header. A successful // CAS inflates the object *and* confers ownership to the inflating thread. // In the current implementation we use a 2-step mechanism where we CAS() // to inflate and then CAS() again to try to swing _owner from NULL to Self. ! // An inflateTry() method that we could call from enter() would be useful. // Catch if the object's header is not neutral (not locked and // not marked is what we care about here). assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); ObjectMonitor * m = omAlloc(Self);
< prev index next >