31
31
import java .lang .management .MemoryPoolMXBean ;
32
32
import java .lang .management .MemoryType ;
33
33
import java .lang .management .MemoryUsage ;
34
+ import java .lang .management .ThreadMXBean ;
34
35
import java .nio .ByteBuffer ;
35
36
import java .util .Iterator ;
36
37
import java .util .List ;
78
79
import com .oracle .truffle .espresso .threads .EspressoThreadRegistry ;
79
80
import com .oracle .truffle .espresso .threads .State ;
80
81
import com .oracle .truffle .espresso .threads .ThreadAccess ;
82
+ import com .oracle .truffle .espresso .vm .structs .JmmOptionalSupport ;
81
83
82
84
@ GenerateNativeEnv (target = ManagementImpl .class , prependEnv = true )
83
85
public final class Management extends NativeEnv {
@@ -163,6 +165,7 @@ public final class Management extends NativeEnv {
163
165
private int managementVersion ;
164
166
165
167
private MemoryMXBean memoryMXBean ;
168
+ private ThreadMXBean threadMXBean ;
166
169
167
170
private final @ Pointer TruffleObject initializeManagementContext ;
168
171
private final @ Pointer TruffleObject disposeManagementContext ;
@@ -190,6 +193,14 @@ private MemoryMXBean getHostMemoryMXBean() {
190
193
return memoryMXBean ;
191
194
}
192
195
196
+ @ TruffleBoundary
197
+ private ThreadMXBean getHostThreadMXBean () {
198
+ if (threadMXBean == null ) {
199
+ threadMXBean = ManagementFactory .getThreadMXBean ();
200
+ }
201
+ return threadMXBean ;
202
+ }
203
+
193
204
/**
194
205
* Procedure to support a new management version in Espresso:
195
206
* <ul>
@@ -266,12 +277,16 @@ public int GetVersion() {
266
277
267
278
@ ManagementImpl
268
279
public int GetOptionalSupport (@ Pointer TruffleObject /* jmmOptionalSupport **/ supportPtr ) {
269
- if (!getUncached ().isNull (supportPtr )) {
270
- ByteBuffer supportBuf = NativeUtils .directByteBuffer (supportPtr , 8 );
271
- supportBuf .putInt (0 ); // nothing optional is supported
272
- return 0 ;
273
- }
274
- return -1 ;
280
+ if (getUncached ().isNull (supportPtr )) {
281
+ return -1 ;
282
+ }
283
+ ByteBuffer supportBuf = NativeUtils .directByteBuffer (supportPtr , 8 );
284
+ supportBuf .putInt (0 ); // clear
285
+ JmmOptionalSupport .JmmOptionalSupportWrapper optionalSupport = getVM ().getStructs ().jmmOptionalSupport .wrap (getHandles (), supportPtr );
286
+ ThreadMXBean hostBean = getHostThreadMXBean ();
287
+ optionalSupport .isOtherThreadCpuTimeSupported (hostBean .isThreadCpuTimeSupported () ? 1 : 0 );
288
+ optionalSupport .isCurrentThreadCpuTimeSupported (hostBean .isCurrentThreadCpuTimeSupported () ? 1 : 0 );
289
+ return 0 ;
275
290
}
276
291
277
292
private static void validateThreadIdArray (EspressoLanguage language , Meta meta , @ JavaType (long [].class ) StaticObject threadIds , SubstitutionProfiler profiler ) {
@@ -286,6 +301,18 @@ private static void validateThreadIdArray(EspressoLanguage language, Meta meta,
286
301
}
287
302
}
288
303
304
+ private static int validateThreadIdArray (EspressoLanguage language , Meta meta , @ JavaType (long [].class ) StaticObject threadIds ) {
305
+ assert threadIds .isArray ();
306
+ int numThreads = threadIds .length (language );
307
+ for (int i = 0 ; i < numThreads ; ++i ) {
308
+ long tid = threadIds .<long []> unwrap (language )[i ];
309
+ if (tid <= 0 ) {
310
+ throw meta .throwIllegalArgumentExceptionBoundary ("Invalid thread ID entry" );
311
+ }
312
+ }
313
+ return numThreads ;
314
+ }
315
+
289
316
private static void validateThreadInfoArray (Meta meta , @ JavaType (internalName = "[Ljava/lang/management/ThreadInfo;" ) StaticObject infoArray , SubstitutionProfiler profiler ) {
290
317
// check if the element of infoArray is of type ThreadInfo class
291
318
Klass infoArrayKlass = infoArray .getKlass ();
@@ -909,5 +936,56 @@ public boolean ResetStatistic(@SuppressWarnings("unused") long obj, /* jmmStatis
909
936
return false ;
910
937
}
911
938
939
+ @ ManagementImpl
940
+ public long GetThreadCpuTimeWithKind (long threadId , boolean withSysTime ,
941
+ @ Inject Meta meta ) {
942
+ if (threadId < 0 ) {
943
+ throw meta .throwIllegalArgumentExceptionBoundary ("Invalid thread ID" );
944
+ }
945
+ ThreadMXBean hostBean = getHostThreadMXBean ();
946
+ if (threadId == 0 ) {
947
+ if (!hostBean .isCurrentThreadCpuTimeSupported ()) {
948
+ return -1 ;
949
+ }
950
+ long id = EspressoThreadRegistry .getThreadId (Thread .currentThread ());
951
+ return withSysTime ? hostBean .getThreadCpuTime (id ) : hostBean .getThreadUserTime (id );
952
+ }
953
+ StaticObject [] activeThreads = getContext ().getActiveThreads ();
954
+ StaticObject thread = findThreadById (activeThreads , threadId );
955
+ if (getThreadAccess ().isVirtualThread (thread )) {
956
+ return -1 ;
957
+ }
958
+ Thread host = getThreadAccess ().getHost (thread );
959
+ long hostId = EspressoThreadRegistry .getThreadId (host );
960
+ return withSysTime ? hostBean .getThreadCpuTime (hostId ) : hostBean .getThreadUserTime (hostId );
961
+ }
962
+
963
+ @ ManagementImpl
964
+ public void GetThreadCpuTimesWithKind (@ JavaType (long [].class ) StaticObject threadIds , @ JavaType (long [].class ) StaticObject times , boolean withSysTime ,
965
+ @ Inject EspressoLanguage language , @ Inject Meta meta ) {
966
+ if (StaticObject .isNull (threadIds ) || StaticObject .isNull (times )) {
967
+ throw meta .throwNullPointerExceptionBoundary ();
968
+ }
969
+ int length = validateThreadIdArray (language , meta , threadIds );
970
+ if (length != times .length (language )) {
971
+ throw meta .throwIllegalArgumentExceptionBoundary ("The length of the given long array does not match the length of the given array of thread IDs" );
972
+ }
973
+
974
+ StaticObject [] activeThreads = getContext ().getActiveThreads ();
975
+ InterpreterToVM interpreterToVM = getInterpreterToVM ();
976
+ ThreadMXBean hostBean = getHostThreadMXBean ();
977
+ for (int i = 0 ; i < length ; i ++) {
978
+ long guestId = interpreterToVM .getArrayLong (language , i , threadIds );
979
+ StaticObject thread = findThreadById (activeThreads , guestId );
980
+ if (getThreadAccess ().isVirtualThread (thread )) {
981
+ continue ;
982
+ }
983
+ Thread host = getThreadAccess ().getHost (thread );
984
+ long hostId = EspressoThreadRegistry .getThreadId (host );
985
+ long time = withSysTime ? hostBean .getThreadCpuTime (hostId ) : hostBean .getThreadUserTime (hostId );
986
+ interpreterToVM .setArrayLong (language , time , i , times );
987
+ }
988
+ }
989
+
912
990
// Checkstyle: resume method name check
913
991
}
0 commit comments