Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(494)

Side by Side Diff: runtime/vm/malloc_hooks.cc

Issue 2701013002: Resolution for issue #28746: changed order in which locks/flags are grabbed in MallocHooks to preve… (Closed)
Patch Set: Resolution for issue #28746: changed order in which locks/flags are grabbed in MallocHooks to preve… Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 6
7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) 7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
8 8
9 #include "vm/malloc_hooks.h" 9 #include "vm/malloc_hooks.h"
10 10
11 #include "gperftools/malloc_hook.h" 11 #include "gperftools/malloc_hook.h"
12 12
13 #include "platform/assert.h" 13 #include "platform/assert.h"
14 #include "vm/hash_map.h" 14 #include "vm/hash_map.h"
15 #include "vm/json_stream.h" 15 #include "vm/json_stream.h"
16 #include "vm/lockers.h" 16 #include "vm/lockers.h"
17 17
18 namespace dart { 18 namespace dart {
19 19
20 // A locker-type class to automatically grab and release the 20 // A locker-type class to automatically grab and release the
21 // in_malloc_hook_flag_. 21 // in_malloc_hook_flag_.
22 class MallocHookScope { 22 class MallocHookScope {
23 public: 23 public:
24 static void InitMallocHookFlag() { 24 static void InitMallocHookFlag() {
25 MutexLocker ml(malloc_hook_scope_mutex_);
25 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey); 26 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey);
26 in_malloc_hook_flag_ = OSThread::CreateThreadLocal(); 27 in_malloc_hook_flag_ = OSThread::CreateThreadLocal();
27 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0); 28 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
28 } 29 }
29 30
30 static void DestroyMallocHookFlag() { 31 static void DestroyMallocHookFlag() {
32 MutexLocker ml(malloc_hook_scope_mutex_);
31 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); 33 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
32 OSThread::DeleteThreadLocal(in_malloc_hook_flag_); 34 OSThread::DeleteThreadLocal(in_malloc_hook_flag_);
33 in_malloc_hook_flag_ = kUnsetThreadLocalKey; 35 in_malloc_hook_flag_ = kUnsetThreadLocalKey;
34 } 36 }
35 37
36 MallocHookScope() { 38 MallocHookScope() {
39 MutexLocker ml(malloc_hook_scope_mutex_);
37 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); 40 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
38 OSThread::SetThreadLocal(in_malloc_hook_flag_, 1); 41 OSThread::SetThreadLocal(in_malloc_hook_flag_, 1);
39 } 42 }
40 43
41 ~MallocHookScope() { 44 ~MallocHookScope() {
45 MutexLocker ml(malloc_hook_scope_mutex_);
42 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); 46 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
43 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0); 47 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
44 } 48 }
45 49
46 static bool IsInHook() { 50 static bool IsInHook() {
47 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey); 51 MutexLocker ml(malloc_hook_scope_mutex_);
52 if (in_malloc_hook_flag_ == kUnsetThreadLocalKey) {
53 // Bail out if the malloc hook flag is invalid. This means that
54 // MallocHookState::TearDown() has been called and MallocHookScope is no
55 // longer intitialized. Don't worry if MallocHookState::TearDown() is
56 // called before the hooks grab the mutex, since
57 // MallocHooksState::Active() is checked after the lock is taken before
58 // proceeding to act on the allocation/free.
59 return false;
60 }
48 return OSThread::GetThreadLocal(in_malloc_hook_flag_); 61 return OSThread::GetThreadLocal(in_malloc_hook_flag_);
49 } 62 }
50 63
51 private: 64 private:
65 static Mutex* malloc_hook_scope_mutex_;
52 static ThreadLocalKey in_malloc_hook_flag_; 66 static ThreadLocalKey in_malloc_hook_flag_;
53 67
54 DISALLOW_ALLOCATION(); 68 DISALLOW_ALLOCATION();
55 DISALLOW_COPY_AND_ASSIGN(MallocHookScope); 69 DISALLOW_COPY_AND_ASSIGN(MallocHookScope);
56 }; 70 };
57 71
58 72
59 // Custom key/value trait specifically for address/size pairs. Unlike 73 // Custom key/value trait specifically for address/size pairs. Unlike
60 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry. 74 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry.
61 class AddressKeyValueTrait { 75 class AddressKeyValueTrait {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 static intptr_t original_pid_; 180 static intptr_t original_pid_;
167 static Mutex* malloc_hook_mutex_; 181 static Mutex* malloc_hook_mutex_;
168 static intptr_t allocation_count_; 182 static intptr_t allocation_count_;
169 static intptr_t heap_allocated_memory_in_bytes_; 183 static intptr_t heap_allocated_memory_in_bytes_;
170 static AddressMap* address_map_; 184 static AddressMap* address_map_;
171 185
172 static const intptr_t kInvalidPid = -1; 186 static const intptr_t kInvalidPid = -1;
173 }; 187 };
174 188
175 189
190 // MallocHookScope state.
191 Mutex* MallocHookScope::malloc_hook_scope_mutex_ = new Mutex();
192 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
193
176 // MallocHooks state / locks. 194 // MallocHooks state / locks.
177 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
178 bool MallocHooksState::active_ = false; 195 bool MallocHooksState::active_ = false;
179 intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid; 196 intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid;
180 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex(); 197 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex();
181 198
182 // Memory allocation state information. 199 // Memory allocation state information.
183 intptr_t MallocHooksState::allocation_count_ = 0; 200 intptr_t MallocHooksState::allocation_count_ = 0;
184 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0; 201 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0;
185 AddressMap* MallocHooksState::address_map_ = NULL; 202 AddressMap* MallocHooksState::address_map_ = NULL;
186 203
187 204
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 280 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
264 return MallocHooksState::heap_allocated_memory_in_bytes(); 281 return MallocHooksState::heap_allocated_memory_in_bytes();
265 } 282 }
266 283
267 284
268 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { 285 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) {
269 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { 286 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) {
270 return; 287 return;
271 } 288 }
272 289
273 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
274 // again.
275 MallocHookScope mhs;
276 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 290 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
291 // Now that we hold the lock, check to make sure everything is still active.
277 if ((ptr != NULL) && MallocHooksState::Active()) { 292 if ((ptr != NULL) && MallocHooksState::Active()) {
293 // Set the malloc hook flag to avoid calling hooks again if memory is
294 // allocated/freed below.
295 MallocHookScope mhs;
278 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); 296 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size);
279 MallocHooksState::address_map()->Insert(ptr, size); 297 MallocHooksState::address_map()->Insert(ptr, size);
280 } 298 }
281 } 299 }
282 300
283 301
284 void MallocHooksState::RecordFreeHook(const void* ptr) { 302 void MallocHooksState::RecordFreeHook(const void* ptr) {
285 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { 303 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) {
286 return; 304 return;
287 } 305 }
288 306
289 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
290 // again.
291 MallocHookScope mhs;
292 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 307 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
308 // Now that we hold the lock, check to make sure everything is still active.
293 if ((ptr != NULL) && MallocHooksState::Active()) { 309 if ((ptr != NULL) && MallocHooksState::Active()) {
310 // Set the malloc hook flag to avoid calling hooks again if memory is
311 // allocated/freed below.
312 MallocHookScope mhs;
294 intptr_t size = 0; 313 intptr_t size = 0;
295 if (MallocHooksState::address_map()->Lookup(ptr, &size)) { 314 if (MallocHooksState::address_map()->Lookup(ptr, &size)) {
296 MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size); 315 MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size);
297 MallocHooksState::address_map()->Remove(ptr); 316 MallocHooksState::address_map()->Remove(ptr);
298 } 317 }
299 } 318 }
300 } 319 }
301 320
302 } // namespace dart 321 } // namespace dart
303 322
304 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) 323 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698