BpfRingBuf.h - implement isEmpty()

Test: TreeHugger, atest BpfRingbufTest
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I23020869ab665c029c3219b1b39c3749be6e6992
diff --git a/staticlibs/native/bpf_headers/BpfRingbufTest.cpp b/staticlibs/native/bpf_headers/BpfRingbufTest.cpp
index 6c0841c..e4de812 100644
--- a/staticlibs/native/bpf_headers/BpfRingbufTest.cpp
+++ b/staticlibs/native/bpf_headers/BpfRingbufTest.cpp
@@ -72,12 +72,15 @@
 
     auto result = BpfRingbuf<uint64_t>::Create(mRingbufPath.c_str());
     ASSERT_RESULT_OK(result);
+    EXPECT_TRUE(result.value()->isEmpty());
 
     for (int i = 0; i < n; i++) {
       RunProgram();
     }
 
+    EXPECT_FALSE(result.value()->isEmpty());
     EXPECT_THAT(result.value()->ConsumeAll(callback), HasValue(n));
+    EXPECT_TRUE(result.value()->isEmpty());
     EXPECT_EQ(output, TEST_RINGBUF_MAGIC_NUM);
     EXPECT_EQ(run_count, n);
   }
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfRingbuf.h b/staticlibs/native/bpf_headers/include/bpf/BpfRingbuf.h
index dd1504c..9aff790 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfRingbuf.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfRingbuf.h
@@ -39,6 +39,8 @@
     mProducerPos = nullptr;
   }
 
+  bool isEmpty(void);
+
  protected:
   // Non-initializing constructor, used by Create.
   BpfRingbufBase(size_t value_size) : mValueSize(value_size) {}
@@ -197,6 +199,13 @@
   return {};
 }
 
+inline bool BpfRingbufBase::isEmpty(void) {
+  uint32_t prod_pos = mProducerPos->load(std::memory_order_acquire);
+  // Only userspace writes to mConsumerPos, so no need to use std::memory_order_acquire
+  uint64_t cons_pos = mConsumerPos->load(std::memory_order_relaxed);
+  return (cons_pos & 0xFFFFFFFF) == prod_pos;
+}
+
 inline base::Result<int> BpfRingbufBase::ConsumeAll(
     const std::function<void(const void*)>& callback) {
   int64_t count = 0;