1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/jfr/support/jfrThreadLocal.cpp Mon Aug 12 18:30:40 2019 +0300 1.3 @@ -0,0 +1,141 @@ 1.4 +/* 1.5 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "jfr/jni/jfrJavaSupport.hpp" 1.30 +#include "jfr/periodic/jfrThreadCPULoadEvent.hpp" 1.31 +#include "jfr/recorder/jfrRecorder.hpp" 1.32 +#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" 1.33 +#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" 1.34 +#include "jfr/recorder/service/jfrOptionSet.hpp" 1.35 +#include "jfr/recorder/storage/jfrStorage.hpp" 1.36 +#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" 1.37 +#include "jfr/support/jfrThreadLocal.hpp" 1.38 +#include "memory/allocation.inline.hpp" 1.39 +#include "runtime/os.hpp" 1.40 +#include "runtime/thread.inline.hpp" 1.41 + 1.42 +/* This data structure is per thread and only accessed by the thread itself, no locking required */ 1.43 +JfrThreadLocal::JfrThreadLocal() : 1.44 + _java_event_writer(NULL), 1.45 + _java_buffer(NULL), 1.46 + _native_buffer(NULL), 1.47 + _shelved_buffer(NULL), 1.48 + _stackframes(NULL), 1.49 + _trace_id(JfrTraceId::assign_thread_id()), 1.50 + _thread_cp(), 1.51 + _data_lost(0), 1.52 + _stack_trace_id(max_julong), 1.53 + _user_time(0), 1.54 + _cpu_time(0), 1.55 + _wallclock_time(os::javaTimeNanos()), 1.56 + _stack_trace_hash(0), 1.57 + _stackdepth(0), 1.58 + _entering_suspend_flag(0), 1.59 + _dead(false) {} 1.60 + 1.61 +u8 JfrThreadLocal::add_data_lost(u8 value) { 1.62 + _data_lost += value; 1.63 + return _data_lost; 1.64 +} 1.65 + 1.66 +bool JfrThreadLocal::has_thread_checkpoint() const { 1.67 + return _thread_cp.valid(); 1.68 +} 1.69 + 1.70 +void JfrThreadLocal::set_thread_checkpoint(const JfrCheckpointBlobHandle& ref) { 1.71 + assert(!_thread_cp.valid(), "invariant"); 1.72 + _thread_cp = ref; 1.73 +} 1.74 + 1.75 +const JfrCheckpointBlobHandle& JfrThreadLocal::thread_checkpoint() const { 1.76 + return _thread_cp; 1.77 +} 1.78 + 1.79 +void JfrThreadLocal::set_dead() { 1.80 + assert(!is_dead(), "invariant"); 1.81 + _dead = true; 1.82 +} 1.83 + 1.84 +void JfrThreadLocal::on_exit(JavaThread* thread) { 1.85 + if (JfrRecorder::is_recording()) { 1.86 + JfrCheckpointManager::write_thread_checkpoint(thread); 1.87 + JfrThreadCPULoadEvent::send_event_for_thread(thread); 1.88 + } 1.89 + thread->jfr_thread_local()->set_dead(); 1.90 +} 1.91 + 1.92 +void JfrThreadLocal::on_destruct(Thread* thread) { 1.93 + JfrThreadLocal* const tl = thread->jfr_thread_local(); 1.94 + if (tl->has_native_buffer()) { 1.95 + release(tl->native_buffer(), thread); 1.96 + } 1.97 + if (tl->has_java_buffer()) { 1.98 + release(tl->java_buffer(), thread); 1.99 + } 1.100 + assert(tl->shelved_buffer() == NULL, "invariant"); 1.101 + if (thread->jfr_thread_local()->has_java_event_writer()) { 1.102 + JfrJavaSupport::destroy_global_jni_handle(tl->java_event_writer()); 1.103 + } 1.104 + destroy_stackframes(thread); 1.105 +} 1.106 + 1.107 +JfrBuffer* JfrThreadLocal::acquire(Thread* thread, size_t size) { 1.108 + return JfrStorage::acquire_thread_local(thread, size); 1.109 +} 1.110 + 1.111 +void JfrThreadLocal::release(JfrBuffer* buffer, Thread* thread) { 1.112 + assert(buffer != NULL, "invariant"); 1.113 + JfrStorage::release_thread_local(buffer, thread); 1.114 +} 1.115 + 1.116 +JfrBuffer* JfrThreadLocal::install_native_buffer() const { 1.117 + assert(!has_native_buffer(), "invariant"); 1.118 + _native_buffer = acquire(Thread::current()); 1.119 + return _native_buffer; 1.120 +} 1.121 + 1.122 +JfrBuffer* JfrThreadLocal::install_java_buffer() const { 1.123 + assert(!has_java_buffer(), "invariant"); 1.124 + assert(!has_java_event_writer(), "invariant"); 1.125 + _java_buffer = acquire(Thread::current()); 1.126 + return _java_buffer; 1.127 +} 1.128 + 1.129 +JfrStackFrame* JfrThreadLocal::install_stackframes() const { 1.130 + assert(_stackframes == NULL, "invariant"); 1.131 + _stackdepth = (u4)JfrOptionSet::stackdepth(); 1.132 + guarantee(_stackdepth > 0, "Stackdepth must be > 0"); 1.133 + _stackframes = NEW_C_HEAP_ARRAY(JfrStackFrame, _stackdepth, mtTracing); 1.134 + return _stackframes; 1.135 +} 1.136 + 1.137 +void JfrThreadLocal::destroy_stackframes(Thread* thread) { 1.138 + assert(thread != NULL, "invariant"); 1.139 + JfrStackFrame* frames = thread->jfr_thread_local()->stackframes(); 1.140 + if (frames != NULL) { 1.141 + FREE_C_HEAP_ARRAY(JfrStackFrame, frames, mtTracing); 1.142 + thread->jfr_thread_local()->set_stackframes(NULL); 1.143 + } 1.144 +}