[compiler-rt] r340884 - Add a RingBuffer class to sanitizer_common
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 28 16:32:56 PDT 2018
Author: kcc
Date: Tue Aug 28 16:32:56 2018
New Revision: 340884
URL: http://llvm.org/viewvc/llvm-project?rev=340884&view=rev
Log:
Add a RingBuffer class to sanitizer_common
Summary: a constrained RingBuffer optimized for fast push
Reviewers: eugenis
Reviewed By: eugenis
Subscribers: kubamracek, mgorny, delcypher, #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D51196
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=340884&r1=340883&r2=340884&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Tue Aug 28 16:32:56 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=340884&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_ring_buffer.h Tue Aug 28 16:32:56 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:
+ 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));
+ CHECK_EQ(sizeof(T) % sizeof(void*), 0U);
+ 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=340884&r1=340883&r2=340884&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/CMakeLists.txt Tue Aug 28 16:32:56 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=340884&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 Tue Aug 28 16:32:56 2018
@@ -0,0 +1,83 @@
+//===-- 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 {
+ long v;
+ long extra[3];
+
+ LargeStruct(long v) : v(v) {}
+ operator long() { return v; }
+};
+
+struct Struct12Bytes {
+ int t[3];
+};
+
+TEST(RingBuffer, Construct) {
+
+ RingBuffer<long> *RBlong = RingBuffer<long>::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((long)(*RB)[0], (long)a0); \
+ EXPECT_EQ((long)(*RB)[1], (long)a1); \
+ EXPECT_EQ((long)(*RB)[2], (long)a2); \
+ EXPECT_EQ((long)(*RB)[3], (long)a3);
+
+ RB->push(1); EXPECT_RING_BUFFER(1, 0, 0, 0);
+ RB->push(2); EXPECT_RING_BUFFER(2, 1, 0, 0);
+ RB->push(3); EXPECT_RING_BUFFER(3, 2, 1, 0);
+ RB->push(4); EXPECT_RING_BUFFER(4, 3, 2, 1);
+ RB->push(5); EXPECT_RING_BUFFER(5, 4, 3, 2);
+ RB->push(6); EXPECT_RING_BUFFER(6, 5, 4, 3);
+ RB->push(7); EXPECT_RING_BUFFER(7, 6, 5, 4);
+ RB->push(8); EXPECT_RING_BUFFER(8, 7, 6, 5);
+ RB->push(9); EXPECT_RING_BUFFER(9, 8, 7, 6);
+ RB->push(10); EXPECT_RING_BUFFER(10, 9, 8, 7);
+ RB->push(11); EXPECT_RING_BUFFER(11, 10, 9, 8);
+ RB->push(12); EXPECT_RING_BUFFER(12, 11, 10, 9);
+
+#undef EXPECT_RING_BUFFER
+}
+
+TEST(RingBuffer, Int) {
+ EXPECT_DEATH(RingBuffer<int>::New(10), "");
+ EXPECT_DEATH(RingBuffer<Struct12Bytes>::New(10), "");
+}
+
+TEST(RingBuffer, Long) {
+ TestRB<long>();
+}
+
+TEST(RingBuffer, LargeStruct) {
+ TestRB<LargeStruct>();
+}
+
+} // namespace __sanitizer
More information about the llvm-commits
mailing list