From 4cf8368eefb733308dca1630054cbbdd4cf020f5 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 | 78 ++++++++++++++++ include_core/omrport.h | 3 + include_core/omrporterror.h | 2 + port/common/omrport.c | 1 + port/common/omrport.tdf | 3 + port/common/omrsysinfo.c | 13 +++ port/omrportpriv.h | 2 + port/unix/omrsysinfo.c | 104 +++++++++++++++++++++ port/win32/omrsysinfo.c | 35 +++++++ port/zos390/omrgetthent.h | 182 ++++++++++++++++++++++++++++++++++++ port/zos390/omrintrospect.h | 148 +---------------------------- 11 files changed, 424 insertions(+), 147 deletions(-) create mode 100644 port/zos390/omrgetthent.h diff --git a/fvtest/porttest/si.cpp b/fvtest/porttest/si.cpp index b8eafbcfd10..f7ccfe83c99 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,75 @@ 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 = 0; + int32_t rc = omrsysinfo_get_process_start_time(pid, &actualProcessStartTimeInNanoseconds); + ASSERT_LT(rc, 0); + 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; + int32_t rc = 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); + } + rc = omrsysinfo_get_process_start_time(pid, &processStartTimeInNanoseconds); + 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); + rc = omrsysinfo_get_process_start_time(pid, &processStartTimeInNanoseconds); + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); +#endif /* defined(LINUX) || defined(OSX) || defined(AIXPPC) || defined(J9ZOS390) */ + ASSERT_EQ(rc, 0); + 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..55a32be370d 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"*/ + int32_t (*sysinfo_get_process_start_time)(struct OMRPortLibrary *portLibrary, uintptr_t pid, uint64_t *processStartTimeInNanoseconds); /** 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, param2) privateOmrPortLibrary->sysinfo_get_process_start_time(privateOmrPortLibrary, param1, param2) #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/include_core/omrporterror.h b/include_core/omrporterror.h index c5e8fb0ad34..a9d020315aa 100644 --- a/include_core/omrporterror.h +++ b/include_core/omrporterror.h @@ -421,6 +421,8 @@ #define OMRPORT_ERROR_SYSINFO_CGROUP_NULL_PARAM (OMRPORT_ERROR_SYSINFO_BASE-30) #define OMRPORT_ERROR_SYSINFO_ERROR_SWAPPINESS_OPEN_FAILED (OMRPORT_ERROR_SYSINFO_BASE-31) #define OMRPORT_ERROR_SYSINFO_ERROR_READING_SWAPPINESS (OMRPORT_ERROR_SYSINFO_BASE-32) +#define OMRPORT_ERROR_SYSINFO_NONEXISTING_PROCESS (OMRPORT_ERROR_SYSINFO_BASE-33) +#define OMRPORT_ERROR_SYSINFO_ERROR_GETTING_PROCESS_START_TIME (OMRPORT_ERROR_SYSINFO_BASE-34) /** * @name Port library initialization return codes 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..e9abe1ce141 100644 --- a/port/common/omrport.tdf +++ b/port/common/omrport.tdf @@ -1630,3 +1630,6 @@ 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, 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, pid=%llu, processStartTimeInNanoseconds=%llu, rc=%d." diff --git a/port/common/omrsysinfo.c b/port/common/omrsysinfo.c index 5f942713ed0..85f372c260d 100644 --- a/port/common/omrsysinfo.c +++ b/port/common/omrsysinfo.c @@ -1178,3 +1178,16 @@ 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 + * @param[in/out] processStartTimeInNanoseconds The pointer to uint64_t that stores the process start time in ns precision epoch time + * @return 0 on success, error code on failure + */ +int32_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid, uint64_t *processStartTimeInNanoseconds) +{ + return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM; +} diff --git a/port/omrportpriv.h b/port/omrportpriv.h index 4b702148f37..506e61572d3 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 int32_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid, uint64_t *processStartTimeInNanoseconds); /* J9SourceJ9Signal*/ extern J9_CFUNC int32_t diff --git a/port/unix/omrsysinfo.c b/port/unix/omrsysinfo.c index 61a0d633780..ad660fa4180 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,14 @@ 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_NUM_SYSCTL_ARGS 4 +#define OMRPORT_SYSINFO_NANOSECONDS_PER_MICROSECOND 1000ULL +#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 +608,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 +7377,84 @@ get_Dispatch_IstreamCount(void) { return (uintptr_t)numberOfIStreams; } #endif /* defined(OMRZTPF) */ + +int32_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid, uint64_t *processStartTimeInNanoseconds) +{ + int32_t rc = 0; + uint64_t computedProcessStartTimeInNanoseconds = 0; + Trc_PRT_sysinfo_get_process_start_time_enter((unsigned long long)pid); + 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 (-1 == stat(procDir, &st)) { + rc = OMRPORT_ERROR_SYSINFO_ERROR_GETTING_PROCESS_START_TIME; + goto done; + } + computedProcessStartTimeInNanoseconds = (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 (-1 == sysctl(mib, OMRPORT_SYSINFO_NUM_SYSCTL_ARGS, &procInfo, &len, NULL, 0)) { + rc = OMRPORT_ERROR_SYSINFO_ERROR_GETTING_PROCESS_START_TIME; + goto done; + } + if (0 == len) { + rc = OMRPORT_ERROR_SYSINFO_NONEXISTING_PROCESS; + goto done; + } + computedProcessStartTimeInNanoseconds = + ((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 (-1 == ret) { + rc = OMRPORT_ERROR_SYSINFO_ERROR_GETTING_PROCESS_START_TIME; + goto done; + } else if (0 == ret) { + rc = OMRPORT_ERROR_SYSINFO_NONEXISTING_PROCESS; + goto done; + } + computedProcessStartTimeInNanoseconds = (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 (-1 == ret) { + rc = OMRPORT_ERROR_SYSINFO_ERROR_GETTING_PROCESS_START_TIME; + goto done; + } + dataOffset = *((unsigned int *)processData.pgthb.offc); + dataOffset = (dataOffset & I_32_MAX) >> 8; + currentProcessInfo = (pgthc *)(((char *)&processData) + dataOffset); + computedProcessStartTimeInNanoseconds = (uint64_t)currentProcessInfo->starttime * OMRPORT_TIME_DELTA_IN_NANOSECONDS; +#else /* defined(J9ZOS390) */ + rc = OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM; +#endif /* defined(LINUX) */ + } else { + rc = OMRPORT_ERROR_SYSINFO_NONEXISTING_PROCESS; + } +done: + *processStartTimeInNanoseconds = computedProcessStartTimeInNanoseconds; + Trc_PRT_sysinfo_get_process_start_time_exit((unsigned long long)pid, (unsigned long long)computedProcessStartTimeInNanoseconds, rc); + return rc; +} diff --git a/port/win32/omrsysinfo.c b/port/win32/omrsysinfo.c index baf108f15ed..0212cdb4d70 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,34 @@ omrsysinfo_cgroup_subsystem_iterator_destroy(struct OMRPortLibrary *portLibrary, return; } +int32_t +omrsysinfo_get_process_start_time(struct OMRPortLibrary *portLibrary, uintptr_t pid, uint64_t *processStartTimeInNanoseconds) +{ + int32_t rc = 0; + uint64_t computedProcessStartTimeInNanoseconds = 0; + Trc_PRT_sysinfo_get_process_start_time_enter((unsigned long long)pid); + 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) { + rc = OMRPORT_ERROR_SYSINFO_NONEXISTING_PROCESS; + goto done; + } + if (!GetProcessTimes(process, &createTime, &exitTime, &kernelTime, &userTime)) { + rc = OMRPORT_ERROR_SYSINFO_ERROR_GETTING_PROCESS_START_TIME; + goto cleanup; + } + seconds = (double)(*(LONGLONG *)&(createTime)) / OMRPORT_SYSINFO_WINDOWS_TICK; + computedProcessStartTimeInNanoseconds = (uint64_t)((seconds - OMRPORT_SYSINFO_SEC_TO_UNIX_EPOCH) * OMRPORT_SYSINFO_NS100_PER_SEC); + computedProcessStartTimeInNanoseconds *= 100; +cleanup: + CloseHandle(process); + } else { + rc = OMRPORT_ERROR_SYSINFO_NONEXISTING_PROCESS; + } +done: + *processStartTimeInNanoseconds = computedProcessStartTimeInNanoseconds; + Trc_PRT_sysinfo_get_process_start_time_exit((unsigned long long)pid, (unsigned long long)computedProcessStartTimeInNanoseconds, rc); + return rc; +} 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