Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_cpu.c
38829 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940#include "hprof.h"4142/* This file contains the cpu loop for the option cpu=samples */4344/* The cpu_loop thread basically waits for gdata->sample_interval millisecs45* then wakes up, and for each running thread it gets their stack trace,46* and updates the traces with 'hits'.47*48* No threads are suspended or resumed, and the thread sampling is in the49* file hprof_tls.c, which manages all active threads. The sampling50* technique (what is sampled) is also in hprof_tls.c.51*52* No adjustments are made to the pause time or sample interval except53* by the user via the interval=n option (default is 10ms).54*55* This thread can cause havoc when started prematurely or not terminated56* properly, see cpu_sample_init() and cpu_term(), and their calls in hprof_init.c.57*58* The listener loop (hprof_listener.c) can dynamically turn on or off the59* sampling of all or selected threads.60*61*/6263/* Private functions */6465static void JNICALL66cpu_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p)67{68int loop_trip_counter;69jboolean cpu_loop_running;7071loop_trip_counter = 0;7273rawMonitorEnter(gdata->cpu_loop_lock); {74gdata->cpu_loop_running = JNI_TRUE;75cpu_loop_running = gdata->cpu_loop_running;76/* Notify cpu_sample_init() that we have started */77rawMonitorNotifyAll(gdata->cpu_loop_lock);78} rawMonitorExit(gdata->cpu_loop_lock);7980rawMonitorEnter(gdata->cpu_sample_lock); /* Only waits inside loop let go */8182while ( cpu_loop_running ) {8384++loop_trip_counter;8586LOG3("cpu_loop()", "iteration", loop_trip_counter);8788/* If a dump is in progress, we pause sampling. */89rawMonitorEnter(gdata->dump_lock); {90if (gdata->dump_in_process) {91gdata->pause_cpu_sampling = JNI_TRUE;92}93} rawMonitorExit(gdata->dump_lock);9495/* Check to see if we need to pause sampling (listener_loop command) */96if (gdata->pause_cpu_sampling) {9798/*99* Pause sampling for now. Reset sample controls if100* sampling is resumed again.101*/102103rawMonitorWait(gdata->cpu_sample_lock, 0);104105rawMonitorEnter(gdata->cpu_loop_lock); {106cpu_loop_running = gdata->cpu_loop_running;107} rawMonitorExit(gdata->cpu_loop_lock);108109/* Continue the while loop, which will terminate if done. */110continue;111}112113/* This is the normal short timed wait before getting a sample */114rawMonitorWait(gdata->cpu_sample_lock, (jlong)gdata->sample_interval);115116/* Make sure we really want to continue */117rawMonitorEnter(gdata->cpu_loop_lock); {118cpu_loop_running = gdata->cpu_loop_running;119} rawMonitorExit(gdata->cpu_loop_lock);120121/* Break out if we are done */122if ( !cpu_loop_running ) {123break;124}125126/*127* If a dump request came in after we checked at the top of128* the while loop, then we catch that fact here. We129* don't want to perturb the data that is being dumped so130* we just ignore the data from this sampling loop.131*/132rawMonitorEnter(gdata->dump_lock); {133if (gdata->dump_in_process) {134gdata->pause_cpu_sampling = JNI_TRUE;135}136} rawMonitorExit(gdata->dump_lock);137138/* Sample all the threads and update trace costs */139if ( !gdata->pause_cpu_sampling) {140tls_sample_all_threads(env);141}142143/* Check to see if we need to finish */144rawMonitorEnter(gdata->cpu_loop_lock); {145cpu_loop_running = gdata->cpu_loop_running;146} rawMonitorExit(gdata->cpu_loop_lock);147148}149rawMonitorExit(gdata->cpu_sample_lock);150151rawMonitorEnter(gdata->cpu_loop_lock); {152/* Notify cpu_sample_term() that we are done. */153rawMonitorNotifyAll(gdata->cpu_loop_lock);154} rawMonitorExit(gdata->cpu_loop_lock);155156LOG2("cpu_loop()", "clean termination");157}158159/* External functions */160161void162cpu_sample_init(JNIEnv *env)163{164gdata->cpu_sampling = JNI_TRUE;165166/* Create the raw monitors needed */167gdata->cpu_loop_lock = createRawMonitor("HPROF cpu loop lock");168gdata->cpu_sample_lock = createRawMonitor("HPROF cpu sample lock");169170rawMonitorEnter(gdata->cpu_loop_lock); {171createAgentThread(env, "HPROF cpu sampling thread",172&cpu_loop_function);173/* Wait for cpu_loop_function() to notify us it has started. */174rawMonitorWait(gdata->cpu_loop_lock, 0);175} rawMonitorExit(gdata->cpu_loop_lock);176}177178void179cpu_sample_off(JNIEnv *env, ObjectIndex object_index)180{181jint count;182183count = 1;184if (object_index != 0) {185tls_set_sample_status(object_index, 0);186count = tls_sum_sample_status();187}188if ( count == 0 ) {189gdata->pause_cpu_sampling = JNI_TRUE;190} else {191gdata->pause_cpu_sampling = JNI_FALSE;192}193}194195void196cpu_sample_on(JNIEnv *env, ObjectIndex object_index)197{198if ( gdata->cpu_loop_lock == NULL ) {199cpu_sample_init(env);200}201202if (object_index == 0) {203gdata->cpu_sampling = JNI_TRUE;204gdata->pause_cpu_sampling = JNI_FALSE;205} else {206jint count;207208tls_set_sample_status(object_index, 1);209count = tls_sum_sample_status();210if ( count > 0 ) {211gdata->pause_cpu_sampling = JNI_FALSE;212}213}214215/* Notify the CPU sampling thread that sampling is on */216rawMonitorEnter(gdata->cpu_sample_lock); {217rawMonitorNotifyAll(gdata->cpu_sample_lock);218} rawMonitorExit(gdata->cpu_sample_lock);219220}221222void223cpu_sample_term(JNIEnv *env)224{225gdata->pause_cpu_sampling = JNI_FALSE;226rawMonitorEnter(gdata->cpu_sample_lock); {227/* Notify the CPU sampling thread to get out of any sampling Wait */228rawMonitorNotifyAll(gdata->cpu_sample_lock);229} rawMonitorExit(gdata->cpu_sample_lock);230rawMonitorEnter(gdata->cpu_loop_lock); {231if ( gdata->cpu_loop_running ) {232gdata->cpu_loop_running = JNI_FALSE;233/* Wait for cpu_loop_function() thread to tell us it completed. */234rawMonitorWait(gdata->cpu_loop_lock, 0);235}236} rawMonitorExit(gdata->cpu_loop_lock);237}238239240