From 3777a2acca37cf3e6063df4ea780fbe729036193 Mon Sep 17 00:00:00 2001 From: Gengchen Tuo Date: Thu, 10 Oct 2024 11:45:49 -0400 Subject: [PATCH] Add omrthread_get_self_thread_time() This function returns the user and system cpu time of the calling thread. This new function is needed because the only way that we're aware of to get the user CPU time of a thread is to use getrusage(RUSAGE_THREAD, ...) which can only be called on the current thread. Related: https://github.com/eclipse-openj9/openj9/pull/20186 Signed-off-by: Gengchen Tuo --- include_core/thread_api.h | 14 ++++++++++++++ thread/common/thrprof.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include_core/thread_api.h b/include_core/thread_api.h index 8fd03718435..285ca031bcc 100644 --- a/include_core/thread_api.h +++ b/include_core/thread_api.h @@ -98,6 +98,11 @@ typedef struct omrthread_monitor_walk_state_t { BOOLEAN lockTaken; } omrthread_monitor_walk_state_t; +typedef struct omrthread_thread_time_t { + int64_t userTime; + int64_t sysTime; +} omrthread_thread_time_t; + /* ---------------- omrthreadinspect.c ---------------- */ /** @@ -1424,6 +1429,15 @@ omrthread_monitor_pin(omrthread_monitor_t monitor, omrthread_t self); void omrthread_monitor_unpin(omrthread_monitor_t monitor, omrthread_t self); +/** + * Gets the system and user CPU time of the current thread + * + * @param[out] threadTime the pointer to the thread time structure + * @return 0 on success or -1 on failure + */ +intptr_t +omrthread_get_self_thread_time(omrthread_thread_time_t *threadTime); + /* forward struct definition */ struct J9ThreadLibrary; diff --git a/thread/common/thrprof.c b/thread/common/thrprof.c index 023085ff616..cc2cb7bb581 100644 --- a/thread/common/thrprof.c +++ b/thread/common/thrprof.c @@ -28,6 +28,11 @@ * APIs for querying per-thread statistics: CPU usage, stack usage. */ +#if defined (LINUX) +#define _GNU_SOURCE +#include +#endif /* defined (LINUX) */ + #include /* for memset() */ #include "omrcfg.h" @@ -1025,3 +1030,34 @@ omrthread_get_jvm_cpu_usage_info_error_recovery(void) GLOBAL_UNLOCK_SIMPLE(lib); } } + +intptr_t +omrthread_get_self_thread_time(omrthread_thread_time_t *threadTime) { + #if defined(LINUX) + struct rusage rUsage = {0}; + int rc = getrusage(RUSAGE_THREAD, &rUsage); + + if (-1 == rc) { + return -1; + } + + threadTime->userTime = (SEC_TO_NANO_CONVERSION_CONSTANT * (int64_t)rUsage.ru_utime.tv_sec) + + (MICRO_TO_NANO_CONVERSION_CONSTANT * (int64_t)rUsage.ru_utime.tv_usec); + threadTime->sysTime = (SEC_TO_NANO_CONVERSION_CONSTANT * (int64_t)rUsage.ru_stime.tv_sec) + + (MICRO_TO_NANO_CONVERSION_CONSTANT * (int64_t)rUsage.ru_stime.tv_usec); +#else /* defined(LINUX) */ + omrthread_t self = omrthread_self(); + + int64_t userTime = omrthread_get_user_time(self); + int64_t cpuTime = omrthread_get_cpu_time(self); + + if (-1 == cpuTime || -1 == userTime) { + return -1; + } + + threadTime->sysTime = cpuTime - userTime; + threadTime->userTime = userTime; +#endif /* defined(LINUX) */ + + return 0; +}