summaryrefslogtreecommitdiffstats
path: root/content/renderer/devtools/lock_free_circular_queue.h
diff options
context:
space:
mode:
authoralph <alph@chromium.org>2015-03-20 06:58:16 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-20 13:59:09 +0000
commitcc35222c027b300b2edb95c7bcb6db02ab95da4c (patch)
tree50108aaf0eb5bfcc1f45408d9a3a5fe5728d267c /content/renderer/devtools/lock_free_circular_queue.h
parentf6dd3c3320e44b29ac283f6ce9d41018cd8eed26 (diff)
downloadchromium_src-cc35222c027b300b2edb95c7bcb6db02ab95da4c.zip
chromium_src-cc35222c027b300b2edb95c7bcb6db02ab95da4c.tar.gz
chromium_src-cc35222c027b300b2edb95c7bcb6db02ab95da4c.tar.bz2
V8 Sampling Profiler: Collect V8 sample trace events on Linux and MacOS
When the v8.cpu_profiler tracing category is enabled it starts generating V8Sample events with stack frames and V8 state. LockFreeCircularQueue template is taken from V8. Android and Windows support will be coming. BUG=406277 Review URL: https://codereview.chromium.org/1017063002 Cr-Commit-Position: refs/heads/master@{#321565}
Diffstat (limited to 'content/renderer/devtools/lock_free_circular_queue.h')
-rw-r--r--content/renderer/devtools/lock_free_circular_queue.h135
1 files changed, 135 insertions, 0 deletions
diff --git a/content/renderer/devtools/lock_free_circular_queue.h b/content/renderer/devtools/lock_free_circular_queue.h
new file mode 100644
index 0000000..dfa780b
--- /dev/null
+++ b/content/renderer/devtools/lock_free_circular_queue.h
@@ -0,0 +1,135 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DEVTOOLS_LOCK_FREE_CIRCULAR_QUEUE_H_
+#define CONTENT_RENDERER_DEVTOOLS_LOCK_FREE_CIRCULAR_QUEUE_H_
+
+#include "base/atomicops.h"
+#include "base/memory/aligned_memory.h"
+
+#define CACHELINE_ALIGNED ALIGNAS(64)
+
+namespace content {
+
+MSVC_PUSH_DISABLE_WARNING(4324) // structure was padded due to align
+
+// Lock-free cache-friendly sampling circular queue for large
+// records. Intended for fast transfer of large records between a
+// single producer and a single consumer. If the queue is full,
+// StartEnqueue will return nullptr. The queue is designed with
+// a goal in mind to evade cache lines thrashing by preventing
+// simultaneous reads and writes to adjanced memory locations.
+template <typename T, unsigned Length>
+class LockFreeCircularQueue {
+ public:
+ // Executed on the application thread.
+ LockFreeCircularQueue();
+ ~LockFreeCircularQueue();
+
+ // StartEnqueue returns a pointer to a memory location for storing the next
+ // record or nullptr if all entries are full at the moment.
+ T* StartEnqueue();
+ // Notifies the queue that the producer has complete writing data into the
+ // memory returned by StartEnqueue and it can be passed to the consumer.
+ void FinishEnqueue();
+
+ // Executed on the consumer (analyzer) thread.
+ // Retrieves, but does not remove, the head of this queue, returning nullptr
+ // if this queue is empty. After the record had been read by a consumer,
+ // Remove must be called.
+ T* Peek();
+ void Remove();
+
+ // The class fields have stricter alignment requirements than a normal new
+ // can fulfil, so we need to provide our own new/delete here.
+ void* operator new(size_t size);
+ void operator delete(void* ptr);
+
+ private:
+ // Reserved values for the entry marker.
+ enum {
+ kEmpty, // Marks clean (processed) entries.
+ kFull // Marks entries already filled by the producer but not yet
+ // completely processed by the consumer.
+ };
+
+ struct CACHELINE_ALIGNED Entry {
+ Entry() : marker(kEmpty) {}
+ T record;
+ base::subtle::Atomic32 marker;
+ };
+
+ Entry* Next(Entry* entry);
+
+ Entry buffer_[Length];
+ CACHELINE_ALIGNED Entry* enqueue_pos_;
+ CACHELINE_ALIGNED Entry* dequeue_pos_;
+
+ DISALLOW_COPY_AND_ASSIGN(LockFreeCircularQueue);
+};
+
+MSVC_POP_WARNING()
+
+template <typename T, unsigned L>
+LockFreeCircularQueue<T, L>::LockFreeCircularQueue()
+ : enqueue_pos_(buffer_), dequeue_pos_(buffer_) {
+}
+
+template <typename T, unsigned L>
+LockFreeCircularQueue<T, L>::~LockFreeCircularQueue() {
+}
+
+template <typename T, unsigned L>
+T* LockFreeCircularQueue<T, L>::Peek() {
+ base::subtle::MemoryBarrier();
+ if (base::subtle::Acquire_Load(&dequeue_pos_->marker) == kFull) {
+ return &dequeue_pos_->record;
+ }
+ return nullptr;
+}
+
+template <typename T, unsigned L>
+void LockFreeCircularQueue<T, L>::Remove() {
+ base::subtle::Release_Store(&dequeue_pos_->marker, kEmpty);
+ dequeue_pos_ = Next(dequeue_pos_);
+}
+
+template <typename T, unsigned L>
+T* LockFreeCircularQueue<T, L>::StartEnqueue() {
+ base::subtle::MemoryBarrier();
+ if (base::subtle::Acquire_Load(&enqueue_pos_->marker) == kEmpty) {
+ return &enqueue_pos_->record;
+ }
+ return nullptr;
+}
+
+template <typename T, unsigned L>
+void LockFreeCircularQueue<T, L>::FinishEnqueue() {
+ base::subtle::Release_Store(&enqueue_pos_->marker, kFull);
+ enqueue_pos_ = Next(enqueue_pos_);
+}
+
+template <typename T, unsigned L>
+typename LockFreeCircularQueue<T, L>::Entry* LockFreeCircularQueue<T, L>::Next(
+ Entry* entry) {
+ Entry* next = entry + 1;
+ if (next == &buffer_[L])
+ return buffer_;
+ return next;
+}
+
+template <typename T, unsigned L>
+void* LockFreeCircularQueue<T, L>::operator new(size_t size) {
+ typedef LockFreeCircularQueue<T, L> QueueTypeAlias;
+ return base::AlignedAlloc(size, ALIGNOF(QueueTypeAlias));
+}
+
+template <typename T, unsigned L>
+void LockFreeCircularQueue<T, L>::operator delete(void* ptr) {
+ base::AlignedFree(ptr);
+}
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DEVTOOLS_LOCK_FREE_CIRCULAR_QUEUE_H_