diff options
author | alph <alph@chromium.org> | 2015-03-20 06:58:16 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-20 13:59:09 +0000 |
commit | cc35222c027b300b2edb95c7bcb6db02ab95da4c (patch) | |
tree | 50108aaf0eb5bfcc1f45408d9a3a5fe5728d267c /content/renderer/devtools/lock_free_circular_queue.h | |
parent | f6dd3c3320e44b29ac283f6ce9d41018cd8eed26 (diff) | |
download | chromium_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.h | 135 |
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_ |