malloc_zone_functions_mac.cc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/allocator/malloc_zone_functions_mac.h"
  5. #include <atomic>
  6. #include "base/synchronization/lock.h"
  7. namespace base {
  8. namespace allocator {
  9. MallocZoneFunctions g_malloc_zones[kMaxZoneCount];
  10. static_assert(std::is_pod<MallocZoneFunctions>::value,
  11. "MallocZoneFunctions must be POD");
  12. void StoreZoneFunctions(const ChromeMallocZone* zone,
  13. MallocZoneFunctions* functions) {
  14. memset(functions, 0, sizeof(MallocZoneFunctions));
  15. functions->malloc = zone->malloc;
  16. functions->calloc = zone->calloc;
  17. functions->valloc = zone->valloc;
  18. functions->free = zone->free;
  19. functions->realloc = zone->realloc;
  20. functions->size = zone->size;
  21. CHECK(functions->malloc && functions->calloc && functions->valloc &&
  22. functions->free && functions->realloc && functions->size);
  23. // These functions might be nullptr.
  24. functions->batch_malloc = zone->batch_malloc;
  25. functions->batch_free = zone->batch_free;
  26. if (zone->version >= 5) {
  27. // Not all custom malloc zones have a memalign.
  28. functions->memalign = zone->memalign;
  29. }
  30. if (zone->version >= 6) {
  31. // This may be nullptr.
  32. functions->free_definite_size = zone->free_definite_size;
  33. }
  34. // Note that zone version 8 introduced a pressure relief callback, and version
  35. // 10 introduced a claimed address callback, but neither are allocation or
  36. // deallocation callbacks and so aren't important to intercept.
  37. functions->context = zone;
  38. }
  39. namespace {
  40. // All modifications to g_malloc_zones are gated behind this lock.
  41. // Dispatch to a malloc zone does not need to acquire this lock.
  42. base::Lock& GetLock() {
  43. static base::Lock* g_lock = new base::Lock;
  44. return *g_lock;
  45. }
  46. void EnsureMallocZonesInitializedLocked() {
  47. GetLock().AssertAcquired();
  48. }
  49. int g_zone_count = 0;
  50. bool IsMallocZoneAlreadyStoredLocked(ChromeMallocZone* zone) {
  51. EnsureMallocZonesInitializedLocked();
  52. GetLock().AssertAcquired();
  53. for (int i = 0; i < g_zone_count; ++i) {
  54. if (g_malloc_zones[i].context == reinterpret_cast<void*>(zone))
  55. return true;
  56. }
  57. return false;
  58. }
  59. } // namespace
  60. bool StoreMallocZone(ChromeMallocZone* zone) {
  61. base::AutoLock l(GetLock());
  62. EnsureMallocZonesInitializedLocked();
  63. if (IsMallocZoneAlreadyStoredLocked(zone))
  64. return false;
  65. if (g_zone_count == kMaxZoneCount)
  66. return false;
  67. StoreZoneFunctions(zone, &g_malloc_zones[g_zone_count]);
  68. ++g_zone_count;
  69. // No other thread can possibly see these stores at this point. The code that
  70. // reads these values is triggered after this function returns. so we want to
  71. // guarantee that they are committed at this stage"
  72. std::atomic_thread_fence(std::memory_order_seq_cst);
  73. return true;
  74. }
  75. bool IsMallocZoneAlreadyStored(ChromeMallocZone* zone) {
  76. base::AutoLock l(GetLock());
  77. return IsMallocZoneAlreadyStoredLocked(zone);
  78. }
  79. bool DoesMallocZoneNeedReplacing(ChromeMallocZone* zone,
  80. const MallocZoneFunctions* functions) {
  81. return IsMallocZoneAlreadyStored(zone) && zone->malloc != functions->malloc;
  82. }
  83. int GetMallocZoneCountForTesting() {
  84. base::AutoLock l(GetLock());
  85. return g_zone_count;
  86. }
  87. void ClearAllMallocZonesForTesting() {
  88. base::AutoLock l(GetLock());
  89. EnsureMallocZonesInitializedLocked();
  90. memset(g_malloc_zones, 0, kMaxZoneCount * sizeof(MallocZoneFunctions));
  91. g_zone_count = 0;
  92. }
  93. } // namespace allocator
  94. } // namespace base