Index: base/allocator/malloc_zone_functions_mac.cc |
diff --git a/base/allocator/malloc_zone_functions_mac.cc b/base/allocator/malloc_zone_functions_mac.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4277ee8a571e2e116e4793fef270cb2dc86bee54 |
--- /dev/null |
+++ b/base/allocator/malloc_zone_functions_mac.cc |
@@ -0,0 +1,101 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/allocator/malloc_zone_functions_mac.h" |
+ |
+#include "base/atomicops.h" |
+#include "base/synchronization/lock.h" |
+ |
+namespace base { |
+namespace allocator { |
+ |
+MallocZoneFunctions g_malloc_zones[kMaxZoneCount]; |
+MallocZoneFunctions::MallocZoneFunctions() {} |
+ |
+void StoreZoneFunctions(ChromeMallocZone* zone, |
+ MallocZoneFunctions* functions) { |
+ functions->malloc = zone->malloc; |
+ functions->calloc = zone->calloc; |
+ functions->valloc = zone->valloc; |
+ functions->free = zone->free; |
+ functions->realloc = zone->realloc; |
+ functions->size = zone->size; |
+ CHECK(functions->malloc && functions->calloc && functions->valloc && |
+ functions->free && functions->realloc && functions->size); |
+ |
+ // These functions might be nullptr. |
+ functions->batch_malloc = zone->batch_malloc; |
+ functions->batch_free = zone->batch_free; |
+ |
+ if (zone->version >= 5) { |
+ // Not all custom malloc zones have a memalign. |
+ functions->memalign = zone->memalign; |
+ } |
+ if (zone->version >= 6) { |
+ // This may be nullptr. |
+ functions->free_definite_size = zone->free_definite_size; |
+ } |
+ |
+ functions->context = zone; |
+} |
+ |
+namespace { |
+ |
+// All modifications to g_malloc_zones are gated behind this lock. |
+// Dispatch to a malloc zone does not need to acquire this lock. |
+base::Lock* GetLock() { |
Primiano Tucci (use gerrit)
2017/02/23 00:40:18
do you really need all this locking here? Isn't ea
erikchen
2017/02/23 01:43:14
Actually, the new Task Scheduler doesn't guarantee
Primiano Tucci (use gerrit)
2017/02/23 11:19:41
Well depends wheteher you use SingleThreadTaskRunn
erikchen
2017/02/23 20:06:44
There's no way to guarantee things happen on a sin
Primiano Tucci (use gerrit)
2017/02/23 21:06:07
ThreadChecker (and SequenceChecker) have zero cost
|
+ static base::Lock* g_lock = new base::Lock; |
+ return g_lock; |
+} |
+ |
+int g_zone_count = 0; |
+bool g_zeroed = false; |
+ |
+bool IsMallocZoneAlreadyStoredLockAcquired(ChromeMallocZone* zone) { |
Primiano Tucci (use gerrit)
2017/02/23 00:40:18
I think the naming pattern in the rest of the code
erikchen
2017/02/23 01:43:14
Done.
|
+ GetLock()->AssertAcquired(); |
+ for (int i = 0; i < g_zone_count; ++i) { |
+ if (g_malloc_zones[i].context == reinterpret_cast<void*>(zone)) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+} // namespace |
+ |
+void StoreMallocZone(ChromeMallocZone* zone) { |
+ base::AutoLock l(*GetLock()); |
+ if (!g_zeroed) { |
+ g_zeroed = true; |
+ memset(g_malloc_zones, 0, sizeof(g_malloc_zones)); |
Primiano Tucci (use gerrit)
2017/02/23 00:40:18
why you need this? global structs and pods are zer
erikchen
2017/02/23 01:43:14
This isn't pod. Notice that MallocZoneFunctions ha
Primiano Tucci (use gerrit)
2017/02/23 11:19:41
Uhm, this means that g_malloc_zones will likely ca
erikchen
2017/02/23 20:06:44
1. Our custom clang module forces us to make a def
Primiano Tucci (use gerrit)
2017/02/23 21:06:07
Alright I see, there seems to be a problem in our
|
+ } |
+ if (IsMallocZoneAlreadyStoredLockAcquired(zone)) |
+ return; |
+ |
+ if (g_zone_count == kMaxZoneCount) |
+ return; |
+ |
+ StoreZoneFunctions(zone, &g_malloc_zones[g_zone_count]); |
+ ++g_zone_count; |
+ base::subtle::MemoryBarrier(); |
Primiano Tucci (use gerrit)
2017/02/23 00:40:18
This memory barrier is not enough in theory and is
erikchen
2017/02/23 01:43:14
Sorry, but I disagree on both points. Comments in
Primiano Tucci (use gerrit)
2017/02/23 11:19:41
No need to be sorry :)
Primiano Tucci (use gerrit)
2017/02/23 17:47:16
Erik and I had a chat offline, summarizing here.
T
|
+} |
+ |
+bool IsMallocZoneAlreadyStored(ChromeMallocZone* zone) { |
+ base::AutoLock l(*GetLock()); |
+ return IsMallocZoneAlreadyStoredLockAcquired(zone); |
+} |
+ |
+int GetMallocZoneCountForTesting() { |
+ base::AutoLock l(*GetLock()); |
+ return g_zone_count; |
+} |
+ |
+void ClearAllMallocZonesForTesting() { |
+ base::AutoLock l(*GetLock()); |
+ memset(g_malloc_zones, 0, sizeof(g_malloc_zones)); |
+ g_zone_count = 0; |
+ g_zeroed = false; |
Primiano Tucci (use gerrit)
2017/02/23 00:40:18
as per the comment above I don't think you need th
erikchen
2017/02/23 01:43:14
removed.
|
+} |
+ |
+} // namespace allocator |
+} // namespace base |