Use std::atomic in the signalling interfaces

Test: vsoc_stress_test
Bug: 70635412
Change-Id: I5f4487bafa6e8058d52778ace1a749607c7722f6
diff --git a/common/vsoc/lib/lock_common.cpp b/common/vsoc/lib/lock_common.cpp
index ed7962e..2744ba3 100644
--- a/common/vsoc/lib/lock_common.cpp
+++ b/common/vsoc/lib/lock_common.cpp
@@ -116,20 +116,18 @@
 }
 
 void layout::GuestAndHostLock::Lock(RegionView* region) {
-  uint32_t* uaddr = reinterpret_cast<uint32_t*>(&lock_uint32_);
   uint32_t expected;
   uint32_t tid = gettid();
   while (1) {
     if (TryLock(tid, &expected)) {
       return;
     }
-    region->WaitForSignal(uaddr, expected);
+    region->WaitForSignal(&lock_uint32_, expected);
   }
 }
 
 void layout::GuestAndHostLock::Unlock(RegionView* region) {
-  uint32_t* uaddr = reinterpret_cast<uint32_t*>(&lock_uint32_);
-  region->SendSignal(UnlockCommon(gettid()), uaddr);
+  region->SendSignal(UnlockCommon(gettid()), &lock_uint32_);
 }
 
 }  // namespace vsoc
diff --git a/common/vsoc/lib/mock_region_view.h b/common/vsoc/lib/mock_region_view.h
index 29ccad9..b6bcc45 100644
--- a/common/vsoc/lib/mock_region_view.h
+++ b/common/vsoc/lib/mock_region_view.h
@@ -54,12 +54,13 @@
   };
 
   virtual void SendSignal(vsoc::layout::Sides /* sides_to_signal */,
-                          uint32_t* uaddr) {
+                          std::atomic<uint32_t>* uaddr) {
     syscall(SYS_futex, reinterpret_cast<int32_t*>(uaddr), FUTEX_WAKE, -1,
             nullptr, nullptr, 0);
   }
 
-  virtual void WaitForSignal(uint32_t* uaddr, uint32_t expected_value) {
+  virtual void WaitForSignal(std::atomic<uint32_t>* uaddr,
+                             uint32_t expected_value) {
     {
       std::lock_guard<std::mutex> guard(mutex_);
       if (tid_to_addr_.find(std::this_thread::get_id()) != tid_to_addr_.end()) {
@@ -107,7 +108,7 @@
   void* region_base_{};
   std::mutex mutex_;
   std::condition_variable map_changed_;
-  std::unordered_map<std::thread::id, uint32_t*> tid_to_addr_;
+  std::unordered_map<std::thread::id, std::atomic<uint32_t>*> tid_to_addr_;
 };
 
 template <typename Layout>
diff --git a/common/vsoc/lib/region_signaling_interface.h b/common/vsoc/lib/region_signaling_interface.h
index b997387..d5bfbea 100644
--- a/common/vsoc/lib/region_signaling_interface.h
+++ b/common/vsoc/lib/region_signaling_interface.h
@@ -36,7 +36,7 @@
   //
   //   signal_addr: the memory location to signal. Must be within the region.
   virtual void SendSignal(layout::Sides sides_to_signal,
-                          uint32_t* signal_addr) = 0;
+                          std::atomic<uint32_t>* signal_addr) = 0;
 
   // This implements the following:
   // if (*signal_addr == last_observed_value)
@@ -49,7 +49,7 @@
   //   signal_addr: the memory that will be signaled. Must be within the region.
   //
   //   last_observed_value: the value that motivated the calling code to wait.
-  virtual void WaitForSignal(uint32_t* signal_addr,
+  virtual void WaitForSignal(std::atomic<uint32_t>* signal_addr,
                              uint32_t last_observed_value) = 0;
 };
 
diff --git a/common/vsoc/lib/region_view.cpp b/common/vsoc/lib/region_view.cpp
index 5c53b12..4f222f1 100644
--- a/common/vsoc/lib/region_view.cpp
+++ b/common/vsoc/lib/region_view.cpp
@@ -22,7 +22,7 @@
     if (stopping_) {
       return;
     }
-    region_->ProcessSignalsFromPeer([](uint32_t* uaddr) {
+    region_->ProcessSignalsFromPeer([](std::atomic<uint32_t>* uaddr) {
       syscall(SYS_futex, uaddr, FUTEX_WAKE, -1, nullptr, nullptr, 0);
     });
   }
@@ -83,7 +83,7 @@
 }
 
 void vsoc::RegionView::ProcessSignalsFromPeer(
-    std::function<void(uint32_t*)> signal_handler) {
+    std::function<void(std::atomic<uint32_t>*)> signal_handler) {
   const vsoc_signal_table_layout& table = incoming_signal_table();
   const size_t num_offsets = (1 << table.num_nodes_lg2);
   std::atomic<uint32_t>* offsets =
@@ -93,8 +93,9 @@
     uint32_t offset = offsets[i].exchange(0);
     if (offset) {
       bool round_trip = offset & UADDR_OFFSET_ROUND_TRIP_FLAG;
-      uint32_t* uaddr =
-          region_offset_to_pointer<uint32_t>(offset & UADDR_OFFSET_MASK);
+      std::atomic<uint32_t>* uaddr =
+          region_offset_to_pointer<std::atomic<uint32_t>>(offset &
+                                                          UADDR_OFFSET_MASK);
       signal_handler(uaddr);
       if (round_trip) {
         SendSignalToPeer(uaddr, false);
@@ -103,12 +104,13 @@
   }
 }
 
-void vsoc::RegionView::SendSignal(Sides sides_to_signal, uint32_t* uaddr) {
+void vsoc::RegionView::SendSignal(Sides sides_to_signal,
+                                  std::atomic<uint32_t>* uaddr) {
   if (sides_to_signal.value_ & Sides::Peer) {
     // If we should also be signalling our side set the round trip flag on
     // the futex signal.
     bool round_trip = sides_to_signal.value_ & Sides::OurSide;
-    SendSignalToPeer(reinterpret_cast<uint32_t*>(uaddr), round_trip);
+    SendSignalToPeer(uaddr, round_trip);
     // Return without signaling our waiters to give the other side a chance
     // to run.
     return;
@@ -119,7 +121,8 @@
   }
 }
 
-void vsoc::RegionView::SendSignalToPeer(uint32_t* uaddr, bool round_trip) {
+void vsoc::RegionView::SendSignalToPeer(std::atomic<uint32_t>* uaddr,
+                                        bool round_trip) {
   const vsoc_signal_table_layout& table = outgoing_signal_table();
   std::atomic<uint32_t>* offsets =
       region_offset_to_pointer<std::atomic<uint32_t>>(
@@ -180,6 +183,7 @@
   return std::unique_ptr<vsoc::RegionWorker>(new vsoc::RegionWorker(this));
 }
 
-void vsoc::RegionView::WaitForSignal(uint32_t* uaddr, uint32_t expected_value) {
+void vsoc::RegionView::WaitForSignal(std::atomic<uint32_t>* uaddr,
+                                     uint32_t expected_value) {
   syscall(SYS_futex, uaddr, FUTEX_WAIT, expected_value, nullptr, nullptr, 0);
 }
diff --git a/common/vsoc/lib/region_view.h b/common/vsoc/lib/region_view.h
index 0c366ee..0f82ace 100644
--- a/common/vsoc/lib/region_view.h
+++ b/common/vsoc/lib/region_view.h
@@ -100,7 +100,8 @@
   //   signal_handler: An action to perform on every offset signalled by our
   //   peer, usually a FUTEX_WAKE call, but can be customized for other
   //   purposes.
-  void ProcessSignalsFromPeer(std::function<void(uint32_t*)> signal_handler);
+  void ProcessSignalsFromPeer(
+      std::function<void(std::atomic<uint32_t>*)> signal_handler);
 
   // Post a signal to the guest, the host, or both.
   // See futex(2) FUTEX_WAKE for details.
@@ -108,7 +109,8 @@
   //   sides_to_signal: controls where the signal is sent
   //
   //   signal_addr: the memory location to signal. Must be within the region.
-  void SendSignal(layout::Sides sides_to_signal, uint32_t* signal_addr);
+  void SendSignal(layout::Sides sides_to_signal,
+                  std::atomic<uint32_t>* signal_addr);
 
   // Post a signal to our peer for a specific memeory location.
   // See futex(2) FUTEX_WAKE for details.
@@ -117,7 +119,7 @@
   //
   //   round_trip: true if there may be waiters on both sides of the shared
   //               memory.
-  void SendSignalToPeer(uint32_t* signal_addr, bool round_trip);
+  void SendSignalToPeer(std::atomic<uint32_t>* signal_addr, bool round_trip);
 
   // Waits until an interrupt appears on this region, then clears the
   // interrupted flag and returns.
@@ -134,7 +136,8 @@
   //   signal_addr: the memory that will be signaled. Must be within the region.
   //
   //   last_observed_value: the value that motivated the calling code to wait.
-  void WaitForSignal(uint32_t* signal_addr, uint32_t last_observed_value);
+  void WaitForSignal(std::atomic<uint32_t>* signal_addr,
+                     uint32_t last_observed_value);
 
   // Starts the signal table scanner. This must be invoked by subclasses, which
   // must store the returned unique_ptr as a class member.
diff --git a/common/vsoc/shm/circqueue.h b/common/vsoc/shm/circqueue.h
index 8c5b966..c8ee3af 100644
--- a/common/vsoc/shm/circqueue.h
+++ b/common/vsoc/shm/circqueue.h
@@ -87,9 +87,9 @@
   // they should be interpreted modulo the buffer size. This fact along with the
   // buffer size being a power of two greatly simplyfies the index calculations.
   // Advances when a reader has finished with buffer space
-  uint32_t r_released_;
+  std::atomic<uint32_t> r_released_;
   // Advances when buffer space is filled and ready for a reader
-  uint32_t w_pub_;
+  std::atomic<uint32_t> w_pub_;
   // Spinlock that protects the region. 0 means unlocked
   SpinLock lock_;
   // The actual memory in the buffer
diff --git a/common/vsoc/shm/e2e_test_region_layout.h b/common/vsoc/shm/e2e_test_region_layout.h
index f0a24e9..7227726 100644
--- a/common/vsoc/shm/e2e_test_region_layout.h
+++ b/common/vsoc/shm/e2e_test_region_layout.h
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#include <atomic>
 #include <cstdint>
 #include "common/vsoc/shm/base.h"
 #include "common/vsoc/shm/version.h"
@@ -117,8 +118,8 @@
   // Later guest tests will wait on this
   E2ETestStageRegister host_status;
   // These fields are used to test the signaling mechanism.
-  uint32_t host_to_guest_signal;
-  uint32_t guest_to_host_signal;
+  std::atomic<uint32_t> host_to_guest_signal;
+  std::atomic<uint32_t> guest_to_host_signal;
   // There rest of the region will be filled by guest_host_strings.
   // We actually use more than one of these, but we can't know how many
   // until we examine the region.
diff --git a/common/vsoc/shm/fb_bcast_layout.h b/common/vsoc/shm/fb_bcast_layout.h
index 67c229b..21985c0 100644
--- a/common/vsoc/shm/fb_bcast_layout.h
+++ b/common/vsoc/shm/fb_bcast_layout.h
@@ -35,7 +35,7 @@
   uint16_t refresh_rate_hz;
 
   // The frame sequential number
-  uint32_t seq_num;
+  std::atomic<uint32_t> seq_num;
   // The offset in the gralloc buffer region of the current frame buffer.
   uint32_t frame_offset;
   // Protects access to the frame offset and sequential number.
diff --git a/guest/vsoc/lib/guest_region_e2e_test.cpp b/guest/vsoc/lib/guest_region_e2e_test.cpp
index b91c1c1..62d98f6 100644
--- a/guest/vsoc/lib/guest_region_e2e_test.cpp
+++ b/guest/vsoc/lib/guest_region_e2e_test.cpp
@@ -118,20 +118,22 @@
   LOG(INFO) << "Signal sent. Waiting for first signal from peer";
   primary.WaitForInterrupt();
   int count = 0;  // counts the number of signals received.
-  primary.ProcessSignalsFromPeer([&primary, &count](uint32_t* uaddr) {
-    ++count;
-    EXPECT_TRUE(uaddr == &primary.data()->host_to_guest_signal);
-  });
+  primary.ProcessSignalsFromPeer(
+      [&primary, &count](std::atomic<uint32_t>* uaddr) {
+        ++count;
+        EXPECT_TRUE(uaddr == &primary.data()->host_to_guest_signal);
+      });
   EXPECT_TRUE(count == 1);
   LOG(INFO) << "Signal received on primary region";
   secondary.SendSignal(side, &secondary.data()->guest_to_host_signal);
   LOG(INFO) << "Signal sent. Waiting for second signal from peer";
   secondary.WaitForInterrupt();
   count = 0;
-  secondary.ProcessSignalsFromPeer([&secondary, &count](uint32_t* uaddr) {
-    ++count;
-    EXPECT_TRUE(uaddr == &secondary.data()->host_to_guest_signal);
-  });
+  secondary.ProcessSignalsFromPeer(
+      [&secondary, &count](std::atomic<uint32_t>* uaddr) {
+        ++count;
+        EXPECT_TRUE(uaddr == &secondary.data()->host_to_guest_signal);
+      });
   EXPECT_TRUE(count == 1);
   LOG(INFO) << "Signal received on secondary region";
 
diff --git a/host/vsoc/lib/host_region_e2e_test.cpp b/host/vsoc/lib/host_region_e2e_test.cpp
index dc87f46..a707838 100644
--- a/host/vsoc/lib/host_region_e2e_test.cpp
+++ b/host/vsoc/lib/host_region_e2e_test.cpp
@@ -87,20 +87,22 @@
   LOG(INFO) << "Signal sent. Waiting for first signal from peer";
   primary.WaitForInterrupt();
   int count = 0;  // counts the number of signals received.
-  primary.ProcessSignalsFromPeer([&primary, &count](uint32_t* uaddr) {
-    ++count;
-    EXPECT_TRUE(uaddr == &primary.data()->guest_to_host_signal);
-  });
+  primary.ProcessSignalsFromPeer(
+      [&primary, &count](std::atomic<uint32_t>* uaddr) {
+        ++count;
+        EXPECT_TRUE(uaddr == &primary.data()->guest_to_host_signal);
+      });
   EXPECT_TRUE(count == 1);
   LOG(INFO) << "Signal received on primary region";
   secondary.SendSignal(side, &secondary.data()->host_to_guest_signal);
   LOG(INFO) << "Signal sent. Waiting for second signal from peer";
   secondary.WaitForInterrupt();
   count = 0;
-  secondary.ProcessSignalsFromPeer([&secondary, &count](uint32_t* uaddr) {
-    ++count;
-    EXPECT_TRUE(uaddr == &secondary.data()->guest_to_host_signal);
-  });
+  secondary.ProcessSignalsFromPeer(
+      [&secondary, &count](std::atomic<uint32_t>* uaddr) {
+        ++count;
+        EXPECT_TRUE(uaddr == &secondary.data()->guest_to_host_signal);
+      });
   EXPECT_TRUE(count == 1);
   LOG(INFO) << "Signal received on secondary region";