/* * 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 */