[compiler-rt] r340969 - [sanitizer] reapply r340884 'Add a RingBuffer class to sanitizer_common', with fixes for Windows

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 29 14:00:01 PDT 2018


Author: kcc
Date: Wed Aug 29 14:00:01 2018
New Revision: 340969

URL: http://llvm.org/viewvc/llvm-project?rev=340969&view=rev
Log:
[sanitizer] reapply r340884 'Add a RingBuffer class to sanitizer_common', with fixes for Windows 

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=340969&r1=340968&r2=340969&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Wed Aug 29 14:00:01 2018
@@ -158,6 +158,7 @@ set(SANITIZER_IMPL_HEADERS
   sanitizer_procmaps.h
   sanitizer_quarantine.h
   sanitizer_report_decorator.h
+  sanitizer_ring_buffer.h
   sanitizer_rtems.h
   sanitizer_signal_interceptors.inc
   sanitizer_stackdepot.h

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h?rev=340969&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h Wed Aug 29 14:00:01 2018
@@ -0,0 +1,80 @@
+//===-- sanitizer_ring_buffer.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Simple ring buffer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_RING_BUFFER_H
+#define SANITIZER_RING_BUFFER_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+// RingBuffer<T>: fixed-size ring buffer optimized for speed of push().
+// T should be a POD type and sizeof(T) should be divisible by sizeof(void*).
+// At creation, all elements are zero.
+template<class T>
+class RingBuffer {
+ public:
+  COMPILER_CHECK(sizeof(T) % sizeof(void *) == 0);
+  static RingBuffer *New(uptr Size) {
+    void *Ptr = MmapOrDie(SizeInBytes(Size), "RingBuffer");
+    RingBuffer *RB = reinterpret_cast<RingBuffer*>(Ptr);
+    uptr End = reinterpret_cast<uptr>(Ptr) + SizeInBytes(Size);
+    RB->last_ = RB->next_ = reinterpret_cast<T*>(End - sizeof(T));
+    return RB;
+  }
+  void Delete() {
+    UnmapOrDie(this, SizeInBytes(size()));
+  }
+  uptr size() const {
+    return last_ + 1 -
+           reinterpret_cast<T *>(reinterpret_cast<uptr>(this) +
+                                 2 * sizeof(T *));
+  }
+  void push(T t) {
+    *next_ = t;
+    next_--;
+    // The condition below works only if sizeof(T) is divisible by sizeof(T*).
+    if (next_ <= reinterpret_cast<T*>(&next_))
+      next_ = last_;
+  }
+
+  T operator[](uptr Idx) const {
+    CHECK_LT(Idx, size());
+    sptr IdxNext = Idx + 1;
+    if (IdxNext > last_ - next_)
+      IdxNext -= size();
+    return next_[IdxNext];
+  }
+
+ private:
+  RingBuffer() {}
+  ~RingBuffer() {}
+  RingBuffer(const RingBuffer&) = delete;
+
+  static uptr SizeInBytes(uptr Size) {
+    return Size * sizeof(T) + 2 * sizeof(T*);
+  }
+
+  // Data layout:
+  // LNDDDDDDDD
+  // D: data elements.
+  // L: last_, always points to the last data element.
+  // N: next_, initially equals to last_, is decremented on every push,
+  //    wraps around if it's less or equal than its own address.
+
+  T *last_;
+  T *next_;
+  T data_[1];  // flexible array.
+};
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_RING_BUFFER_H

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt?rev=340969&r1=340968&r2=340969&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt Wed Aug 29 14:00:01 2018
@@ -26,6 +26,7 @@ set(SANITIZER_UNITTESTS
   sanitizer_posix_test.cc
   sanitizer_printf_test.cc
   sanitizer_procmaps_test.cc
+  sanitizer_ring_buffer_test.cc
   sanitizer_quarantine_test.cc
   sanitizer_stackdepot_test.cc
   sanitizer_stacktrace_printer_test.cc

Added: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc?rev=340969&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc Wed Aug 29 14:00:01 2018
@@ -0,0 +1,77 @@
+//===-- sanitizer_vector_test.cc ------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of *Sanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_ring_buffer.h"
+#include "gtest/gtest.h"
+
+namespace __sanitizer {
+
+struct LargeStruct {
+  int64_t v;
+  int64_t extra[3];
+
+  explicit LargeStruct(int64_t v) : v(v) {}
+  operator int64_t() { return v; }
+};
+
+struct Struct10Bytes {
+  short t[3];
+};
+
+TEST(RingBuffer, Construct) {
+  RingBuffer<int64_t> *RBlong = RingBuffer<int64_t>::New(20);
+  EXPECT_EQ(RBlong->size(), 20U);
+  RBlong->Delete();
+}
+
+template <class T> void TestRB() {
+  RingBuffer<T> *RB;
+  const size_t Sizes[] = {1, 2, 3, 5, 8, 16, 20, 40, 10000};
+  for (size_t Size : Sizes) {
+    RB = RingBuffer<T>::New(Size);
+    EXPECT_EQ(RB->size(), Size);
+    RB->Delete();
+  }
+
+  RB = RingBuffer<T>::New(4);
+  EXPECT_EQ(RB->size(), 4U);
+#define EXPECT_RING_BUFFER(a0, a1, a2, a3) \
+  EXPECT_EQ((int64_t)(*RB)[0], (int64_t)a0);                 \
+  EXPECT_EQ((int64_t)(*RB)[1], (int64_t)a1);                 \
+  EXPECT_EQ((int64_t)(*RB)[2], (int64_t)a2);                 \
+  EXPECT_EQ((int64_t)(*RB)[3], (int64_t)a3);
+
+  RB->push(T(1)); EXPECT_RING_BUFFER(1, 0, 0, 0);
+  RB->push(T(2)); EXPECT_RING_BUFFER(2, 1, 0, 0);
+  RB->push(T(3)); EXPECT_RING_BUFFER(3, 2, 1, 0);
+  RB->push(T(4)); EXPECT_RING_BUFFER(4, 3, 2, 1);
+  RB->push(T(5)); EXPECT_RING_BUFFER(5, 4, 3, 2);
+  RB->push(T(6)); EXPECT_RING_BUFFER(6, 5, 4, 3);
+  RB->push(T(7)); EXPECT_RING_BUFFER(7, 6, 5, 4);
+  RB->push(T(8)); EXPECT_RING_BUFFER(8, 7, 6, 5);
+  RB->push(T(9)); EXPECT_RING_BUFFER(9, 8, 7, 6);
+  RB->push(T(10)); EXPECT_RING_BUFFER(10, 9, 8, 7);
+  RB->push(T(11)); EXPECT_RING_BUFFER(11, 10, 9, 8);
+  RB->push(T(12)); EXPECT_RING_BUFFER(12, 11, 10, 9);
+
+#undef EXPECT_RING_BUFFER
+}
+
+TEST(RingBuffer, int64) {
+  TestRB<int64_t>();
+}
+
+TEST(RingBuffer, LargeStruct) {
+  TestRB<LargeStruct>();
+}
+
+}  // namespace __sanitizer




More information about the llvm-commits mailing list