Index: base/metrics/persistent_memory_allocator.cc |
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc |
index 99ea44b8e9326a8c3d97b79663949c710f03d841..f70b396917134cc1706e8634916f638b82de71aa 100644 |
--- a/base/metrics/persistent_memory_allocator.cc |
+++ b/base/metrics/persistent_memory_allocator.cc |
@@ -540,10 +540,19 @@ bool PersistentMemoryAllocator::ChangeType(Reference ref, |
return false; |
} |
- // Clear the memory while the type doesn't match either "from" or "to". |
- memset(const_cast<char*>(reinterpret_cast<volatile char*>(block) + |
- sizeof(BlockHeader)), |
- 0, block->size - sizeof(BlockHeader)); |
+ // Clear the memory in an atomic manner. Using "release" stores force |
+ // every write to be done after the ones before it. This is better than |
+ // using memset because (a) it supports "volatile" and (b) it creates a |
+ // reliable pattern upon which other threads may rely. |
+ volatile std::atomic<int>* data = |
+ reinterpret_cast<volatile std::atomic<int>*>( |
+ reinterpret_cast<volatile char*>(block) + sizeof(BlockHeader)); |
+ const uint32_t words = (block->size - sizeof(BlockHeader)) / sizeof(int); |
+ DCHECK_EQ(0U, (block->size - sizeof(BlockHeader)) % sizeof(int)); |
+ for (uint32_t i = 0; i < words; ++i) { |
+ data->store(0, std::memory_order_release); |
+ ++data; |
+ } |
// If the destination type is "transitioning" then skip the final exchange. |
if (to_type_id == kTypeIdTransitioning) |