summaryrefslogtreecommitdiff
path: root/src/monitor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/monitor.cc')
-rw-r--r--src/monitor.cc57
1 files changed, 41 insertions, 16 deletions
diff --git a/src/monitor.cc b/src/monitor.cc
index 16298aed86..b9a94590f3 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -24,6 +24,7 @@
#include <time.h>
#include <unistd.h>
+#include "class_linker.h"
#include "mutex.h"
#include "object.h"
#include "stl_util.h"
@@ -120,8 +121,8 @@ Monitor::Monitor(Object* obj)
obj_(obj),
wait_set_(NULL),
lock_("a monitor lock"),
- owner_filename_(NULL),
- owner_line_number_(0) {
+ locking_method_(NULL),
+ locking_pc_(0) {
}
Monitor::~Monitor() {
@@ -197,15 +198,15 @@ void Monitor::Lock(Thread* self) {
uint64_t waitStart, waitEnd;
if (!lock_.TryLock()) {
uint32_t wait_threshold = lock_profiling_threshold_;
- const char* current_owner_filename = NULL;
- uint32_t current_owner_line_number = -1;
+ const Method* current_locking_method = NULL;
+ uint32_t current_locking_pc = 0;
{
ScopedThreadStateChange tsc(self, Thread::kBlocked);
if (wait_threshold != 0) {
waitStart = NanoTime() / 1000;
}
- current_owner_filename = owner_filename_;
- current_owner_line_number = owner_line_number_;
+ current_locking_method = locking_method_;
+ current_locking_pc = locking_pc_;
lock_.Lock();
if (wait_threshold != 0) {
@@ -222,7 +223,11 @@ void Monitor::Lock(Thread* self) {
sample_percent = 100 * wait_ms / wait_threshold;
}
if (sample_percent != 0 && (static_cast<uint32_t>(rand() % 100) < sample_percent)) {
- LogContentionEvent(self, wait_ms, sample_percent, current_owner_filename, current_owner_line_number);
+ const char* current_locking_filename;
+ uint32_t current_locking_line_number;
+ TranslateLocation(current_locking_method, current_locking_pc,
+ current_locking_filename, current_locking_line_number);
+ LogContentionEvent(self, wait_ms, sample_percent, current_locking_filename, current_locking_line_number);
}
}
}
@@ -232,7 +237,8 @@ void Monitor::Lock(Thread* self) {
// When debugging, save the current monitor holder for future
// acquisition failures to use in sampled logging.
if (lock_profiling_threshold_ != 0) {
- self->GetCurrentLocation(owner_filename_, owner_line_number_);
+ locking_method_ = self->GetCurrentMethod();
+ locking_pc_ = self->GetCurrentReturnPc();
}
}
@@ -246,8 +252,8 @@ bool Monitor::Unlock(Thread* self) {
// We own the monitor, so nobody else can be in here.
if (lock_count_ == 0) {
owner_ = NULL;
- owner_filename_ = "unlocked";
- owner_line_number_ = 0;
+ locking_method_ = NULL;
+ locking_pc_ = 0;
lock_.Unlock();
} else {
--lock_count_;
@@ -366,10 +372,10 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThr
int prevLockCount = lock_count_;
lock_count_ = 0;
owner_ = NULL;
- const char* savedFileName = owner_filename_;
- owner_filename_ = NULL;
- uint32_t savedLineNumber = owner_line_number_;
- owner_line_number_ = 0;
+ const Method* savedMethod = locking_method_;
+ locking_method_ = NULL;
+ uint32_t savedPc = locking_pc_;
+ locking_pc_ = 0;
/*
* Update thread status. If the GC wakes up, it'll ignore us, knowing
@@ -435,8 +441,8 @@ done:
*/
owner_ = self;
lock_count_ = prevLockCount;
- owner_filename_ = savedFileName;
- owner_line_number_ = savedLineNumber;
+ locking_method_ = savedMethod;
+ locking_pc_ = savedPc;
RemoveFromWaitSet(self);
/* set self->status back to Thread::kRunnable, and self-suspend if needed */
@@ -810,6 +816,25 @@ void Monitor::DescribeWait(std::ostream& os, const Thread* thread) {
os << "\n";
}
+void Monitor::TranslateLocation(const Method* method, uint32_t pc,
+ const char*& source_file, uint32_t& line_number) const {
+ // If method is null, location is unknown
+ if (method == NULL) {
+ source_file = "unknown";
+ line_number = 0;
+ return;
+ }
+
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Class* c = method->GetDeclaringClass();
+ DexCache* dex_cache = c->GetDexCache();
+ const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
+ const DexFile::ClassDef* class_def = dex_file.FindClassDef(c->GetDescriptor()->ToModifiedUtf8());
+
+ source_file = dex_file.dexGetSourceFile(*class_def);
+ line_number = dex_file.GetLineNumFromPC(method, method->ToDexPC(pc));
+}
+
MonitorList::MonitorList() : lock_("MonitorList lock") {
}