Chromium Code Reviews| Index: runtime/vm/malloc_hooks.cc |
| diff --git a/runtime/vm/malloc_hooks.cc b/runtime/vm/malloc_hooks.cc |
| index 4f7de9e20d70b8b4c0326e5d47d996f0496ea5dc..1804e20c7118409c7b6715565d1ccf82dbc2de1e 100644 |
| --- a/runtime/vm/malloc_hooks.cc |
| +++ b/runtime/vm/malloc_hooks.cc |
| @@ -13,60 +13,35 @@ |
| #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) : 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_; |
| - |
| - DISALLOW_ALLOCATION(); |
| - DISALLOW_COPY_AND_ASSIGN(MallocHookScope); |
| + Mutex* mutex_; |
| + static ThreadId owner_; |
|
siva
2017/02/23 01:46:36
It might be cleaner to not declare this as static
bkonyi
2017/02/23 02:03:27
Done.
|
| }; |
| @@ -187,14 +162,11 @@ 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 MallocLocker::owner_ = OSThread::kInvalidThreadId; |
| // Memory allocation state information. |
| intptr_t MallocHooksState::allocation_count_ = 0; |
| @@ -206,10 +178,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 +196,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 +207,6 @@ void MallocHooks::TearDown() { |
| ASSERT(success); |
| MallocHooksState::TearDown(); |
| - MallocHookScope::DestroyMallocHookFlag(); |
| } |
| @@ -244,7 +214,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 +241,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 +259,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 +268,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 +289,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); |