From 4849c608fdc2cb01cdb8cdfaf9fd5f366496991f Mon Sep 17 00:00:00 2001 From: Amarpreet Singh Date: Tue, 2 Jan 2024 11:24:24 -0500 Subject: [PATCH] Get the process start time Get the process start time on linux, windows, osx, aix and z/os. Issue: https://github.com/eclipse/omr/issues/7201 Signed-off-by: Amarpreet Singh --- fvtest/porttest/si.cpp | 74 +++++++++++++++ include_core/omrport.h | 3 + nls/portnls.h | 3 + port/common/omrport.c | 1 + port/common/omrport.tdf | 10 ++ port/common/omrsysinfo.c | 12 +++ port/omrportpriv.h | 2 + port/unix/omrsysinfo.c | 109 +++++++++++++++++++++ port/win32/omrsysinfo.c | 31 ++++++ port/win32/omrtime.c | 2 +- port/zos390/omrgetthent.h | 182 ++++++++++++++++++++++++++++++++++++ port/zos390/omrintrospect.h | 148 +---------------------------- 12 files changed, 429 insertions(+), 148 deletions(-) create mode 100644 port/zos390/omrgetthent.h diff --git a/fvtest/porttest/si.cpp b/fvtest/porttest/si.cpp index b8eafbcfd10..d1c473ed8b1 100644 --- a/fvtest/porttest/si.cpp +++ b/fvtest/porttest/si.cpp @@ -52,6 +52,12 @@ #endif /* defined(J9ZOS390) */ #include /* For RLIM_INFINITY */ #endif /* !defined(OMR_OS_WINDOWS) */ +#if defined(OMR_OS_WINDOWS) +#include +#else /* defined(OMR_OS_WINDOWS) */ +#include +#include +#endif /* defined(OMR_OS_WINDOWS) */ #if defined(J9ZOS390) && !defined(OMR_EBCDIC) #include "atoe.h" @@ -3119,3 +3125,71 @@ TEST(PortSysinfoTest, GetProcessorDescription) ASSERT_TRUE(feature == TRUE || feature == FALSE); } } + +/* The method omrsysinfo_get_process_start_time is not implemented on z/TPF. */ +#if !defined(OMRZTPF) +/** + * Test: GetProcessorStartTimeOfNonExistingProcessTest. + * Description: Verify that getting the process start time for a non-existing process (UINTPTR_MAX) results in 0 nanoseconds. + * Passing Condition: The expected process start time is 0 nanoseconds, and the actual process start time matches this value. + */ +TEST(PortSysinfoTest, GetProcessorStartTimeOfNonExistingProcessTest) +{ + OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary()); + /* + * If a pid of UINTPTR_MAX exists in the future then the test will need to be modified. + * UINTPTR_MAX represents the maximum unsigned integer value, which can be a 32-bit or a 64-bit depending on the system. + * On unix systems, a pid is represented by pid_t, which can be a 32-bit or a 64-bit signed integer. + * On windows systems, a pid is represented by DWORD, which is a 32-bit unsigned integer, and + * the maximum value of DWORD is not a valid pid as it is reserved for use by the ASFW_ANY parameter. + */ + uintptr_t pid = UINTPTR_MAX; + uint64_t expectedProcessStartTimeInNanoseconds = 0; + uint64_t actualProcessStartTimeInNanoseconds = omrsysinfo_get_process_start_time(pid); + ASSERT_EQ(expectedProcessStartTimeInNanoseconds, actualProcessStartTimeInNanoseconds); +} + +/** + * Test: GetProcessorStartTimeOfExistingProcessTest. + * Description: Verify that getting the process start time for an existing process results in a valid timestamp. + * Passing Condition: The process start time is greater than the test start time and less than the current time at the end of the test. + */ +TEST(PortSysinfoTest, GetProcessorStartTimeOfExistingProcessTest) +{ + OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary()); + uintptr_t pid = UINTPTR_MAX; + uintptr_t success = 0; + uint64_t testStartTimeInNanoseconds = omrtime_current_time_nanos(&success); + uint64_t processStartTimeInNanoseconds = 0; +#if defined(LINUX) || defined(OSX) || defined(AIXPPC) || defined(J9ZOS390) + int status = 0; + sleep(3); + pid = fork(); + ASSERT_NE(pid, -1); + /* The if block will only be invoked by the child process. */ + if (0 == pid) { + sleep(10); + /* A call to exit allows the child process to stop and avoids a timeout on x86-64 macOS. */ + exit(0); + } + processStartTimeInNanoseconds = omrsysinfo_get_process_start_time(pid); + waitpid(pid, &status, 0); +#elif defined(OMR_OS_WINDOWS) /* defined(LINUX) || defined(OSX) || defined(AIXPPC) || defined(J9ZOS390) */ + STARTUPINFO si; + PROCESS_INFORMATION pi; + BOOL ret = FALSE; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + ret = CreateProcess(NULL, "cmd.exe /c timeout /t 10", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ASSERT_EQ(ret, TRUE); + pid = (uintptr_t)GetProcessId(pi.hProcess); + processStartTimeInNanoseconds = omrsysinfo_get_process_start_time(pid); + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); +#endif /* defined(LINUX) || defined(OSX) || defined(AIXPPC) || defined(J9ZOS390) */ + ASSERT_GT(processStartTimeInNanoseconds, testStartTimeInNanoseconds); + ASSERT_LT(processStartTimeInNanoseconds, omrtime_current_time_nanos(&success)); +} +#endif /* !defined(OMRZTPF) */ diff --git a/include_core/omrport.h b/include_core/omrport.h index 01895a32363..90c15d8a717 100644 --- a/include_core/omrport.h +++ b/include_core/omrport.h @@ -2459,6 +2459,8 @@ typedef struct OMRPortLibrary { int32_t (*sysinfo_cgroup_subsystem_iterator_next)(struct OMRPortLibrary *portLibrary, struct OMRCgroupMetricIteratorState *state, struct OMRCgroupMetricElement *metricElement); /** see @ref omrsysinfo.c::omrsysinfo_cgroup_subsystem_iterator_destroy "omrsysinfo_cgroup_subsystem_iterator_destroy"*/ void (*sysinfo_cgroup_subsystem_iterator_destroy)(struct OMRPortLibrary *portLibrary, struct OMRCgroupMetricIteratorState *state); + /** see @ref omrsysinfo.c::omrsysinfo_get_process_start_time "omrsysinfo_get_process_start_time"*/ + uint64_t (*sysinfo_get_process_start_time)(struct OMRPortLibrary *portLibrary, uintptr_t pid); /** see @ref omrport.c::omrport_init_library "omrport_init_library"*/ int32_t (*port_init_library)(struct OMRPortLibrary *portLibrary, uintptr_t size) ; /** see @ref omrport.c::omrport_startup_library "omrport_startup_library"*/ @@ -3102,6 +3104,7 @@ extern J9_CFUNC int32_t omrport_getVersion(struct OMRPortLibrary *portLibrary); #define omrsysinfo_cgroup_subsystem_iterator_metricKey(param1, param2) privateOmrPortLibrary->sysinfo_cgroup_subsystem_iterator_metricKey(privateOmrPortLibrary, param1, param2) #define omrsysinfo_cgroup_subsystem_iterator_next(param1, param2) privateOmrPortLibrary->sysinfo_cgroup_subsystem_iterator_next(privateOmrPortLibrary, param1, param2) #define omrsysinfo_cgroup_subsystem_iterator_destroy(param1) privateOmrPortLibrary->sysinfo_cgroup_subsystem_iterator_destroy(privateOmrPortLibrary, param1) +#define omrsysinfo_get_process_start_time(param1) privateOmrPortLibrary->sysinfo_get_process_start_time(privateOmrPortLibrary, param1) #define omrintrospect_startup() privateOmrPortLibrary->introspect_startup(privateOmrPortLibrary) #define omrintrospect_shutdown() privateOmrPortLibrary->introspect_shutdown(privateOmrPortLibrary) #define omrintrospect_set_suspend_signal_offset(param1) privateOmrPortLibrary->introspect_set_suspend_signal_offset(privateOmrPortLibrary, param1) diff --git a/nls/portnls.h b/nls/portnls.h index 428763a59df..8f1fc104959 100644 --- a/nls/portnls.h +++ b/nls/portnls.h @@ -176,5 +176,8 @@ #define J9NLS_PORT_RUNNING_IN_CONTAINER_FAILURE__MODULE 0x504f5254 #define J9NLS_PORT_RUNNING_IN_CONTAINER_FAILURE__ID 50 #define J9NLS_PORT_RUNNING_IN_CONTAINER_FAILURE J9NLS_PORT_RUNNING_IN_CONTAINER_FAILURE__MODULE, J9NLS_PORT_RUNNING_IN_CONTAINER_FAILURE__ID +#define J9NLS_PORT_SYSINFO_UNSUPPORTED_PLATFORM_ERROR__MODULE 0x504f5254 +#define J9NLS_PORT_SYSINFO_UNSUPPORTED_PLATFORM_ERROR__ID 51 +#define J9NLS_PORT_SYSINFO_UNSUPPORTED_PLATFORM_ERROR J9NLS_PORT_SYSINFO_UNSUPPORTED_PLATFORM_ERROR__MODULE, J9NLS_PORT_SYSINFO_UNSUPPORTED_PLATFORM_ERROR__ID #endif diff --git a/port/common/omrport.c b/port/common/omrport.c index c0ee28fbe2f..ab2319f0c1b 100644 --- a/port/common/omrport.c +++ b/port/common/omrport.c @@ -335,6 +335,7 @@ static OMRPortLibrary MainPortLibraryTable = { omrsysinfo_cgroup_subsystem_iterator_metricKey, /* sysinfo_cgroup_subsystem_iterator_metricKey */ omrsysinfo_cgroup_subsystem_iterator_next, /* sysinfo_cgroup_subsystem_iterator_next */ omrsysinfo_cgroup_subsystem_iterator_destroy, /* sysinfo_cgroup_subsystem_iterator_destroy */ + omrsysinfo_get_process_start_time, /* sysinfo_get_process_start_time */ omrport_init_library, /* port_init_library */ omrport_startup_library, /* port_startup_library */ omrport_create_library, /* port_create_library */ diff --git a/port/common/omrport.tdf b/port/common/omrport.tdf index c0d49788e0d..f9bc6f39a9f 100644 --- a/port/common/omrport.tdf +++ b/port/common/omrport.tdf @@ -1630,3 +1630,13 @@ TraceEvent=Trc_PRT_sl_open_shared_library_noload Group=sl Overhead=1 Level=3 NoE TraceException=Trc_PRT_retrieveLinuxMemoryStats_failedOpeningSwappinessFs Group=sysinfo Overhead=1 Level=1 NoEnv Template="retrieveLinuxMemoryStats: Failed to open /proc/sys/vm/swappiness. Error code = %d." TraceException=Trc_PRT_retrieveLinuxMemoryStats_failedReadingSwappiness Group=sysinfo Overhead=1 Level=1 NoEnv Template="retrieveLinuxMemoryStats: Failed to read /proc/sys/vm/swappiness. Error code = %d." TraceException=Trc_PRT_retrieveLinuxMemoryStats_unexpectedSwappinessFormat Group=sysinfo Overhead=1 Level=1 NoEnv Template="retrieveLinuxMemoryStats: Expected %d items to read, but read %d items." + +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_enter Group=sysinfo Overhead=1 Level=1 NoEnv Template="Enter omrsysinfo_get_process_start_time for pid %llu" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_stat_error Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time stat error for pid %llu" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_sysctl_error Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time sysctl error for pid %llu" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_pid_does_not_exist Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time pid %llu does not exist" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_getprocs_error Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time getprocs error for pid %llu" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_getthent_error Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time getthent error for pid %llu" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_OpenProcess_error Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time OpenProcess error for pid %llu" +TraceEntry=Trc_PRT_sysinfo_get_process_start_time_GetProcessTimes_error Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_process_start_time GetProcessTimes error for pid %llu" +TraceExit=Trc_PRT_sysinfo_get_process_start_time_exit Group=sysinfo Overhead=1 Level=1 NoEnv Template="Exit omrsysinfo_get_process_start_time for pid %llu" diff --git a/port/common/omrsysinfo.c b/port/common/omrsysinfo.c index 5f942713ed0..2f405ff8332 100644 --- a/port/common/omrsysinfo.c +++ b/port/common/omrsysinfo.c @@ -1178,3 +1178,15 @@ omrsysinfo_cgroup_subsystem_iterator_destroy(struct OMRPortLibrary *portLibrary, { return; } + +/** + * Get the process start time in ns precision epoch time. + * @param[in] portLibrary The port library + * @param[in] pid The process ID + * @return 0 if the process does not exist, process start time in ns precision epoch time if the process exists + */ +uint64_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid) +{ + return 0; +} diff --git a/port/omrportpriv.h b/port/omrportpriv.h index 4b702148f37..fe6f7bf6ee4 100644 --- a/port/omrportpriv.h +++ b/port/omrportpriv.h @@ -661,6 +661,8 @@ extern J9_CFUNC int32_t omrsysinfo_cgroup_subsystem_iterator_next(struct OMRPortLibrary *portLibrary, struct OMRCgroupMetricIteratorState *state, struct OMRCgroupMetricElement *metricElement); extern J9_CFUNC void omrsysinfo_cgroup_subsystem_iterator_destroy(struct OMRPortLibrary *portLibrary, struct OMRCgroupMetricIteratorState *state); +extern J9_CFUNC uint64_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid); /* J9SourceJ9Signal*/ extern J9_CFUNC int32_t diff --git a/port/unix/omrsysinfo.c b/port/unix/omrsysinfo.c index 5b0832320a4..e6895841a7b 100644 --- a/port/unix/omrsysinfo.c +++ b/port/unix/omrsysinfo.c @@ -80,6 +80,7 @@ #if defined(J9ZOS390) +#include "omrgetthent.h" #include "omrsimap.h" #endif /* defined(J9ZOS390) */ @@ -95,6 +96,7 @@ #if defined(AIXPPC) #include +#include #include #include #endif /* defined(AIXPPC) */ @@ -195,6 +197,19 @@ uintptr_t Get_Number_Of_CPUs(); #define JIFFIES 100 #define USECS_PER_SEC 1000000 #define TICKS_TO_USEC ((uint64_t)(USECS_PER_SEC/JIFFIES)) +#define OMRPORT_SYSINFO_PROC_DIR_BUFFER_SIZE 256 +#define OMRPORT_SYSINFO_STAT_ERROR -1 +#define OMRPORT_SYSINFO_NUM_SYSCTL_ARGS 4 +#define OMRPORT_SYSINFO_SYSCTL_ERROR -1 +#define OMRPORT_SYSINFO_NANOSECONDS_PER_MICROSECOND 1000ULL +#define OMRPORT_SYSINFO_GETPROCS_ERROR -1 +#define OMRPORT_SYSINFO_GETPROCS_NONEXISTING_PID_ERROR 0 +#define OMRPORT_SYSINFO_GETTHENT_ERROR -1 +#if defined(_LP64) +#define GETTHENT BPX4GTH +#else /* defined(_LP64) */ +#define GETTHENT BPX1GTH +#endif /* defined(_LP64) */ static uintptr_t copyEnvToBuffer(struct OMRPortLibrary *portLibrary, void *args); static uintptr_t copyEnvToBufferSignalHandler(struct OMRPortLibrary *portLib, uint32_t gpType, void *gpInfo, void *unUsed); @@ -598,6 +613,19 @@ static intptr_t searchSystemPath(struct OMRPortLibrary *portLibrary, char *filen #if defined(J9ZOS390) static void setOSFeature(struct OMROSDesc *desc, uint32_t feature); static intptr_t getZOSDescription(struct OMRPortLibrary *portLibrary, struct OMROSDesc *desc); +#if defined(_LP64) +#pragma linkage(BPX4GTH,OS) +#else /* defined(_LP64) */ +#pragma linkage(BPX1GTH,OS) +#endif /* defined(_LP64) */ +void GETTHENT( + unsigned int *inputSize, + unsigned char **input, + unsigned int *outputSize, + unsigned char **output, + unsigned int *ret, + unsigned int *retCode, + unsigned int *reasonCode); #endif /* defined(J9ZOS390) */ #if !defined(RS6000) && !defined(J9ZOS390) && !defined(OSX) && !defined(OMRZTPF) @@ -7354,3 +7382,84 @@ get_Dispatch_IstreamCount(void) { return (uintptr_t)numberOfIStreams; } #endif /* defined(OMRZTPF) */ + +uint64_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid) +{ + Trc_PRT_sysinfo_get_process_start_time_enter((unsigned long long)pid); + uint64_t processStartTimeInNanoseconds = 0; + if (0 != omrsysinfo_process_exists(portLibrary, pid)) { +#if defined(LINUX) + char procDir[OMRPORT_SYSINFO_PROC_DIR_BUFFER_SIZE] = {0}; + struct stat st; + snprintf(procDir, sizeof(procDir), "/proc/%" PRIuPTR, pid); + if (OMRPORT_SYSINFO_STAT_ERROR == stat(procDir, &st)) { + Trc_PRT_sysinfo_get_process_start_time_stat_error((unsigned long long)pid); + goto done; + } + processStartTimeInNanoseconds = (uint64_t)st.st_mtime * OMRPORT_TIME_DELTA_IN_NANOSECONDS + st.st_mtim.tv_nsec; +#elif defined(OSX) /* defined(LINUX) */ + int mib[OMRPORT_SYSINFO_NUM_SYSCTL_ARGS] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + size_t len = sizeof(struct kinfo_proc); + struct kinfo_proc procInfo; + if (OMRPORT_SYSINFO_SYSCTL_ERROR == sysctl(mib, OMRPORT_SYSINFO_NUM_SYSCTL_ARGS, &procInfo, &len, NULL, 0)) { + Trc_PRT_sysinfo_get_process_start_time_sysctl_error((unsigned long long)pid); + goto done; + } + if (0 == len) { + Trc_PRT_sysinfo_get_process_start_time_pid_does_not_exist((unsigned long long)pid); + goto done; + } + processStartTimeInNanoseconds = + ((uint64_t)procInfo.kp_proc.p_starttime.tv_sec * OMRPORT_TIME_DELTA_IN_NANOSECONDS) + + ((uint64_t)procInfo.kp_proc.p_starttime.tv_usec * OMRPORT_SYSINFO_NANOSECONDS_PER_MICROSECOND); +#elif defined(AIXPPC) /* defined(OSX) */ + pid_t convertedPid = (pid_t)pid; + struct procsinfo procInfos[] = {0}; + int ret = getprocs(procInfos, sizeof(procInfos[0]), NULL, 0, &convertedPid, sizeof(procInfos) / sizeof(procInfos[0])); + if (OMRPORT_SYSINFO_GETPROCS_ERROR == ret) { + Trc_PRT_sysinfo_get_process_start_time_getprocs_error((unsigned long long)pid); + goto done; + } else if (OMRPORT_SYSINFO_GETPROCS_NONEXISTING_PID_ERROR == ret) { + Trc_PRT_sysinfo_get_process_start_time_pid_does_not_exist((unsigned long long)pid); + goto done; + } + processStartTimeInNanoseconds = (uint64_t)(procInfos[0].pi_start) * OMRPORT_TIME_DELTA_IN_NANOSECONDS; +#elif defined(J9ZOS390) /* defined(AIXPPC) */ + pgtha pgtha; + ProcessData processData; + pgthc *currentProcessInfo = NULL; + uint32_t dataOffset = 0; + uint32_t inputSize = sizeof(pgtha); + unsigned char *input = (unsigned char *)&pgtha; + uint32_t outputSize = sizeof(ProcessData); + unsigned char *output = (unsigned char *)&processData; + uint32_t ret = 0; + uint32_t retCode = 0; + uint32_t reasonCode = 0; + memset(input, 0, sizeof(pgtha)); + memset(output, 0, sizeof(processData)); + pgtha.pid = pid; + pgtha.accesspid = PGTHA_ACCESS_CURRENT; + pgtha.flag1 = PGTHA_FLAG_PROCESS_DATA; + GETTHENT(&inputSize, &input, &outputSize, &output, &ret, &retCode, &reasonCode); + if (OMRPORT_SYSINFO_GETTHENT_ERROR == ret) { + Trc_PRT_sysinfo_get_process_start_time_getthent_error((unsigned long long)pid); + goto done; + } + dataOffset = *((unsigned int *)processData.pgthb.offc); + dataOffset = (dataOffset & I_32_MAX) >> 8; + currentProcessInfo = (pgthc *)(((char *)&processData) + dataOffset); + processStartTimeInNanoseconds = (uint64_t)currentProcessInfo->starttime * OMRPORT_TIME_DELTA_IN_NANOSECONDS; +#else /* defined(J9ZOS390) */ + portLibrary->nls_printf( + portLibrary, + J9NLS_WARNING, + J9NLS_PORT_SYSINFO_UNSUPPORTED_PLATFORM_ERROR, + "omrsysinfo_get_process_start_time is unsupported on this platform."); +#endif /* defined(LINUX) */ + } +done: + Trc_PRT_sysinfo_get_process_start_time_exit((unsigned long long)pid); + return processStartTimeInNanoseconds; +} diff --git a/port/win32/omrsysinfo.c b/port/win32/omrsysinfo.c index baf108f15ed..3fb61342b38 100644 --- a/port/win32/omrsysinfo.c +++ b/port/win32/omrsysinfo.c @@ -46,6 +46,10 @@ #include "ut_omrport.h" #include "omrsysinfo_helpers.h" +#define OMRPORT_SYSINFO_WINDOWS_TICK 10000000ULL +#define OMRPORT_SYSINFO_SEC_TO_UNIX_EPOCH 11644473600ULL +#define OMRPORT_SYSINFO_NS100_PER_SEC 10000000ULL + static int32_t copyEnvToBuffer(struct OMRPortLibrary *portLibrary, void *args); typedef struct CopyEnvToBufferArgs { @@ -1990,3 +1994,30 @@ omrsysinfo_cgroup_subsystem_iterator_destroy(struct OMRPortLibrary *portLibrary, return; } +uint64_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid) +{ + Trc_PRT_sysinfo_get_process_start_time_enter((unsigned long long)pid); + uint64_t processStartTimeInNanoseconds = 0; + if (0 != omrsysinfo_process_exists(portLibrary, pid)) { + double seconds = 0; + FILETIME createTime, exitTime, kernelTime, userTime; + HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)pid); + if (NULL == process) { + Trc_PRT_sysinfo_get_process_start_time_OpenProcess_error((unsigned long long)pid); + goto done; + } + if (!GetProcessTimes(process, &createTime, &exitTime, &kernelTime, &userTime)) { + Trc_PRT_sysinfo_get_process_start_time_GetProcessTimes_error((unsigned long long)pid); + goto cleanup; + } + seconds = (double)(*(LONGLONG*)&(createTime)) / OMRPORT_SYSINFO_WINDOWS_TICK; + processStartTimeInNanoseconds = (uint64_t)((seconds - OMRPORT_SYSINFO_SEC_TO_UNIX_EPOCH) * OMRPORT_SYSINFO_NS100_PER_SEC); + processStartTimeInNanoseconds *= 100; +cleanup: + CloseHandle(process); + } +done: + Trc_PRT_sysinfo_get_process_start_time_exit((unsigned long long)pid); + return processStartTimeInNanoseconds; +} diff --git a/port/win32/omrtime.c b/port/win32/omrtime.c index 217fcf53462..0f7f14c4918 100644 --- a/port/win32/omrtime.c +++ b/port/win32/omrtime.c @@ -181,7 +181,7 @@ omrtime_nano_time(struct OMRPortLibrary *portLibrary) if (PPG_time_hiresClockFrequency == OMRTIME_NANOSECONDS_PER_SECOND) { nanos = ticks; } else if (PPG_time_hiresClockFrequency < OMRTIME_NANOSECONDS_PER_SECOND) { - nanos = (int64_t)(ticks * (OMRTIME_NANOSECONDS_PER_SECOND / PPG_time_hiresClockFrequency)); + nanos = (int64_t)(ticks * (OMRPORT_TIME_DELTA_IN_NANOSECONDS / PPG_time_hiresClockFrequency)); } else { nanos = (int64_t)(ticks / (PPG_time_hiresClockFrequency / OMRTIME_NANOSECONDS_PER_SECOND)); } diff --git a/port/zos390/omrgetthent.h b/port/zos390/omrgetthent.h new file mode 100644 index 00000000000..f047f99a8bf --- /dev/null +++ b/port/zos390/omrgetthent.h @@ -0,0 +1,182 @@ +/******************************************************************************* + * Copyright IBM Corp. and others 2024 + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] https://openjdk.org/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0 + *******************************************************************************/ + +#if !defined(OMRGETTHENT_H_) +#define OMRGETTHENT_H_ + +#include "omrutil.h" + +#define PGTHA_ACCESS_CURRENT 1 +#define PGTHA_FLAG_PROCESS_DATA 0x80 + +#pragma pack(packed) + +typedef struct pgtha { + /* Start of PGTHACONTINUE group. */ + unsigned int pid; + unsigned char thid[8]; + /* FIRST, CURRENT or NEXT. */ + unsigned char accesspid; + /* FIRST, CURRENT, NEXT or LAST. */ + unsigned char accessthid; + /* End of PGTHACONTINUE group. */ + unsigned short asid; + unsigned char loginname[8]; + /* Only THREAD and PTAG checked if ACCESSPID==CURRENT & ACCESSTHID==NEXT. */ + unsigned char flag1; + char padding; +} pgtha; + +/* +PGTHB DSECT , O U T P U T - - - - - - - - - - +PGTHBID DS CL4 "gthb" +PGTHBCONTINUE DS 0CL14 NEXT VALUE FOR PGTHACONTINUE +PGTHBPID DS F PROCESS ID +PGTHBTHID DS CL8 THREAD ID +PGTHBACCESSPID DS FL1 CURRENT/FIRST/NEXT +PGTHBACCESSTHID DS FL1 CURRENT/FIRST/NEXT/LAST + DS FL2 +PGTHBLENUSED DS F LENGTH OF OUTPUT BUFFER USED +PGTHBLIMITC DS CL1 N, A +PGTHBOFFC DS FL3 OFFSET OF PROCESS AREA +PGTHBLIMITD DS CL1 N, A, X +PGTHBOFFD DS FL3 OFFSET OF CONTTY AREA +PGTHBLIMITE DS CL1 N, A, X +PGTHBOFFE DS FL3 OFFSET OF PATH AREA +PGTHBLIMITF DS CL1 N, A, X +PGTHBOFFF DS FL3 OFFSET OF COMMAND AREA +PGTHBLIMITG DS CL1 N, A, X +PGTHBOFFG DS FL3 OFFSET OF FILE DATA AREA +PGTHBLIMITJ DS CL1 N, A, V, X +PGTHBOFFJ DS FL3 OFFSET OF THREAD AREA +PGTHB#LEN EQU *-PGTHB +*/ +typedef struct pgthb { + /* "gthb" eyecatcher. */ + char id[4]; + /* Start of PGTHBCONTINUE. */ + int pid; + char thid[8]; + char accesspid; + char accessthid; + /* End of PGTHBCONTINUE. */ + char padding[2]; + int lenused; + char limitc; + char offc[3]; + char limitd; + char offd[3]; + char limite; + char offe[3]; + char limitf; + char offf[3]; + char limitg; + char offg[3]; + char limitj; + char offj[3]; +} pgthb; + +typedef struct pgthc { + /* "gthc" eyecatcher. */ + char id[4]; + char flag1; + char flag2; + char flag3; + char padding; + int pid; + int ppid; + int pgpid; + int sid; + int fgpid; + int euid; + int ruid; + int suid; + int egid; + int rgid; + int sgid; + int tsize; + int syscallcount; + int usertime; + int systime; + int starttime; + short cntoe; + short cntptcreated; + short cntthreads; + short asid; + char jobname[8]; + char loginname[8]; + union { + int value; + struct { + char value[3]; + char demonination; + } tuple; + } memlimit; + union { + int value; + struct { + char value[3]; + char demonination; + } tuple; + } memusage; +} pgthc; + +typedef struct pgthj { + /* "gthj" eyecatcher. */ + char id[4]; + char limitj; + char offj[3]; + char limitk; + char offk[3]; + char thid[8]; + char syscall[4]; + struct tcb *tcb; + int ttime; + int wtime; + int padding; + /* if status2==D. */ + short semnum; + /* if status2==D. */ + short semval; + int latchwaitpid; + char penmask[8]; + char loginname[8]; + /* Last 5 syscalls. */ + char prevsc[5][4]; + /* Start of PGTHJSTATUSCHARS group. */ + char status1; + char status2; + char status3; + char status4; + char status5; + /* End of PGTHJSTATUSCHARS group. */ +} pgthj; + +typedef struct ProcessData { + struct pgthb pgthb; + struct pgthj pgthj; + char padding[256]; +} ProcessData; + +#pragma pack(reset) + +#endif /* !defined(OMRGETTHENT_H_) */ diff --git a/port/zos390/omrintrospect.h b/port/zos390/omrintrospect.h index c46169a086a..6915cb916f7 100644 --- a/port/zos390/omrintrospect.h +++ b/port/zos390/omrintrospect.h @@ -30,6 +30,7 @@ #include #include "edcwccwi.h" +#import "omrgetthent.h" #include "omrintrospect_common.h" #include "omrutil.h" @@ -155,11 +156,9 @@ PGTHAPTAG EQU X'02' PGTHK, PTAG (NEEDS PGTHJ) PGTHA#LEN EQU *-PGTHA */ #define PGTHA_ACCESS_FIRST 0 -#define PGTHA_ACCESS_CURRENT 1 #define PGTHA_ACCESS_NEXT 2 #define PGTHA_ACCESS_LAST 3 -#define PGTHA_FLAG_PROCESS_DATA 0x80 #define PGTHA_FLAG_CONTTY 0x40 #define PGTHA_FLAG_PATH 0x20 #define PGTHA_FLAG_CMD_AND_ARGS 0x10 @@ -167,72 +166,6 @@ PGTHA#LEN EQU *-PGTHA #define PGTHA_FLAG_THREAD_DATA 0x4 #define PGTHA_FLAG_PTAG 0x2 /* needs thread data */ -struct pgtha { - /* start of PGTHACONTINUE group */ - unsigned int pid; - unsigned char thid[8]; - unsigned char accesspid; /* FIRST, CURRENT or NEXT */ - unsigned char accessthid; /* FIRST, CURRENT, NEXT or LAST */ - /* end of PGTHACONTINUE group */ - - unsigned short asid; - unsigned char loginname[8]; - unsigned char flag1; /* ONLY THREAD and PTAG checked if ACCESSPID==CURRENT & ACCESSTHID==NEXT */ - - char _padding; -}; - - -/* -PGTHB DSECT , O U T P U T - - - - - - - - - - -PGTHBID DS CL4 "gthb" -PGTHBCONTINUE DS 0CL14 NEXT VALUE FOR PGTHACONTINUE -PGTHBPID DS F PROCESS ID -PGTHBTHID DS CL8 THREAD ID -PGTHBACCESSPID DS FL1 CURRENT/FIRST/NEXT -PGTHBACCESSTHID DS FL1 CURRENT/FIRST/NEXT/LAST - DS FL2 -PGTHBLENUSED DS F LENGTH OF OUTPUT BUFFER USED -PGTHBLIMITC DS CL1 N, A -PGTHBOFFC DS FL3 OFFSET OF PROCESS AREA -PGTHBLIMITD DS CL1 N, A, X -PGTHBOFFD DS FL3 OFFSET OF CONTTY AREA -PGTHBLIMITE DS CL1 N, A, X -PGTHBOFFE DS FL3 OFFSET OF PATH AREA -PGTHBLIMITF DS CL1 N, A, X -PGTHBOFFF DS FL3 OFFSET OF COMMAND AREA -PGTHBLIMITG DS CL1 N, A, X -PGTHBOFFG DS FL3 OFFSET OF FILE DATA AREA -PGTHBLIMITJ DS CL1 N, A, V, X -PGTHBOFFJ DS FL3 OFFSET OF THREAD AREA -PGTHB#LEN EQU *-PGTHB -*/ -struct pgthb { - char id[4]; /* "gthb" eyecatcher */ - /* start of PGTHBCONTINUE */ - int pid; - char thid[8]; - char accesspid; - char accessthid; - /* end of PGTHBCONTINUE */ - - char _padding[2]; - - int lenused; - char limitc; - char offc[3]; - char limitd; - char offd[3]; - char limite; - char offe[3]; - char limitf; - char offf[3]; - char limitg; - char offg[3]; - char limitj; - char offj[3]; -}; - /* * VALUES FOR PGTH.LIMIT. FIELDS PGTH#NOTREQUESTED EQU C'N' Associated PghtA.. bit off @@ -343,56 +276,6 @@ PGTHC#LEN EQU *-PGTHC #define PGTHC_MEM_DENOMINATION_TERABYTE 0xE3 #define PGTHC_MEM_DENOMINATION_PETABYTE 0xD7 -struct pgthc { - char id[4]; /* "gthc" eyecatcher */ - char flag1; - char flag2; - char flag3; - - char _padding; - - int pid; - int ppid; - int pgpid; - int sid; - int fgpid; - int euid; - int ruid; - int suid; - int egid; - int rgid; - int sgid; - int tsize; - int syscallcount; - int usertime; - int systime; - int starttime; - - short cntoe; - short cntptcreated; - short cntthreads; - short asid; - - char jobname[8]; - char loginname[8]; - - union { - int value; - struct { - char value[3]; - char demonination; - } tuple; - } memlimit; - - union { - int value; - struct { - char value[3]; - char demonination; - } tuple; - } memusage; -}; - /* * USING PGTHD,Rx where Rx = ADDRESS of PGTHB + PGTHBOFFD PGTHD DSECT , C O N T T Y - - - - - - - - - - @@ -568,35 +451,6 @@ PGTHJ#LEN EQU *-PGTHJ #define PGTHJ_STATUS4_DETACHED 0xE5 #define PGTHJ_STATUS5_FREEZE 0xC5 -struct pgthj { - char id[4]; /* "gthj" eyecatcher */ - char limitj; - char offj[3]; - char limitk; - char offk[3]; - char thid[8]; - char syscall[4]; - struct tcb *tcb; - int ttime; - int wtime; - - int _padding; - - short semnum; /* if status2==D */ - short semval; /* if status2==D */ - int latchwaitpid; - char penmask[8]; - char loginname[8]; - char prevsc[5][4]; /* last 5 syscalls */ - - /* start of PGTHJSTATUSCHARS group */ - char status1; - char status2; - char status3; - char status4; - char status5; - /* end of PGTHJSTATUSCHARS group */ -}; /* * USING PGTHH,Rx where Rx = ADDRESS of PGTHB + PGTHJOFFK