Mutex* Locks::abort_lock_ = nullptr;
Mutex* Locks::allocated_monitor_ids_lock_ = nullptr;
Mutex* Locks::allocated_thread_ids_lock_ = nullptr;
-Mutex* Locks::breakpoint_lock_ = nullptr;
+ReaderWriterMutex* Locks::breakpoint_lock_ = nullptr;
ReaderWriterMutex* Locks::classlinker_classes_lock_ = nullptr;
ReaderWriterMutex* Locks::heap_bitmap_lock_ = nullptr;
Mutex* Locks::logging_lock_ = nullptr;
UPDATE_CURRENT_LOCK_LEVEL(kBreakpointLock);
DCHECK(breakpoint_lock_ == nullptr);
- breakpoint_lock_ = new Mutex("breakpoint lock", current_lock_level);
+ breakpoint_lock_ = new ReaderWriterMutex("breakpoint lock", current_lock_level);
UPDATE_CURRENT_LOCK_LEVEL(kClassLinkerClassesLock);
DCHECK(classlinker_classes_lock_ == nullptr);
static Mutex* thread_list_lock_ ACQUIRED_AFTER(trace_lock_);
// Guards breakpoints.
- static Mutex* breakpoint_lock_ ACQUIRED_AFTER(thread_list_lock_);
+ static ReaderWriterMutex* breakpoint_lock_ ACQUIRED_AFTER(thread_list_lock_);
// Guards lists of classes within the class linker.
static ReaderWriterMutex* classlinker_classes_lock_ ACQUIRED_AFTER(breakpoint_lock_);
bool need_full_deoptimization_;
};
-static std::ostream& operator<<(std::ostream& os, Breakpoint& rhs)
+static std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
os << StringPrintf("Breakpoint[%s @%#x]", PrettyMethod(rhs.Method()).c_str(), rhs.DexPc());
return os;
static bool IsBreakpoint(const mirror::ArtMethod* m, uint32_t dex_pc)
LOCKS_EXCLUDED(Locks::breakpoint_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
if (gBreakpoints[i].DexPc() == dex_pc && gBreakpoints[i].Method() == m) {
VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i];
{
// TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected?
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
CHECK_EQ(gBreakpoints.size(), 0U);
}
}
static const Breakpoint* FindFirstBreakpointForMethod(mirror::ArtMethod* m)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::breakpoint_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
for (Breakpoint& breakpoint : gBreakpoints) {
if (breakpoint.Method() == m) {
return &breakpoint;
// Sanity checks all existing breakpoints on the same method.
static void SanityCheckExistingBreakpoints(mirror::ArtMethod* m, bool need_full_deoptimization)
- EXCLUSIVE_LOCKS_REQUIRED(Locks::breakpoint_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
if (kIsDebugBuild) {
for (const Breakpoint& breakpoint : gBreakpoints) {
CHECK_EQ(need_full_deoptimization, breakpoint.NeedFullDeoptimization());
mirror::ArtMethod* m = FromMethodId(location->method_id);
DCHECK(m != nullptr) << "No method for method id " << location->method_id;
- MutexLock mu(self, *Locks::breakpoint_lock_);
+ WriterMutexLock mu(self, *Locks::breakpoint_lock_);
const Breakpoint* const existing_breakpoint = FindFirstBreakpointForMethod(m);
bool need_full_deoptimization;
if (existing_breakpoint == nullptr) {
// Uninstalls a breakpoint at the specified location. Also indicates through the deoptimization
// request if we need to undeoptimize.
void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
- MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
+ WriterMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
mirror::ArtMethod* m = FromMethodId(location->method_id);
DCHECK(m != nullptr) << "No method for method id " << location->method_id;
bool need_full_deoptimization = false;
EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
- InterpreterHandlerTable GetInterpreterHandlerTable() const {
+ InterpreterHandlerTable GetInterpreterHandlerTable() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return interpreter_handler_table_;
}
return instrumentation_stubs_installed_;
}
- bool HasMethodEntryListeners() const {
+ bool HasMethodEntryListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_method_entry_listeners_;
}
- bool HasMethodExitListeners() const {
+ bool HasMethodExitListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_method_exit_listeners_;
}
- bool HasDexPcListeners() const {
+ bool HasDexPcListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_dex_pc_listeners_;
}
- bool HasFieldReadListeners() const {
+ bool HasFieldReadListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_field_read_listeners_;
}
- bool HasFieldWriteListeners() const {
+ bool HasFieldWriteListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_field_write_listeners_;
}
- bool HasExceptionCaughtListeners() const {
+ bool HasExceptionCaughtListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_exception_caught_listeners_;
}
- bool IsActive() const {
+ bool IsActive() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return have_dex_pc_listeners_ || have_method_entry_listeners_ || have_method_exit_listeners_ ||
have_field_read_listeners_ || have_field_write_listeners_ ||
have_exception_caught_listeners_ || have_method_unwind_listeners_;
LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_,
deoptimized_methods_lock_);
- void UpdateInterpreterHandlerTable() {
+ void UpdateInterpreterHandlerTable() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
interpreter_handler_table_ = IsActive() ? kAlternativeHandlerTable : kMainHandlerTable;
}
// Do we have any listeners for method entry events? Short-cut to avoid taking the
// instrumentation_lock_.
- bool have_method_entry_listeners_;
+ bool have_method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Do we have any listeners for method exit events? Short-cut to avoid taking the
// instrumentation_lock_.
- bool have_method_exit_listeners_;
+ bool have_method_exit_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Do we have any listeners for method unwind events? Short-cut to avoid taking the
// instrumentation_lock_.
- bool have_method_unwind_listeners_;
+ bool have_method_unwind_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Do we have any listeners for dex move events? Short-cut to avoid taking the
// instrumentation_lock_.
- bool have_dex_pc_listeners_;
+ bool have_dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Do we have any listeners for field read events? Short-cut to avoid taking the
// instrumentation_lock_.
- bool have_field_read_listeners_;
+ bool have_field_read_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Do we have any listeners for field write events? Short-cut to avoid taking the
// instrumentation_lock_.
- bool have_field_write_listeners_;
+ bool have_field_write_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Do we have any exception caught listeners? Short-cut to avoid taking the instrumentation_lock_.
- bool have_exception_caught_listeners_;
+ bool have_exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
// The event listeners, written to with the mutator_lock_ exclusively held.
std::list<InstrumentationListener*> method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
// Current interpreter handler table. This is updated each time the thread state flags are
// modified.
- InterpreterHandlerTable interpreter_handler_table_;
+ InterpreterHandlerTable interpreter_handler_table_ GUARDED_BY(Locks::mutator_lock_);
// Greater than 0 if quick alloc entry points instrumented.
// TODO: The access and changes to this is racy and should be guarded by a lock.
#endif
AssertThreadsAreSuspended(self, self, debug_thread);
- VLOG(threads) << *self << " SuspendAll complete";
+ VLOG(threads) << *self << " SuspendAllForDebugger complete";
}
void ThreadList::SuspendSelfForDebugger() {