| 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)
|
|
|