Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an API for system processes #7681

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include_core/omrport.h
Original file line number Diff line number Diff line change
Expand Up @@ -1905,6 +1905,7 @@ typedef struct J9Heap J9Heap;

typedef uintptr_t (*omrsig_protected_fn)(struct OMRPortLibrary *portLib, void *handler_arg);
typedef uintptr_t (*omrsig_handler_fn)(struct OMRPortLibrary *portLib, uint32_t gpType, void *gpInfo, void *handler_arg);
typedef uintptr_t (*OMRProcessInfoCallback)(uintptr_t pid, const char *commandLine, void *userData);

typedef struct OMRPortLibrary {
/** portGlobals*/
Expand Down Expand Up @@ -2007,6 +2008,8 @@ typedef struct OMRPortLibrary {
intptr_t (*sysinfo_get_CPU_utilization)(struct OMRPortLibrary *portLibrary, struct J9SysinfoCPUTime *cpuTime) ;
/** see @ref omrsysinfo.c::omrsysinfo_get_CPU_load "omrsysinfo_get_CPU_utilization"*/
intptr_t (*sysinfo_get_CPU_load)(struct OMRPortLibrary *portLibrary, double *load) ;
/** see @ref omrsysinfo.c::omrsysinfo_get_processes "omrsysinfo_get_processes" */
uintptr_t (*sysinfo_get_processes)(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData);
/** see @ref omrsysinfo.c::omrsysinfo_limit_iterator_init "omrsysinfo_limit_iterator_init"*/
int32_t (*sysinfo_limit_iterator_init)(struct OMRPortLibrary *portLibrary, J9SysinfoLimitIteratorState *state) ;
/** see @ref omrsysinfo.c::omrsysinfo_limit_iterator_hasNext "omrsysinfo_limit_iterator_hasNext"*/
Expand Down Expand Up @@ -2907,6 +2910,7 @@ extern J9_CFUNC int32_t omrport_getVersion(struct OMRPortLibrary *portLibrary);
#define omrsysinfo_env_iterator_hasNext(param1) privateOmrPortLibrary->sysinfo_env_iterator_hasNext(privateOmrPortLibrary, (param1))
#define omrsysinfo_env_iterator_next(param1,param2) privateOmrPortLibrary->sysinfo_env_iterator_next(privateOmrPortLibrary, (param1), (param2))
#define omrsysinfo_set_number_user_specified_CPUs(param1) privateOmrPortLibrary->sysinfo_set_number_user_specified_CPUs(privateOmrPortLibrary,(param1))
#define omrsysinfo_get_processes(callback, userData) privateOmrPortLibrary->sysinfo_get_processes(privateOmrPortLibrary, callback, userData)
#define omrfile_startup() privateOmrPortLibrary->file_startup(privateOmrPortLibrary)
#define omrfile_shutdown() privateOmrPortLibrary->file_shutdown(privateOmrPortLibrary)
#define omrfile_write(param1,param2,param3) privateOmrPortLibrary->file_write(privateOmrPortLibrary, (param1), (param2), (param3))
Expand Down
1 change: 1 addition & 0 deletions port/common/omrport.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ static OMRPortLibrary MainPortLibraryTable = {
omrsysinfo_get_load_average, /* sysinfo_get_load_average */
omrsysinfo_get_CPU_utilization, /* sysinfo_get_CPU_utilization */
omrsysinfo_get_CPU_load, /* sysinfo_get_CPU_load */
omrsysinfo_get_processes, /* sysinfo_get_processes */
omrsysinfo_limit_iterator_init, /* sysinfo_limit_iterator_next */
omrsysinfo_limit_iterator_hasNext, /* sysinfo_limit_iterator_hasNext */
omrsysinfo_limit_iterator_next, /* sysinfo_limit_iterator_next */
Expand Down
2 changes: 2 additions & 0 deletions port/common/omrport.tdf
Original file line number Diff line number Diff line change
Expand Up @@ -1635,3 +1635,5 @@ TraceEntry=Trc_PRT_sysinfo_get_process_start_time_enter Group=sysinfo Overhead=1
TraceExit=Trc_PRT_sysinfo_get_process_start_time_exit Group=sysinfo Overhead=1 Level=1 NoEnv Template="Exit omrsysinfo_get_process_start_time, pid=%zu, processStartTimeInNanoseconds=%llu, rc=%d."

TraceEvent=Trc_PRT_vmem_reserve_tempfile_not_created Group=mem Overhead=1 Level=5 NoEnv Template="reserve_memory cannot create temporary file %s of size %zu"

TraceException=Trc_PRT_sysinfo_get_processes_failedOpeningProcFS Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_processes failed opening /proc = %d."
13 changes: 13 additions & 0 deletions port/common/omrsysinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -1203,3 +1203,16 @@ omrsysinfo_get_number_context_switches(struct OMRPortLibrary *portLibrary, uint6
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
}

/**
* Get the process ID and commandline for each process.
* @param[in] portLibrary The port library.
* @param[in] callback The function to be invoked for each process with the process ID and command info.
* @param[in] userData Data passed to the callback.
* @return 0 on success, or the first non-zero value returned by the callback.
*/
uintptr_t
omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData)
{
return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
}
2 changes: 2 additions & 0 deletions port/omrportpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,8 @@ extern J9_CFUNC intptr_t
omrsysinfo_get_CPU_utilization(struct OMRPortLibrary *portLibrary, struct J9SysinfoCPUTime *cpuTime);
extern J9_CFUNC intptr_t
omrsysinfo_get_CPU_load(struct OMRPortLibrary *portLibrary, double *cpuLoad);
extern J9_CFUNC uintptr_t
omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData);
extern J9_CFUNC void
omrsysinfo_set_number_user_specified_CPUs(struct OMRPortLibrary *portLibrary, uintptr_t number);
extern J9_CFUNC intptr_t
Expand Down
115 changes: 115 additions & 0 deletions port/unix/omrsysinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -7557,3 +7557,118 @@ omrsysinfo_get_number_context_switches(struct OMRPortLibrary *portLibrary, uint6
return OMRPORT_ERROR_SYSINFO_NOT_SUPPORTED;
#endif /* defined(LINUX) */
}

/*
* Get the process ID and commandline for each process.
* @param[in] portLibrary The port library.
* @param[in] callback The function to be invoked for each process with the process ID and command info.
* @param[in] userData Data passed to the callback.
* @return 0 on success, or the first non-zero value returned by the callback.
*/
uintptr_t
omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData)
{
#if defined(LINUX)
#define INITIAL_BUFFER_SIZE 4096
char path[PATH_MAX];
uintptr_t callback_result = 0;
uintptr_t pid;
intptr_t file = 0;
uintptr_t buffer_size = INITIAL_BUFFER_SIZE;
intptr_t bytes_read = 0;
intptr_t total_bytes_read = 0;
uintptr_t new_size = 0;
intptr_t i = 0;
char *command = NULL;
char *end = NULL;
char *new_command = NULL;
DIR *dir = opendir("/proc");
if (NULL == dir) {
int32_t rc = findError(errno);
portLibrary->error_set_last_error(portLibrary, errno, rc);
Trc_PRT_sysinfo_get_processes_failedOpeningProcFS(rc);
return (uintptr_t)(intptr_t)rc;
}
/* Allocate initial buffer. */
command = (char *)portLibrary->mem_allocate_memory(portLibrary, buffer_size, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY);
if (NULL == command) {
closedir(dir);
return OMRPORT_ERROR_SYSINFO_MEMORY_ALLOC_FAILED;
}
for (;;) {
struct dirent *entry = readdir(dir);
if (NULL == entry) {
break;
}
if ('\0' == entry->d_name[0]) {
continue;
}
/* Convert name to pid, skipping non-numeric entries. */
pid = (uintptr_t)strtoull(entry->d_name, &end, 10);
if ('\0' != *end) {
continue;
}
/* Try reading /proc/[pid]/cmdline. */
portLibrary->str_printf(portLibrary, path, sizeof(path), "/proc/%s/cmdline", entry->d_name);
file = portLibrary->file_open(portLibrary, path, EsOpenRead, 0);
total_bytes_read = 0;
if (file >= 0) {
for (;;) {
bytes_read = portLibrary->file_read(portLibrary, file, command + total_bytes_read, buffer_size - 1 - total_bytes_read);
if (bytes_read < 0) {
break;
}
total_bytes_read += bytes_read;
if (total_bytes_read == buffer_size - 1) {
/* Buffer may be too small, increase and retry. */
new_size = buffer_size * 2;
new_command = (char *)portLibrary->mem_reallocate_memory(
portLibrary,
command,
new_size, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY);
if (NULL == new_command) {
break;
}
command = new_command;
buffer_size = new_size;
continue;
}
break;
}
bytes_read = total_bytes_read;
portLibrary->file_close(portLibrary, file);
}
/* If cmdline is empty, try reading from comm. */
if (bytes_read <= 0) {
portLibrary->str_printf(portLibrary, path, sizeof(path), "/proc/%s/comm", entry->d_name);
file = portLibrary->file_open(portLibrary, path, EsOpenRead, 0);
if (file >= 0) {
bytes_read = portLibrary->file_read(portLibrary, file, command, buffer_size - 1);
portLibrary->file_close(portLibrary, file);
}
}
/* Skip process if no data. */
if (bytes_read <= 0) {
continue;
}
/* Replace null terminators with spaces. */
for (i = 0; i < bytes_read; i++) {
if ('\0' == command[i]) {
command[i] = ' ';
}
}
command[bytes_read] = '\0';
/* Call the callback function with PID and command. */
callback_result = callback(pid, command, userData);
if (0 != callback_result) {
break;
}
}
portLibrary->mem_free_memory(portLibrary, command);
closedir(dir);
return callback_result;
#else /* defined(LINUX) */
/* sysinfo_get_processes is not supported on this platform. */
return OMRPORT_ERROR_SYSINFO_NOT_SUPPORTED;
#endif /* defined(LINUX) */
}