< prev index next > src/hotspot/share/code/nmethodBarrier.cpp
Concurrent class unloading
#include "gc/shared/barrierSet.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/spinYield.hpp"
bool nmethodBarrierState::is_safe() const {
- CounterUnion twin_value;
- twin_value._value = Atomic::load(&_state);
- return twin_value._counters._lock > 0;
+ return Thread::current()->in_nmethod_entry_barrier();
}
bool nmethodBarrierState::enter() {
while (true) {
CounterUnion old;
CounterUnion next;
next._value = old._value;
int disarmed_value = nmethodBarrier::disarmed_value();
+ assert(disarmed_value != 0, "sanity");
+
if (old._counters._epoch != disarmed_value) {
next._counters._epoch = disarmed_value;
next._counters._lock = 1;
} else if (old._counters._lock == 0) {
return false;
} else {
++next._counters._lock;
}
assert(next._counters._lock > 0, "check");
+ assert(next._counters._epoch == nmethodBarrier::disarmed_value(), "sanity");
if (Atomic::cmpxchg(next._value, &_state, old._value) == old._value) {
+ Thread::current()->set_is_in_nmethod_entry_barrier(true);
return true;
}
}
}
CounterUnion next;
next._value = old._value;
--next._counters._lock;
+ assert(old._counters._epoch == nmethodBarrier::disarmed_value(), "sanity");
+ assert(old._counters._lock > 0, "check");
+ assert(next._counters._lock >= 0, "check");
+
if (Atomic::cmpxchg(next._value, &_state, old._value) == old._value) {
+ Thread::current()->set_is_in_nmethod_entry_barrier(false);
return;
}
}
}
nmethod* nm = cb->as_nmethod();
nmethodBarrier nmbarrier(nm, return_address_ptr);
return bs->on_nmethod_entry_barrier(nm, &nmbarrier) ? 0 : 1;
}
-void nmethodBarrier::initialize(nmethod* nm) {
- BarrierSet* bs = BarrierSet::barrier_set();
- if (bs->needs_nmethod_entry_barrier()) {
- nm->disarm_barrier();
- }
-}
-
void nmethodBarrier::disarm() {
_nm->disarm_barrier();
// multiple threads can enter the barrier at the same time while armed
// one can finish and decide that the barrier can be disarmed, in the meantime the other
// have made the same decision continued on and deoptimized on something else.
assert(!_is_deoptimized, "can only disarm methods that didn't deoptimize!");
}
int nmethodBarrier::disarmed_value() {
BarrierSet* bs = BarrierSet::barrier_set();
+ int value = bs->nmethod_entry_barrier_state();
+#ifdef ASSERT
Thread* thread = Thread::current();
- int* state_addr = reinterpret_cast<int*>(reinterpret_cast<char*>(thread) +
- in_bytes(bs->nmethod_entry_barrier_state_thread_offset()));
- return *state_addr;
+ if (thread->is_Java_thread()) {
+ int* state_addr = reinterpret_cast<int*>(reinterpret_cast<char*>(thread) +
+ in_bytes(bs->nmethod_entry_barrier_state_thread_offset()));
+ assert(*state_addr == value, "global and local values out of sync");
+ }
+#endif
+ return value;
}
< prev index next >