Index: runtime/vm/malloc_hooks.cc |
diff --git a/runtime/vm/malloc_hooks.cc b/runtime/vm/malloc_hooks.cc |
index 4f7de9e20d70b8b4c0326e5d47d996f0496ea5dc..a85d22e85f306300ee3b7f499290bd4a7f3f7846 100644 |
--- a/runtime/vm/malloc_hooks.cc |
+++ b/runtime/vm/malloc_hooks.cc |
@@ -13,60 +13,33 @@ |
#include "platform/assert.h" |
#include "vm/hash_map.h" |
#include "vm/json_stream.h" |
-#include "vm/lockers.h" |
+#include "vm/os_thread.h" |
namespace dart { |
-// A locker-type class to automatically grab and release the |
-// in_malloc_hook_flag_. |
-class MallocHookScope { |
+// A locker-type class similar to MutexLocker which tracks which thread |
+// currently holds the lock. We use this instead of MutexLocker and |
+// mutex->IsOwnedByCurrentThread() since IsOwnedByCurrentThread() is only |
+// enabled for debug mode. |
+class MallocLocker : public ValueObject { |
public: |
- static void InitMallocHookFlag() { |
- MutexLocker ml(malloc_hook_scope_mutex_); |
- ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey); |
- in_malloc_hook_flag_ = OSThread::CreateThreadLocal(); |
- OSThread::SetThreadLocal(in_malloc_hook_flag_, 0); |
+ explicit MallocLocker(Mutex* mutex, ThreadId* owner) |
+ : mutex_(mutex), owner_(owner) { |
+ ASSERT(owner != NULL); |
+ mutex_->Lock(); |
+ ASSERT(*owner_ == OSThread::kInvalidThreadId); |
+ *owner_ = OSThread::GetCurrentThreadId(); |
} |
- static void DestroyMallocHookFlag() { |
- MutexLocker ml(malloc_hook_scope_mutex_); |
- ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); |
- OSThread::DeleteThreadLocal(in_malloc_hook_flag_); |
- in_malloc_hook_flag_ = kUnsetThreadLocalKey; |
- } |
- |
- MallocHookScope() { |
- MutexLocker ml(malloc_hook_scope_mutex_); |
- ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); |
- OSThread::SetThreadLocal(in_malloc_hook_flag_, 1); |
- } |
- |
- ~MallocHookScope() { |
- MutexLocker ml(malloc_hook_scope_mutex_); |
- ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); |
- OSThread::SetThreadLocal(in_malloc_hook_flag_, 0); |
- } |
- |
- static bool IsInHook() { |
- MutexLocker ml(malloc_hook_scope_mutex_); |
- if (in_malloc_hook_flag_ == kUnsetThreadLocalKey) { |
- // Bail out if the malloc hook flag is invalid. This means that |
- // MallocHookState::TearDown() has been called and MallocHookScope is no |
- // longer intitialized. Don't worry if MallocHookState::TearDown() is |
- // called before the hooks grab the mutex, since |
- // MallocHooksState::Active() is checked after the lock is taken before |
- // proceeding to act on the allocation/free. |
- return false; |
- } |
- return OSThread::GetThreadLocal(in_malloc_hook_flag_); |
+ virtual ~MallocLocker() { |
+ ASSERT(*owner_ == OSThread::GetCurrentThreadId()); |
+ *owner_ = OSThread::kInvalidThreadId; |
+ mutex_->Unlock(); |
} |
private: |
- static Mutex* malloc_hook_scope_mutex_; |
- static ThreadLocalKey in_malloc_hook_flag_; |
- |
- DISALLOW_ALLOCATION(); |
- DISALLOW_COPY_AND_ASSIGN(MallocHookScope); |
+ Mutex* mutex_; |
+ ThreadId* owner_; |
}; |
@@ -135,6 +108,12 @@ class MallocHooksState : public AllStatic { |
} |
static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; } |
+ static ThreadId* malloc_hook_mutex_owner() { |
+ return &malloc_hook_mutex_owner_; |
+ } |
+ static bool IsLockHeldByCurrentThread() { |
+ return (malloc_hook_mutex_owner_ == OSThread::GetCurrentThreadId()); |
+ } |
static intptr_t allocation_count() { return allocation_count_; } |
@@ -179,6 +158,7 @@ class MallocHooksState : public AllStatic { |
static bool active_; |
static intptr_t original_pid_; |
static Mutex* malloc_hook_mutex_; |
+ static ThreadId malloc_hook_mutex_owner_; |
static intptr_t allocation_count_; |
static intptr_t heap_allocated_memory_in_bytes_; |
static AddressMap* address_map_; |
@@ -187,14 +167,12 @@ class MallocHooksState : public AllStatic { |
}; |
-// MallocHookScope state. |
-Mutex* MallocHookScope::malloc_hook_scope_mutex_ = new Mutex(); |
-ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey; |
- |
// MallocHooks state / locks. |
bool MallocHooksState::active_ = false; |
intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid; |
Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex(); |
+ThreadId MallocHooksState::malloc_hook_mutex_owner_ = |
+ OSThread::kInvalidThreadId; |
// Memory allocation state information. |
intptr_t MallocHooksState::allocation_count_ = 0; |
@@ -206,10 +184,10 @@ void MallocHooks::InitOnce() { |
if (!FLAG_enable_malloc_hooks) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
ASSERT(!MallocHooksState::Active()); |
- MallocHookScope::InitMallocHookFlag(); |
MallocHooksState::Init(); |
// Register malloc hooks. |
@@ -225,7 +203,8 @@ void MallocHooks::TearDown() { |
if (!FLAG_enable_malloc_hooks) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
ASSERT(MallocHooksState::Active()); |
// Remove malloc hooks. |
@@ -236,7 +215,6 @@ void MallocHooks::TearDown() { |
ASSERT(success); |
MallocHooksState::TearDown(); |
- MallocHookScope::DestroyMallocHookFlag(); |
} |
@@ -244,7 +222,8 @@ void MallocHooks::ResetStats() { |
if (!FLAG_enable_malloc_hooks) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
if (MallocHooksState::Active()) { |
MallocHooksState::ResetStats(); |
} |
@@ -271,7 +250,8 @@ void MallocHooks::PrintToJSONObject(JSONObject* jsobj) { |
// to acquire the lock recursively so we extract the values first |
// and then add the JSON properties. |
{ |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
if (Active()) { |
allocated_memory = MallocHooksState::heap_allocated_memory_in_bytes(); |
allocation_count = MallocHooksState::allocation_count(); |
@@ -289,7 +269,8 @@ intptr_t MallocHooks::allocation_count() { |
if (!FLAG_enable_malloc_hooks) { |
return 0; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
return MallocHooksState::allocation_count(); |
} |
@@ -298,22 +279,22 @@ intptr_t MallocHooks::heap_allocated_memory_in_bytes() { |
if (!FLAG_enable_malloc_hooks) { |
return 0; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
return MallocHooksState::heap_allocated_memory_in_bytes(); |
} |
void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { |
- if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { |
+ if (MallocHooksState::IsLockHeldByCurrentThread() || |
+ !MallocHooksState::IsOriginalProcess()) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
// Now that we hold the lock, check to make sure everything is still active. |
if ((ptr != NULL) && MallocHooksState::Active()) { |
- // Set the malloc hook flag to avoid calling hooks again if memory is |
- // allocated/freed below. |
- MallocHookScope mhs; |
MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); |
MallocHooksState::address_map()->Insert(ptr, size); |
} |
@@ -321,16 +302,15 @@ void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { |
void MallocHooksState::RecordFreeHook(const void* ptr) { |
- if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { |
+ if (MallocHooksState::IsLockHeldByCurrentThread() || |
+ !MallocHooksState::IsOriginalProcess()) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
+ MallocHooksState::malloc_hook_mutex_owner()); |
// Now that we hold the lock, check to make sure everything is still active. |
if ((ptr != NULL) && MallocHooksState::Active()) { |
- // Set the malloc hook flag to avoid calling hooks again if memory is |
- // allocated/freed below. |
- MallocHookScope mhs; |
intptr_t size = 0; |
if (MallocHooksState::address_map()->Lookup(ptr, &size)) { |
MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size); |