Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_cpu.c
38829 views
1
/*
2
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
*
8
* - Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
*
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* - Neither the name of Oracle nor the names of its
16
* contributors may be used to endorse or promote products derived
17
* from this software without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32
/*
33
* This source code is provided to illustrate the usage of a given feature
34
* or technique and has been deliberately simplified. Additional steps
35
* required for a production-quality application, such as security checks,
36
* input validation and proper error handling, might not be present in
37
* this sample code.
38
*/
39
40
41
#include "hprof.h"
42
43
/* This file contains the cpu loop for the option cpu=samples */
44
45
/* The cpu_loop thread basically waits for gdata->sample_interval millisecs
46
* then wakes up, and for each running thread it gets their stack trace,
47
* and updates the traces with 'hits'.
48
*
49
* No threads are suspended or resumed, and the thread sampling is in the
50
* file hprof_tls.c, which manages all active threads. The sampling
51
* technique (what is sampled) is also in hprof_tls.c.
52
*
53
* No adjustments are made to the pause time or sample interval except
54
* by the user via the interval=n option (default is 10ms).
55
*
56
* This thread can cause havoc when started prematurely or not terminated
57
* properly, see cpu_sample_init() and cpu_term(), and their calls in hprof_init.c.
58
*
59
* The listener loop (hprof_listener.c) can dynamically turn on or off the
60
* sampling of all or selected threads.
61
*
62
*/
63
64
/* Private functions */
65
66
static void JNICALL
67
cpu_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p)
68
{
69
int loop_trip_counter;
70
jboolean cpu_loop_running;
71
72
loop_trip_counter = 0;
73
74
rawMonitorEnter(gdata->cpu_loop_lock); {
75
gdata->cpu_loop_running = JNI_TRUE;
76
cpu_loop_running = gdata->cpu_loop_running;
77
/* Notify cpu_sample_init() that we have started */
78
rawMonitorNotifyAll(gdata->cpu_loop_lock);
79
} rawMonitorExit(gdata->cpu_loop_lock);
80
81
rawMonitorEnter(gdata->cpu_sample_lock); /* Only waits inside loop let go */
82
83
while ( cpu_loop_running ) {
84
85
++loop_trip_counter;
86
87
LOG3("cpu_loop()", "iteration", loop_trip_counter);
88
89
/* If a dump is in progress, we pause sampling. */
90
rawMonitorEnter(gdata->dump_lock); {
91
if (gdata->dump_in_process) {
92
gdata->pause_cpu_sampling = JNI_TRUE;
93
}
94
} rawMonitorExit(gdata->dump_lock);
95
96
/* Check to see if we need to pause sampling (listener_loop command) */
97
if (gdata->pause_cpu_sampling) {
98
99
/*
100
* Pause sampling for now. Reset sample controls if
101
* sampling is resumed again.
102
*/
103
104
rawMonitorWait(gdata->cpu_sample_lock, 0);
105
106
rawMonitorEnter(gdata->cpu_loop_lock); {
107
cpu_loop_running = gdata->cpu_loop_running;
108
} rawMonitorExit(gdata->cpu_loop_lock);
109
110
/* Continue the while loop, which will terminate if done. */
111
continue;
112
}
113
114
/* This is the normal short timed wait before getting a sample */
115
rawMonitorWait(gdata->cpu_sample_lock, (jlong)gdata->sample_interval);
116
117
/* Make sure we really want to continue */
118
rawMonitorEnter(gdata->cpu_loop_lock); {
119
cpu_loop_running = gdata->cpu_loop_running;
120
} rawMonitorExit(gdata->cpu_loop_lock);
121
122
/* Break out if we are done */
123
if ( !cpu_loop_running ) {
124
break;
125
}
126
127
/*
128
* If a dump request came in after we checked at the top of
129
* the while loop, then we catch that fact here. We
130
* don't want to perturb the data that is being dumped so
131
* we just ignore the data from this sampling loop.
132
*/
133
rawMonitorEnter(gdata->dump_lock); {
134
if (gdata->dump_in_process) {
135
gdata->pause_cpu_sampling = JNI_TRUE;
136
}
137
} rawMonitorExit(gdata->dump_lock);
138
139
/* Sample all the threads and update trace costs */
140
if ( !gdata->pause_cpu_sampling) {
141
tls_sample_all_threads(env);
142
}
143
144
/* Check to see if we need to finish */
145
rawMonitorEnter(gdata->cpu_loop_lock); {
146
cpu_loop_running = gdata->cpu_loop_running;
147
} rawMonitorExit(gdata->cpu_loop_lock);
148
149
}
150
rawMonitorExit(gdata->cpu_sample_lock);
151
152
rawMonitorEnter(gdata->cpu_loop_lock); {
153
/* Notify cpu_sample_term() that we are done. */
154
rawMonitorNotifyAll(gdata->cpu_loop_lock);
155
} rawMonitorExit(gdata->cpu_loop_lock);
156
157
LOG2("cpu_loop()", "clean termination");
158
}
159
160
/* External functions */
161
162
void
163
cpu_sample_init(JNIEnv *env)
164
{
165
gdata->cpu_sampling = JNI_TRUE;
166
167
/* Create the raw monitors needed */
168
gdata->cpu_loop_lock = createRawMonitor("HPROF cpu loop lock");
169
gdata->cpu_sample_lock = createRawMonitor("HPROF cpu sample lock");
170
171
rawMonitorEnter(gdata->cpu_loop_lock); {
172
createAgentThread(env, "HPROF cpu sampling thread",
173
&cpu_loop_function);
174
/* Wait for cpu_loop_function() to notify us it has started. */
175
rawMonitorWait(gdata->cpu_loop_lock, 0);
176
} rawMonitorExit(gdata->cpu_loop_lock);
177
}
178
179
void
180
cpu_sample_off(JNIEnv *env, ObjectIndex object_index)
181
{
182
jint count;
183
184
count = 1;
185
if (object_index != 0) {
186
tls_set_sample_status(object_index, 0);
187
count = tls_sum_sample_status();
188
}
189
if ( count == 0 ) {
190
gdata->pause_cpu_sampling = JNI_TRUE;
191
} else {
192
gdata->pause_cpu_sampling = JNI_FALSE;
193
}
194
}
195
196
void
197
cpu_sample_on(JNIEnv *env, ObjectIndex object_index)
198
{
199
if ( gdata->cpu_loop_lock == NULL ) {
200
cpu_sample_init(env);
201
}
202
203
if (object_index == 0) {
204
gdata->cpu_sampling = JNI_TRUE;
205
gdata->pause_cpu_sampling = JNI_FALSE;
206
} else {
207
jint count;
208
209
tls_set_sample_status(object_index, 1);
210
count = tls_sum_sample_status();
211
if ( count > 0 ) {
212
gdata->pause_cpu_sampling = JNI_FALSE;
213
}
214
}
215
216
/* Notify the CPU sampling thread that sampling is on */
217
rawMonitorEnter(gdata->cpu_sample_lock); {
218
rawMonitorNotifyAll(gdata->cpu_sample_lock);
219
} rawMonitorExit(gdata->cpu_sample_lock);
220
221
}
222
223
void
224
cpu_sample_term(JNIEnv *env)
225
{
226
gdata->pause_cpu_sampling = JNI_FALSE;
227
rawMonitorEnter(gdata->cpu_sample_lock); {
228
/* Notify the CPU sampling thread to get out of any sampling Wait */
229
rawMonitorNotifyAll(gdata->cpu_sample_lock);
230
} rawMonitorExit(gdata->cpu_sample_lock);
231
rawMonitorEnter(gdata->cpu_loop_lock); {
232
if ( gdata->cpu_loop_running ) {
233
gdata->cpu_loop_running = JNI_FALSE;
234
/* Wait for cpu_loop_function() thread to tell us it completed. */
235
rawMonitorWait(gdata->cpu_loop_lock, 0);
236
}
237
} rawMonitorExit(gdata->cpu_loop_lock);
238
}
239
240