OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/metrics/persistent_memory_allocator.h" | 5 #include "base/metrics/persistent_memory_allocator.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 | 9 |
10 #if defined(OS_WIN) | 10 #if defined(OS_WIN) |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 // If clearing the memory, first change it to the "transitioning" type so | 533 // If clearing the memory, first change it to the "transitioning" type so |
534 // there can be no confusion by other threads. After the memory is cleared, | 534 // there can be no confusion by other threads. After the memory is cleared, |
535 // it can be changed to its final type. | 535 // it can be changed to its final type. |
536 if (!block->type_id.compare_exchange_strong( | 536 if (!block->type_id.compare_exchange_strong( |
537 from_type_id, kTypeIdTransitioning, std::memory_order_acquire, | 537 from_type_id, kTypeIdTransitioning, std::memory_order_acquire, |
538 std::memory_order_acquire)) { | 538 std::memory_order_acquire)) { |
539 // Existing type wasn't what was expected: fail (with no changes) | 539 // Existing type wasn't what was expected: fail (with no changes) |
540 return false; | 540 return false; |
541 } | 541 } |
542 | 542 |
543 // Clear the memory while the type doesn't match either "from" or "to". | 543 // Clear the memory in an atomic manner. Using "release" stores force |
544 memset(const_cast<char*>(reinterpret_cast<volatile char*>(block) + | 544 // every write to be done after the ones before it. This is better than |
545 sizeof(BlockHeader)), | 545 // using memset because (a) it supports "volatile" and (b) it creates a |
546 0, block->size - sizeof(BlockHeader)); | 546 // reliable pattern upon which other threads may rely. |
| 547 volatile std::atomic<int>* data = |
| 548 reinterpret_cast<volatile std::atomic<int>*>( |
| 549 reinterpret_cast<volatile char*>(block) + sizeof(BlockHeader)); |
| 550 const uint32_t words = (block->size - sizeof(BlockHeader)) / sizeof(int); |
| 551 DCHECK_EQ(0U, (block->size - sizeof(BlockHeader)) % sizeof(int)); |
| 552 for (uint32_t i = 0; i < words; ++i) { |
| 553 data->store(0, std::memory_order_release); |
| 554 ++data; |
| 555 } |
547 | 556 |
548 // If the destination type is "transitioning" then skip the final exchange. | 557 // If the destination type is "transitioning" then skip the final exchange. |
549 if (to_type_id == kTypeIdTransitioning) | 558 if (to_type_id == kTypeIdTransitioning) |
550 return true; | 559 return true; |
551 | 560 |
552 // Finish the change to the desired type. | 561 // Finish the change to the desired type. |
553 from_type_id = kTypeIdTransitioning; // Exchange needs modifiable original. | 562 from_type_id = kTypeIdTransitioning; // Exchange needs modifiable original. |
554 bool success = block->type_id.compare_exchange_strong( | 563 bool success = block->type_id.compare_exchange_strong( |
555 from_type_id, to_type_id, std::memory_order_release, | 564 from_type_id, to_type_id, std::memory_order_release, |
556 std::memory_order_relaxed); | 565 std::memory_order_relaxed); |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 | 995 |
987 // static | 996 // static |
988 bool FilePersistentMemoryAllocator::IsFileAcceptable( | 997 bool FilePersistentMemoryAllocator::IsFileAcceptable( |
989 const MemoryMappedFile& file, | 998 const MemoryMappedFile& file, |
990 bool read_only) { | 999 bool read_only) { |
991 return IsMemoryAcceptable(file.data(), file.length(), 0, read_only); | 1000 return IsMemoryAcceptable(file.data(), file.length(), 0, read_only); |
992 } | 1001 } |
993 #endif // !defined(OS_NACL) | 1002 #endif // !defined(OS_NACL) |
994 | 1003 |
995 } // namespace base | 1004 } // namespace base |
OLD | NEW |