1 // Copyright 2013 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 
5 #include "device/base/synchronization/one_writer_seqlock.h"
6 
7 namespace device {
8 
OneWriterSeqLock()9 OneWriterSeqLock::OneWriterSeqLock() : sequence_(0) {}
10 
ReadBegin(uint32_t max_retries) const11 base::subtle::Atomic32 OneWriterSeqLock::ReadBegin(uint32_t max_retries) const {
12   base::subtle::Atomic32 version;
13   for (uint32_t i = 0; i <= max_retries; ++i) {
14     version = base::subtle::Acquire_Load(&sequence_);
15 
16     // If the counter is even, then the associated data might be in a
17     // consistent state, so we can try to read.
18     if ((version & 1) == 0)
19       break;
20 
21     // Otherwise, the writer is in the middle of an update. Retry the read.
22     // In a multiprocessor environment with short write time, thread yield is
23     // expensive and best be avoided during the first 10~100 iterations.
24     if (i > 10)
25       base::PlatformThread::YieldCurrentThread();
26   }
27   return version;
28 }
29 
ReadRetry(base::subtle::Atomic32 version) const30 bool OneWriterSeqLock::ReadRetry(base::subtle::Atomic32 version) const {
31   // If the sequence number was updated then a read should be re-attempted.
32   // -- Load fence, read membarrier
33   return base::subtle::Release_Load(&sequence_) != version;
34 }
35 
WriteBegin()36 void OneWriterSeqLock::WriteBegin() {
37   // Increment the sequence number to odd to indicate the beginning of a write
38   // update.
39   base::subtle::Barrier_AtomicIncrement(&sequence_, 1);
40   // -- Store fence, write membarrier
41 }
42 
WriteEnd()43 void OneWriterSeqLock::WriteEnd() {
44   // Increment the sequence to an even number to indicate the completion of
45   // a write update.
46   // -- Store fence, write membarrier
47   base::subtle::Barrier_AtomicIncrement(&sequence_, 1);
48 }
49 
50 }  // namespace device
51