diff options
| author | Kostya Serebryany <kcc@google.com> | 2018-08-28 23:32:56 +0000 |
|---|---|---|
| committer | Kostya Serebryany <kcc@google.com> | 2018-08-28 23:32:56 +0000 |
| commit | 66eefee7ed831b8570d3b640dd810f53dc820b7c (patch) | |
| tree | 92b593f8c9d38cb4ffe9fea19923481a8a1676d6 /compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h | |
| parent | 689f7733173c4a7757f10bc7442905c18274f288 (diff) | |
| download | bcm5719-llvm-66eefee7ed831b8570d3b640dd810f53dc820b7c.tar.gz bcm5719-llvm-66eefee7ed831b8570d3b640dd810f53dc820b7c.zip | |
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
llvm-svn: 340884
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h')
| -rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h b/compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h new file mode 100644 index 00000000000..f3535b9cb4f --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_ring_buffer.h @@ -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 |

