Chromium Code Reviews| 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..d52114e52325ccd6e740ce4ac33798b65ee5f1f5 |
| --- /dev/null |
| +++ b/base/allocator/malloc_zone_functions_mac.cc |
| @@ -0,0 +1,95 @@ |
| +// 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(const 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() { |
|
Mark Mentovai
2017/02/23 02:20:12
I know I told you that I didn’t care which, but no
erikchen
2017/02/23 20:06:44
Done.
|
| + static base::Lock* g_lock = new base::Lock; |
| + return g_lock; |
| +} |
| + |
| +int g_zone_count = 0; |
| + |
| +bool IsMallocZoneAlreadyStoredLocked(ChromeMallocZone* zone) { |
| + 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 (IsMallocZoneAlreadyStoredLocked(zone)) |
| + return; |
| + |
| + if (g_zone_count == kMaxZoneCount) |
| + return; |
| + |
| + StoreZoneFunctions(zone, &g_malloc_zones[g_zone_count]); |
| + ++g_zone_count; |
| + base::subtle::MemoryBarrier(); |
| +} |
| + |
| +bool IsMallocZoneAlreadyStored(ChromeMallocZone* zone) { |
| + base::AutoLock l(*GetLock()); |
| + return IsMallocZoneAlreadyStoredLocked(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; |
| +} |
| + |
| +} // namespace allocator |
| +} // namespace base |