/*
* Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
*
* This file is part of the Lock Contention Tracing Subsystem for the HotSpot
* Virtual Machine, which is developed at Christian Doppler Laboratory on
* Monitoring and Evolution of Very-Large-Scale Software Systems. Please
* contact us at if you need additional information
* or have any questions.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work. If not, see .
*
*/
#ifndef SHARE_VM_EVTRACE_TRACEMANAGER_INLINE_HPP
#define SHARE_VM_EVTRACE_TRACEMANAGER_INLINE_HPP
#include "evtrace/traceBuffer.hpp"
#include "evtrace/traceBufferQueue.hpp"
#include "evtrace/traceMetadata.hpp"
inline bool TraceManager::is_initialized() {
return _is_initialized;
}
inline void TraceManager::assert_initialized() {
assert(_is_initialized, "not initialized");
assert(_free_queue != NULL || !EnableEventTracingBufferReuse, "freeQueue not initialized");
assert(_flush_queue != NULL, "flushQueue not initialized");
}
inline TraceBuffer *TraceManager::allocate_buffer() {
// tradeoff: small buffer sizes reduce the time it takes to process a
// buffer and make it available again, but cause more queue operations
// (and possible contentions). large buffers are wasteful for short-lived
// threads, but cause less queue contention and reclaim operations
// waiting for buffers to be processed can take significantly longer.
size_t capacity = EventTracingBufferCapacity;
if (EnableEventTracingRandomizedBufferCapacity) {
// use random buffer sizes to avoid that threads which do similar work
// submit and request buffers all at once
capacity = round_to(capacity / 2 + ((size_t) os::random()) % capacity, 128);
}
TraceBuffer *buffer = new (capacity) TraceBuffer(capacity);
if (EnableEventTracingDiagnostics) {
Atomic::inc_ptr(&_allocated_buffer_count);
jlong count = Atomic::add_ptr(1, &_buffer_count);
jlong max;
do {
max = _max_buffer_count;
} while (count > max && Atomic::cmpxchg(count, &_max_buffer_count, max) != max);
}
return buffer;
}
inline void TraceManager::free_buffer(TraceBuffer *buffer) {
assert(buffer != NULL, "sanity");
delete buffer;
if (EnableEventTracingDiagnostics) {
Atomic::dec_ptr(&_buffer_count);
}
}
inline TraceBuffer *TraceManager::request_buffer() {
assert_initialized();
TraceBuffer *buffer = NULL;
if (EnableEventTracingBufferReuse) {
buffer = _free_queue->try_dequeue();
}
if (buffer == NULL) {
buffer = allocate_buffer();
}
return buffer;
}
inline void TraceManager::pre_submit_buffer(TraceBuffer *buffer) {
assert(buffer != NULL, "no buffer given");
assert(buffer->owner_id == 0, "must not be set at this point");
buffer->owner_id = _metadata->thread_id(buffer->owner);
buffer->owner = NULL;
}
inline void TraceManager::submit_buffer(TraceBuffer *buffer) {
assert_initialized();
assert(buffer != NULL, "buffer is NULL");
TraceManager::pre_submit_buffer(buffer);
size_t bytes = buffer->filled_size();
_flush_queue->enqueue(buffer);
if (EnableEventTracingDiagnostics) {
Atomic::add(bytes, &_submitted_trace_bytes);
}
}
inline TraceMetadata *TraceManager::metadata() {
assert_initialized();
return _metadata;
}
inline void TraceManager::update_stack_trace_stats(bool truncated, intptr_t total_frames, intptr_t memento_frames) {
assert_initialized();
if (EnableEventTracingDiagnostics) {
assert(total_frames > 0 && memento_frames >= 0, "sanity");
Atomic::inc_ptr(&_total_stack_traces);
if (truncated) {
Atomic::inc_ptr(&_truncated_stack_traces);
}
Atomic::add_ptr(total_frames, &_total_stack_frames);
if (memento_frames != 0) {
assert(memento_frames < total_frames, "sanity");
Atomic::inc_ptr(&_reused_memento_stack_traces);
Atomic::add_ptr(memento_frames, &_reused_memento_stack_frames);
}
}
}
#endif /* SHARE_VM_EVTRACE_TRACEMANAGER_INLINE_HPP */