< prev index next > src/hotspot/share/runtime/synchronizer.cpp
Print this page
// 2) wait on lock2
// 3) when notified on lock2, unlock lock2
// 4) reenter lock1 with original recursion count
// 5) lock lock2
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
+ // NOTE(TSAN): We cannot instrument complete_exit/reenter in ObjectSynchronizer
+ // in a manner similar to wait and waitUninterruptibly, because
+ // (1) recursion count stored by inflated monitor is different from
+ // the absolute recursion count tracked by Tsan, and (2) in the
+ // general case, we cannot merely store Tsan's recursion count
+ // once: we must track it for *each invocation* of complete_exit.
+ // Hence, the best place to instrument for Tsan is at the call site
+ // for complete_exit/reenter. Luckily, there is only one call site.
intx ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
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);
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_lock(THREAD, obj()));
}
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
if (UseBiasedLocking) {
ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
// If this thread has locked the object, exit the monitor. We
// intentionally do not use CHECK here because we must exit the
// monitor even if an exception is pending.
if (monitor->check_owner(THREAD)) {
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_unlock(THREAD, obj));
monitor->exit(true, THREAD);
}
}
// -----------------------------------------------------------------------------
_thread->check_for_valid_safepoint_state();
_obj = obj;
if (_dolock) {
ObjectSynchronizer::enter(_obj, &_lock, _thread);
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_lock(_thread, _obj()));
}
}
ObjectLocker::~ObjectLocker() {
if (_dolock) {
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_unlock(_thread, _obj()));
ObjectSynchronizer::exit(_obj(), &_lock, _thread);
}
}
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_wait);
DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
+
+ TSAN_ONLY(int tsan_rec = 0;)
+ TSAN_RUNTIME_ONLY(
+ tsan_rec = SharedRuntime::tsan_oop_rec_unlock(THREAD, obj());
+ assert(tsan_rec > 0, "tsan: unlocking unlocked mutex");
+ );
+
monitor->wait(millis, true, THREAD);
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_rec_lock(THREAD, obj(), tsan_rec));
+
// This dummy call is in place to get around dtrace bug 6254741. Once
// that's fixed we can uncomment the following line, remove the call
// and change this function back into a "void" func.
// DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
return dtrace_waited_probe(monitor, 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");
}
if (millis < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
! ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_wait);
+ TSAN_ONLY(int tsan_rec;)
+ TSAN_RUNTIME_ONLY(
+ tsan_rec = SharedRuntime::tsan_oop_rec_unlock(THREAD, obj());
+ assert(tsan_rec > 0, "tsan: unlocking unlocked mutex");
+ );
+ monitor->wait(millis, false, THREAD);
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_rec_lock(THREAD, obj(), tsan_rec));
}
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke(obj, THREAD);
public:
ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
void do_monitor(ObjectMonitor* mid) {
if (mid->owner() == THREAD) {
+ // Note well -- this occurs ONLY on thread exit, and is a last ditch
+ // effort to release all locks. Hence, we don't need to record tsan's
+ // recursion count -- it will never be locked again.
+ TSAN_RUNTIME_ONLY(SharedRuntime::tsan_oop_rec_unlock(THREAD, (oop)mid->object()));
(void)mid->complete_exit(CHECK);
}
}
};
< prev index next >