Index: runtime/vm/malloc_hooks.cc |
diff --git a/runtime/vm/malloc_hooks.cc b/runtime/vm/malloc_hooks.cc |
index 4f7de9e20d70b8b4c0326e5d47d996f0496ea5dc..5425a2e2393390144baeda4b242b8421b696c174 100644 |
--- a/runtime/vm/malloc_hooks.cc |
+++ b/runtime/vm/malloc_hooks.cc |
@@ -13,60 +13,37 @@ |
#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 { |
zra
2017/02/22 22:54:54
This seems generally useful. Should it go in os_th
bkonyi
2017/02/22 23:04:26
In its current state, I don't think that would wor
siva
2017/02/22 23:53:04
Discussed offline with Zach, For this CL we leave
bkonyi
2017/02/23 00:28:46
That makes sense to me.
|
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) : mutex_(mutex) { |
+ 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; |
+ virtual ~MallocLocker() { |
+ ASSERT(IsOwnedByCurrentThread()); |
+ owner_ = OSThread::kInvalidThreadId; |
+ mutex_->Unlock(); |
} |
- 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_); |
+ static bool IsOwnedByCurrentThread() { |
+ return (owner_ == OSThread::GetCurrentThreadId()); |
} |
private: |
- static Mutex* malloc_hook_scope_mutex_; |
- static ThreadLocalKey in_malloc_hook_flag_; |
+ Mutex* mutex_; |
+ static ThreadId owner_; |
- DISALLOW_ALLOCATION(); |
- DISALLOW_COPY_AND_ASSIGN(MallocHookScope); |
+ DISALLOW_COPY_AND_ASSIGN(MallocLocker); |
zra
2017/02/22 22:54:54
Is this redundant if this is inheriting from Value
bkonyi
2017/02/22 23:04:26
Looks like it is. I had based MallocLocker on Mute
bkonyi
2017/02/23 00:28:46
Done.
|
}; |
@@ -187,9 +164,8 @@ class MallocHooksState : public AllStatic { |
}; |
-// MallocHookScope state. |
-Mutex* MallocHookScope::malloc_hook_scope_mutex_ = new Mutex(); |
-ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey; |
+// MallocLocker state. |
+ThreadId MallocLocker::owner_ = OSThread::kInvalidThreadId; |
siva
2017/02/22 23:53:04
Shouldn't this be clubbed just below the line :
Mu
bkonyi
2017/02/23 00:28:46
Done.
|
// MallocHooks state / locks. |
bool MallocHooksState::active_ = false; |
@@ -206,10 +182,9 @@ void MallocHooks::InitOnce() { |
if (!FLAG_enable_malloc_hooks) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex()); |
ASSERT(!MallocHooksState::Active()); |
- MallocHookScope::InitMallocHookFlag(); |
MallocHooksState::Init(); |
// Register malloc hooks. |
@@ -225,7 +200,7 @@ void MallocHooks::TearDown() { |
if (!FLAG_enable_malloc_hooks) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex()); |
ASSERT(MallocHooksState::Active()); |
// Remove malloc hooks. |
@@ -236,7 +211,6 @@ void MallocHooks::TearDown() { |
ASSERT(success); |
MallocHooksState::TearDown(); |
- MallocHookScope::DestroyMallocHookFlag(); |
} |
@@ -244,7 +218,7 @@ void MallocHooks::ResetStats() { |
if (!FLAG_enable_malloc_hooks) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex()); |
if (MallocHooksState::Active()) { |
MallocHooksState::ResetStats(); |
} |
@@ -271,7 +245,7 @@ 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()); |
if (Active()) { |
allocated_memory = MallocHooksState::heap_allocated_memory_in_bytes(); |
allocation_count = MallocHooksState::allocation_count(); |
@@ -289,7 +263,7 @@ intptr_t MallocHooks::allocation_count() { |
if (!FLAG_enable_malloc_hooks) { |
return 0; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex()); |
return MallocHooksState::allocation_count(); |
} |
@@ -298,22 +272,20 @@ 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()); |
return MallocHooksState::heap_allocated_memory_in_bytes(); |
} |
void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { |
- if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { |
+ if (MallocLocker::IsOwnedByCurrentThread() || |
+ !MallocHooksState::IsOriginalProcess()) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex()); |
// 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 +293,14 @@ void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { |
void MallocHooksState::RecordFreeHook(const void* ptr) { |
- if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { |
+ if (MallocLocker::IsOwnedByCurrentThread() || |
+ !MallocHooksState::IsOriginalProcess()) { |
return; |
} |
- MutexLocker ml(MallocHooksState::malloc_hook_mutex()); |
+ MallocLocker ml(MallocHooksState::malloc_hook_mutex()); |
// 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); |