Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp
40948 views
1
/*
2
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
#include <assert.h>
25
#include <jni.h>
26
#include <jvmti.h>
27
#include <stdio.h>
28
#include "jni_tools.h"
29
30
extern "C" {
31
32
#define FIND_CLASS(_class, _className)\
33
if (!NSK_JNI_VERIFY(env, (_class = \
34
env->FindClass(_className)) != NULL))\
35
return
36
37
#define GET_OBJECT_CLASS(_class, _obj)\
38
if (!NSK_JNI_VERIFY(env, (_class = \
39
env->GetObjectClass(_obj)) != NULL))\
40
return
41
42
#define GET_STATIC_FIELD_ID(_fieldID, _class, _fieldName, _fieldSig)\
43
if (!NSK_JNI_VERIFY(env, (_fieldID = \
44
env->GetStaticFieldID(_class, _fieldName, _fieldSig)) != NULL))\
45
return
46
47
#define GET_STATIC_OBJ_FIELD(_value, _class, _fieldName, _fieldSig)\
48
GET_STATIC_FIELD_ID(field, _class, _fieldName, _fieldSig);\
49
_value = env->GetStaticObjectField(_class, field)
50
51
#define GET_STATIC_BOOL_FIELD(_value, _class, _fieldName)\
52
GET_STATIC_FIELD_ID(field, _class, _fieldName, "Z");\
53
_value = env->GetStaticBooleanField(_class, field)
54
55
#define GET_FIELD_ID(_fieldID, _class, _fieldName, _fieldSig)\
56
if (!NSK_JNI_VERIFY(env, (_fieldID = \
57
env->GetFieldID(_class, _fieldName, _fieldSig)) != NULL))\
58
return
59
60
#define GET_INT_FIELD(_value, _obj, _class, _fieldName)\
61
GET_FIELD_ID(field, _class, _fieldName, "I");\
62
_value = env->GetIntField(_obj, field)
63
64
#define GET_BOOL_FIELD(_value, _obj, _class, _fieldName)\
65
GET_FIELD_ID(field, _class, _fieldName, "Z");\
66
_value = env->GetBooleanField(_obj, field)
67
68
#define GET_LONG_FIELD(_value, _obj, _class, _fieldName)\
69
GET_FIELD_ID(field, _class, _fieldName, "J");\
70
_value = env->GetLongField(_obj, field)
71
72
#define GET_STATIC_INT_FIELD(_value, _class, _fieldName)\
73
GET_STATIC_FIELD_ID(field, _class, _fieldName, "I");\
74
_value = env->GetStaticIntField(_class, field)
75
76
#define SET_INT_FIELD(_obj, _class, _fieldName, _newValue)\
77
GET_FIELD_ID(field, _class, _fieldName, "I");\
78
env->SetIntField(_obj, field, _newValue)
79
80
#define GET_OBJ_FIELD(_value, _obj, _class, _fieldName, _fieldSig)\
81
GET_FIELD_ID(field, _class, _fieldName, _fieldSig);\
82
_value = env->GetObjectField(_obj, field)
83
84
85
#define GET_ARR_ELEMENT(_arr, _index)\
86
env->GetObjectArrayElement(_arr, _index)
87
88
#define SET_ARR_ELEMENT(_arr, _index, _newValue)\
89
env->SetObjectArrayElement(_arr, _index, _newValue)
90
91
#define GET_STATIC_METHOD_ID(_methodID, _class, _methodName, _sig)\
92
if (!NSK_JNI_VERIFY(env, (_methodID = \
93
env->GetStaticMethodID(_class, _methodName, _sig)) != NULL))\
94
return
95
96
#define GET_METHOD_ID(_methodID, _class, _methodName, _sig)\
97
if (!NSK_JNI_VERIFY(env, (_methodID = \
98
env->GetMethodID(_class, _methodName, _sig)) != NULL))\
99
return
100
101
#define CALL_STATIC_VOID_NOPARAM(_class, _methodName)\
102
GET_STATIC_METHOD_ID(method, _class, _methodName, "()V");\
103
if (!NSK_JNI_VERIFY_VOID(env, env->CallStaticVoidMethod(_class, method)))\
104
return
105
106
#define CALL_STATIC_VOID(_class, _methodName, _sig, _param)\
107
GET_STATIC_METHOD_ID(method, _class, _methodName, _sig);\
108
if (!NSK_JNI_VERIFY_VOID(env, env->CallStaticVoidMethod(_class, method, _param)))\
109
return
110
111
#define CALL_STATIC_OBJ(_value, _class, _methodName, _sig, _param)\
112
GET_STATIC_METHOD_ID(method, _class, _methodName, _sig);\
113
_value = env->CallStaticObjectMethod(_class, method, _param)
114
115
#define CALL_VOID_NOPARAM(_obj, _class, _methodName)\
116
GET_METHOD_ID(method, _class, _methodName, "()V");\
117
if (!NSK_JNI_VERIFY_VOID(env, env->CallVoidMethod(_obj, method)))\
118
return
119
120
#define CALL_VOID(_obj, _class, _methodName, _sig, _param)\
121
GET_METHOD_ID(method, _class, _methodName, "()V");\
122
if (!NSK_JNI_VERIFY_VOID(env, env->CallVoidMethod(_obj, method, _param)))\
123
return
124
125
#define CALL_VOID2(_obj, _class, _methodName, _sig, _param1, _param2)\
126
GET_METHOD_ID(method, _class, _methodName, _sig);\
127
if (!NSK_JNI_VERIFY_VOID(env, env->CallVoidMethod(_obj, method, _param1, _param2)))\
128
return
129
130
#define CALL_INT_NOPARAM(_value, _obj, _class, _methodName)\
131
GET_METHOD_ID(method, _class, _methodName, "()I");\
132
_value = env->CallIntMethod(_obj, method)
133
134
#define NEW_OBJ(_obj, _class, _constructorName, _sig, _params)\
135
GET_METHOD_ID(method, _class, _constructorName, _sig);\
136
if (!NSK_JNI_VERIFY(env, (_obj = \
137
env->NewObject(_class, method, _params)) != NULL))\
138
return
139
140
#define MONITOR_ENTER(x) \
141
NSK_JNI_VERIFY(env, env->MonitorEnter(x) == 0)
142
143
#define MONITOR_EXIT(x) \
144
NSK_JNI_VERIFY(env, env->MonitorExit(x) == 0)
145
146
#define TRACE(msg)\
147
GET_OBJ_FIELD(logger, obj, threadClass, "logger", "Lnsk/share/Log$Logger;");\
148
jmsg = env->NewStringUTF(msg);\
149
CALL_VOID2(logger, loggerClass, "trace",\
150
"(ILjava/lang/String;)V", 50, jmsg)
151
152
static const char *SctrlClassName="nsk/monitoring/share/ThreadController";
153
static const char *SthreadControllerSig
154
= "Lnsk/monitoring/share/ThreadController;";
155
156
static const char *SThreadsGroupLocksSig
157
="Lnsk/monitoring/share/ThreadsGroupLocks;";
158
static const char *SThreadsGroupLocksClassName
159
="nsk/monitoring/share/ThreadsGroupLocks";
160
161
162
static const char *SbringState_mn="bringState";
163
static const char *SnativeBringState_mn="nativeBringState";
164
static const char *SrecursiveMethod_mn="recursiveMethod";
165
static const char *SnativeRecursiveMethod_mn="nativeRecursiveMethod";
166
static const char *SloggerClassName = "nsk/share/Log$Logger";
167
168
static const char *Snoparams="()V";
169
static const char *Slongparam="(J)V";
170
171
/*
172
* Class: nsk_monitoring_share_BaseThread
173
* Method: nativeRecursiveMethod
174
* Signature: ()V
175
*/
176
JNIEXPORT void JNICALL
177
Java_nsk_monitoring_share_BaseThread_nativeRecursiveMethod(JNIEnv *env,
178
jobject obj) {
179
jint currDepth, maxDepth;
180
jobject logger;
181
jstring jmsg;
182
jfieldID field;
183
jmethodID method;
184
185
jobject controller;
186
jclass threadClass, ctrlClass, loggerClass;
187
188
int invocationType;
189
190
GET_OBJECT_CLASS(threadClass, obj);
191
FIND_CLASS(ctrlClass, SctrlClassName);
192
FIND_CLASS(loggerClass, SloggerClassName);
193
194
195
/* currDepth++ */
196
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
197
currDepth++;
198
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
199
200
GET_OBJ_FIELD(controller, obj, threadClass, "controller",
201
SthreadControllerSig);
202
GET_INT_FIELD(maxDepth, controller, ctrlClass, "maxDepth");
203
204
GET_STATIC_INT_FIELD(invocationType, ctrlClass, "invocationType");
205
206
if (maxDepth - currDepth > 0)
207
{
208
CALL_STATIC_VOID_NOPARAM(threadClass, "yield");
209
210
if (invocationType == 2/*MIXED_TYPE*/)
211
{
212
CALL_VOID_NOPARAM(obj, threadClass, SrecursiveMethod_mn);
213
}
214
else
215
{
216
CALL_VOID_NOPARAM(obj, threadClass, SnativeRecursiveMethod_mn);
217
}
218
}
219
else
220
{
221
TRACE("state has been reached");
222
if (invocationType == 2/*MIXED_TYPE*/)
223
{
224
CALL_VOID_NOPARAM(obj, threadClass, SbringState_mn);
225
}
226
else
227
{
228
CALL_VOID_NOPARAM(obj, threadClass, SnativeBringState_mn);
229
}
230
}
231
232
currDepth--;
233
GET_OBJECT_CLASS(threadClass, obj);
234
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
235
}
236
237
/*
238
* Class: nsk_monitoring_share_BlockedThread
239
* Method: nativeBringState
240
* Signature: ()V
241
*/
242
JNIEXPORT void JNICALL
243
Java_nsk_monitoring_share_BlockedThread_nativeBringState(JNIEnv *env,
244
jobject obj) {
245
jobject logger;
246
jstring jmsg;
247
jfieldID field;
248
jmethodID method;
249
250
jclass threadClass, loggerClass;
251
252
jobject STATE;
253
254
//ThreadsGroupLocks:
255
jclass ThreadsGroupLocks;
256
jobject threadsGroupLocks;
257
jmethodID getBarrier;
258
259
260
//CountDownLatch
261
jobject barrier;
262
jclass CountDownLatch;
263
264
//Blocker
265
jobject blocker;
266
jclass Blocker;
267
268
GET_OBJECT_CLASS(threadClass, obj);
269
270
FIND_CLASS(loggerClass, SloggerClassName);
271
FIND_CLASS(ThreadsGroupLocks, SThreadsGroupLocksClassName);
272
FIND_CLASS(Blocker, "Lnsk/monitoring/share/ThreadsGroupLocks$Blocker;");
273
FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");
274
275
GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", SThreadsGroupLocksSig);
276
GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");
277
GET_OBJ_FIELD(blocker, threadsGroupLocks, ThreadsGroupLocks, "blocker", "Lnsk/monitoring/share/ThreadsGroupLocks$Blocker;");
278
279
getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",
280
"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");
281
barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);
282
283
284
TRACE("entering to monitor");
285
286
CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");
287
CALL_VOID_NOPARAM(blocker, Blocker, "block");
288
TRACE("exiting from monitor");
289
290
}
291
292
/*
293
* Class: nsk_monitoring_share_WaitingThread
294
* Method: nativeBringState
295
* Signature: ()V
296
*/
297
JNIEXPORT void JNICALL
298
Java_nsk_monitoring_share_WaitingThread_nativeBringState(JNIEnv *env,
299
jobject obj) {
300
jobject logger;
301
jstring jmsg;
302
jfieldID field;
303
jmethodID method;
304
305
jclass threadClass, loggerClass;
306
307
//STATE
308
jobject STATE;
309
310
//ThreadsGroupLocks:
311
jclass ThreadsGroupLocks;
312
jobject threadsGroupLocks;
313
jmethodID getBarrier;
314
315
//CountDownLatch
316
jobject barrier;
317
jclass CountDownLatch;
318
319
GET_OBJECT_CLASS(threadClass, obj);
320
321
FIND_CLASS(loggerClass, SloggerClassName);
322
FIND_CLASS(ThreadsGroupLocks, "nsk/monitoring/share/ThreadsGroupLocks");
323
FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");
324
325
GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");
326
GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", "Lnsk/monitoring/share/ThreadsGroupLocks;");
327
328
getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",
329
"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");
330
barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);
331
CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");
332
333
TRACE("waiting on a monitor");
334
CALL_VOID_NOPARAM(barrier, CountDownLatch, "await");
335
}
336
337
/*
338
* Class: nsk_monitoring_share_SleepingThread
339
* Method: nativeBringState
340
* Signature: ()V
341
*/
342
JNIEXPORT void JNICALL
343
Java_nsk_monitoring_share_SleepingThread_nativeBringState(JNIEnv *env,
344
jobject obj) {
345
jfieldID field;
346
jmethodID method;
347
348
jclass threadClass, loggerClass;
349
350
//STATE
351
jobject STATE;
352
353
//ThreadsGroupLocks:
354
jclass ThreadsGroupLocks;
355
jobject threadsGroupLocks;
356
jmethodID getBarrier;
357
358
//CountDownLatch
359
jobject barrier;
360
jclass CountDownLatch;
361
362
//Thread
363
jclass Thread;
364
365
jlong sleepTime = 20 * 60 * 1000;
366
367
368
GET_OBJECT_CLASS(threadClass, obj);
369
370
FIND_CLASS(loggerClass, SloggerClassName);
371
FIND_CLASS(ThreadsGroupLocks, "nsk/monitoring/share/ThreadsGroupLocks");
372
FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");
373
374
GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");
375
GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", "Lnsk/monitoring/share/ThreadsGroupLocks;");
376
377
// Thread.sleep(3600 * 1000);
378
FIND_CLASS(Thread, "java/lang/Thread");
379
380
getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",
381
"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");
382
barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);
383
CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");
384
385
CALL_STATIC_VOID(Thread, "sleep", "(J)V", sleepTime);
386
}
387
388
/*
389
* Class: nsk_monitoring_share_RunningThread
390
* Method: nativeBringState
391
* Signature: ()V
392
*/
393
JNIEXPORT void JNICALL
394
Java_nsk_monitoring_share_RunningThread_nativeBringState(JNIEnv *env,
395
jobject obj) {
396
jobject logger;
397
jstring jmsg;
398
jfieldID field;
399
jmethodID method;
400
401
jclass threadClass, loggerClass;
402
403
//STATE
404
jobject STATE;
405
406
//ThreadsGroupLocks:
407
jclass ThreadsGroupLocks;
408
jobject threadsGroupLocks;
409
jmethodID getBarrier;
410
411
//CountDownLatch
412
jobject barrier;
413
jclass CountDownLatch;
414
415
//Thread
416
jclass Thread;
417
418
//runnableCanExit
419
jboolean flag = JNI_FALSE;
420
421
GET_OBJECT_CLASS(threadClass, obj);
422
423
FIND_CLASS(loggerClass, SloggerClassName);
424
FIND_CLASS(ThreadsGroupLocks, "nsk/monitoring/share/ThreadsGroupLocks");
425
FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");
426
427
GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");
428
GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", "Lnsk/monitoring/share/ThreadsGroupLocks;");
429
430
// Thread.sleep(3600 * 1000);
431
FIND_CLASS(Thread, "java/lang/Thread");
432
433
getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",
434
"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");
435
436
TRACE("running loop");
437
438
barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);
439
CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");
440
441
// while (!threadsGroupLocks.runnableCanExit.get()) {
442
// Thread.yield();
443
// }
444
while (flag == JNI_FALSE)
445
{
446
GET_BOOL_FIELD(flag, threadsGroupLocks, ThreadsGroupLocks, "runnableCanExit");
447
CALL_STATIC_VOID_NOPARAM(Thread, "yield");
448
}
449
450
}
451
452
jstring getStateName(JNIEnv *env, jint state) {
453
switch (state & JVMTI_JAVA_LANG_THREAD_STATE_MASK) {
454
case JVMTI_JAVA_LANG_THREAD_STATE_NEW:
455
return env->NewStringUTF("NEW");
456
case JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED:
457
return env->NewStringUTF("TERMINATED");
458
case JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE:
459
return env->NewStringUTF("RUNNABLE");
460
case JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED:
461
return env->NewStringUTF("BLOCKED");
462
case JVMTI_JAVA_LANG_THREAD_STATE_WAITING:
463
return env->NewStringUTF("WAITING");
464
case JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING:
465
return env->NewStringUTF("TIMED_WAITING");
466
}
467
// should never reach
468
assert(0);
469
return 0;
470
}
471
472
/*
473
* Class: nsk_monitoring_share_ThreadController
474
* Method: getThreadState
475
* Signature: (Ljava/lang/Thread;)Ljava/lang/Thread/State;
476
*/
477
JNIEXPORT jobject JNICALL
478
Java_nsk_monitoring_share_ThreadController_getThreadState(JNIEnv *env,
479
jobject obj, jobject thread) {
480
481
JavaVM *vm;
482
jvmtiEnv *jvmti;
483
jclass ThreadState;
484
jmethodID method;
485
jobject threadState;
486
jstring stateName;
487
jint state;
488
489
if (!NSK_VERIFY(env->GetJavaVM(&vm) == 0)) {
490
return NULL;
491
}
492
493
if (!NSK_VERIFY(vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1) == JNI_OK)) {
494
return NULL;
495
}
496
497
if (!NSK_VERIFY(jvmti->GetThreadState((jthread)thread, &state) == JVMTI_ERROR_NONE)) {
498
return NULL;
499
}
500
501
stateName = getStateName(env, state);
502
if (!NSK_JNI_VERIFY(env, (ThreadState = env->FindClass("java/lang/Thread$State")) != NULL))
503
return NULL;
504
505
if (!NSK_JNI_VERIFY(env, (method = env->GetStaticMethodID(ThreadState, "valueOf", "(Ljava/lang/String;)Ljava/lang/Thread$State;")) != NULL))
506
return NULL;
507
threadState = env->CallStaticObjectMethod(ThreadState, method, stateName);
508
509
return threadState;
510
}
511
512
}
513
514