From fb9758e1e7d8faf95e41d7a8364700322245bf05 Mon Sep 17 00:00:00 2001 From: Gengchen Tuo Date: Thu, 10 Oct 2024 11:45:49 -0400 Subject: [PATCH] Add omrthread_get_thread_times() This function returns the user and system cpu time of the calling thread. This new function is needed so we can get both user time and system time using only one system call. Related: https://github.com/eclipse-openj9/openj9/pull/20186 Signed-off-by: Gengchen Tuo --- include_core/thread_api.h | 14 ++++++++ thread/common/thrprof.c | 76 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/include_core/thread_api.h b/include_core/thread_api.h index 8fd03718435..ff93bec9ac7 100644 --- a/include_core/thread_api.h +++ b/include_core/thread_api.h @@ -62,6 +62,11 @@ typedef struct omrthread_process_time_t { int64_t _userTime; } omrthread_process_time_t; +typedef struct omrthread_thread_time_t { + int64_t userTime; + int64_t sysTime; +} omrthread_thread_time_t; + typedef struct omrthread_state_t { uintptr_t flags; omrthread_monitor_t blocker; @@ -1240,6 +1245,15 @@ omrthread_get_jvm_cpu_usage_info(J9ThreadsCpuUsage *cpuUsage); void omrthread_get_jvm_cpu_usage_info_error_recovery(void); +/** + * 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_thread_times(omrthread_thread_time_t *threadTime); + /* ---------------- omrthreadattr.c ---------------- */ /** diff --git a/thread/common/thrprof.c b/thread/common/thrprof.c index 023085ff616..f9b5eff978d 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,74 @@ omrthread_get_jvm_cpu_usage_info_error_recovery(void) GLOBAL_UNLOCK_SIMPLE(lib); } } + +intptr_t +omrthread_get_thread_times(omrthread_thread_time_t *threadTime) +{ +#if defined(LINUX) + struct rusage rUsage; + memset(&rUsage, 0, sizeof(rUsage)); + + if (-1 != getrusage(RUSAGE_THREAD, &rUsage)) { + 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); + + return 0; + } + + return -1; +#elif defined(OMR_OS_WINDOWS) && !defined(BREW) /* defined(LINUX) */ + + omrthread_t self = omrthread_self(); + FILETIME creationTime, exitTime, kernelTime, userTime; + + /* WARNING! Not supported on Win95! Need to test to ensure this fails gracefully */ + + if (GetThreadTimes(self->handle, &creationTime, &exitTime, &kernelTime, &userTime)) { + /* Time is in 100's of nanos. Convert to nanos */ + threadTime->sysTime = ((int64_t)kernelTime.dwLowDateTime | ((int64_t)kernelTime.dwHighDateTime << 32)) * 100; + threadTime->userTime = ((int64_t)userTime.dwLowDateTime | ((int64_t)userTime.dwHighDateTime << 32)) * 100; + + return 0; + } + + return -1; +#elif defined(AIXPPC) /* defined(OMR_OS_WINDOWS) && !defined(BREW) */ + + omrthread_t self = omrthread_self(); + + /* AIX provides a function call that returns an entire structure of + * information about the thread. + */ + + struct rusage rUsage; + + memset(&rUsage, 0, sizeof(rUsage)); + if (0 == pthread_getrusage_np(self->handle, &rUsage, PTHRDSINFO_RUSAGE_COLLECT)) { + 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); + return 0; + } + + return -1; +#else /* defined(AIXPPC) */ + + omrthread_t self = omrthread_self(); + + int64_t userTime = omrthread_get_self_user_time(self); + int64_t cpuTime = omrthread_get_self_cpu_time(self); + + if ((-1 == cpuTime) || (-1 == userTime)) { + return -1; + } + + threadTime->sysTime = cpuTime - userTime; + threadTime->userTime = userTime; + + return 0; +#endif +}