8203290: [AIX] Check functionality of JDK-8199712 (Flight Recorder)

Implements JFR for AIX

Reviewed-by: erikj, mdoerr, mgronlun, stuefe, ihse
This commit is contained in:
Tyler Steele 2022-02-17 08:49:22 +00:00 committed by Thomas Stuefe
parent 1864481df1
commit c0275e18b7
10 changed files with 746 additions and 787 deletions

View File

@ -264,22 +264,6 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_DTRACE],
])
])
###############################################################################
# Check if the feature 'jfr' is available on this platform.
#
AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JFR],
[
JVM_FEATURES_CHECK_AVAILABILITY(jfr, [
AC_MSG_CHECKING([if platform is supported by JFR])
if test "x$OPENJDK_TARGET_OS" = xaix; then
AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU])
AVAILABLE=false
else
AC_MSG_RESULT([yes])
fi
])
])
###############################################################################
# Check if the feature 'jvmci' is available on this platform.
#
@ -399,18 +383,11 @@ AC_DEFUN_ONCE([JVM_FEATURES_PREPARE_PLATFORM],
JVM_FEATURES_CHECK_CDS
JVM_FEATURES_CHECK_DTRACE
JVM_FEATURES_CHECK_JFR
JVM_FEATURES_CHECK_JVMCI
JVM_FEATURES_CHECK_SHENANDOAHGC
JVM_FEATURES_CHECK_STATIC_BUILD
JVM_FEATURES_CHECK_ZGC
# Filter out features by default for all variants on certain platforms.
# Make sure to just add to JVM_FEATURES_PLATFORM_FILTER, since it could
# have a value already from custom extensions.
if test "x$OPENJDK_TARGET_OS" = xaix; then
JVM_FEATURES_PLATFORM_FILTER="$JVM_FEATURES_PLATFORM_FILTER jfr"
fi
])
###############################################################################

View File

@ -1,5 +1,7 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* Copyright (c) 2022, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,12 +32,22 @@
// Handle to the libperfstat.
static void* g_libhandle = NULL;
typedef int (*fun_perfstat_cpu_t) (perfstat_id_t *name, PERFSTAT_CPU_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number);
typedef int (*fun_perfstat_cpu_total_t) (perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number);
typedef int (*fun_perfstat_memory_total_t) (perfstat_id_t *name, perfstat_memory_total_t* userbuff,
int sizeof_userbuff, int desired_number);
typedef int (*fun_perfstat_netinterface_t) (perfstat_id_t *name, perfstat_netinterface_t* userbuff,
int sizeof_userbuff, int desired_number);
typedef int (*fun_perfstat_process_t) (perfstat_id_t *name,
PERFSTAT_PROCESS_T_LATEST* userbuff, int sizeof_userbuff,
int desired_number);
typedef int (*fun_perfstat_partition_total_t) (perfstat_id_t *name,
PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff, int sizeof_userbuff,
int desired_number);
@ -48,12 +60,15 @@ typedef void (*fun_perfstat_reset_t) ();
typedef cid_t (*fun_wpar_getcid_t) ();
static fun_perfstat_cpu_total_t g_fun_perfstat_cpu_total = NULL;
static fun_perfstat_memory_total_t g_fun_perfstat_memory_total = NULL;
static fun_perfstat_cpu_total_t g_fun_perfstat_cpu_total = NULL;
static fun_perfstat_cpu_t g_fun_perfstat_cpu = NULL;
static fun_perfstat_memory_total_t g_fun_perfstat_memory_total = NULL;
static fun_perfstat_netinterface_t g_fun_perfstat_netinterface = NULL;
static fun_perfstat_partition_total_t g_fun_perfstat_partition_total = NULL;
static fun_perfstat_wpar_total_t g_fun_perfstat_wpar_total = NULL;
static fun_perfstat_reset_t g_fun_perfstat_reset = NULL;
static fun_wpar_getcid_t g_fun_wpar_getcid = NULL;
static fun_perfstat_process_t g_fun_perfstat_process = NULL;
static fun_perfstat_wpar_total_t g_fun_perfstat_wpar_total = NULL;
static fun_perfstat_reset_t g_fun_perfstat_reset = NULL;
static fun_wpar_getcid_t g_fun_wpar_getcid = NULL;
bool libperfstat::init() {
@ -84,7 +99,10 @@ bool libperfstat::init() {
// These functions are required for every release.
RESOLVE_FUN(perfstat_cpu_total);
RESOLVE_FUN(perfstat_cpu);
RESOLVE_FUN(perfstat_memory_total);
RESOLVE_FUN(perfstat_netinterface);
RESOLVE_FUN(perfstat_process);
RESOLVE_FUN(perfstat_reset);
trcVerbose("libperfstat loaded.");
@ -108,6 +126,22 @@ void libperfstat::cleanup() {
}
int libperfstat::perfstat_cpu_total(perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number) {
if (g_fun_perfstat_cpu_total == NULL) {
return -1;
}
return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_cpu(perfstat_id_t *name, PERFSTAT_CPU_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number) {
if (g_fun_perfstat_cpu == NULL) {
return -1;
}
return g_fun_perfstat_cpu(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_memory_total(perfstat_id_t *name,
perfstat_memory_total_t* userbuff,
int sizeof_userbuff, int desired_number) {
@ -117,12 +151,13 @@ int libperfstat::perfstat_memory_total(perfstat_id_t *name,
return g_fun_perfstat_memory_total(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_cpu_total(perfstat_id_t *name, PERFSTAT_CPU_TOTAL_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number) {
if (g_fun_perfstat_cpu_total == NULL) {
int libperfstat::perfstat_netinterface(perfstat_id_t *name,
perfstat_netinterface_t* userbuff,
int sizeof_userbuff, int desired_number) {
if (g_fun_perfstat_netinterface == NULL) {
return -1;
}
return g_fun_perfstat_cpu_total(name, userbuff, sizeof_userbuff, desired_number);
return g_fun_perfstat_netinterface(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_partition_total(perfstat_id_t *name, PERFSTAT_PARTITON_TOTAL_T_LATEST* userbuff,
@ -133,6 +168,14 @@ int libperfstat::perfstat_partition_total(perfstat_id_t *name, PERFSTAT_PARTITON
return g_fun_perfstat_partition_total(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_process(perfstat_id_t *name, perfstat_process_t* userbuff,
int sizeof_userbuff, int desired_number) {
if (g_fun_perfstat_process == NULL) {
return -1;
}
return g_fun_perfstat_process(name, userbuff, sizeof_userbuff, desired_number);
}
int libperfstat::perfstat_wpar_total(perfstat_id_wpar_t *name, PERFSTAT_WPAR_TOTAL_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number) {
if (g_fun_perfstat_wpar_total == NULL) {

View File

@ -1,5 +1,7 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* Copyright (c) 2022, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,7 +49,9 @@
// work without recompilation on all newer AIX versions.
//
#define IDENTIFIER_LENGTH 64 /* length of strings included in the structures */
#define IDENTIFIER_LENGTH 64 /* length of strings included in the structures */
#define FIRST_CPU "" /* pseudo-name for fist CPU */
#define FIRST_NETINTERFACE "" /* pseudo-name for first NETINTERFACE */
typedef struct { /* structure element identifier */
@ -439,6 +443,102 @@ typedef struct { /* global cpu information AIX 7.2 / 6.1 TL6 (see oslevel -r) *
* of perfstat_cpu_total_t data structure */
} perfstat_cpu_total_t_72;
typedef struct { /* component perfstat_cpu_t from AIX 7.2 documentation */
char name [IDENTIFIER_LENGTH]; /* Logical processor name (processor0, processor1,.). */
ulong_t state; /* Specifies whether the CPU is offline or online.
* (NOTE: The type of 'state' is not specified in the documentation, but
* ulong_t is the correct length) */
u_longlong_t user; /* Raw number of clock ticks spent in user mode. */
u_longlong_t sys; /* Raw number of clock ticks spent in system mode. */
u_longlong_t idle; /* Raw number of clock ticks spent idle. */
u_longlong_t wait; /* Raw number of clock ticks spent waiting for I/O. */
u_longlong_t pswitch; /* Number of context switches (changes of currently running process). */
u_longlong_t syscall; /* Number of system calls executed. */
u_longlong_t sysread; /* Number of read system calls executed. */
u_longlong_t syswrite; /* Number of write system calls executed. */
u_longlong_t sysfork; /* Number of fork system call executed. */
u_longlong_t sysexec; /* Number of exec system call executed. */
u_longlong_t readch; /* Number of characters transferred with read system call. */
u_longlong_t writech; /* Number of characters transferred with write system call. */
u_longlong_t bread; /* Number of block reads. */
u_longlong_t bwrite; /* Number of block writes. */
u_longlong_t lread; /* Number of logical read requests. */
u_longlong_t lwrite; /* Number of logical write requests. */
u_longlong_t phread; /* Number of physical reads (reads on raw device). */
u_longlong_t phwrite; /* Number of physical writes (writes on raw device). */
u_longlong_t iget; /* Number of inode lookups. */
u_longlong_t namei; /* Number of vnode lookup from a path name. */
u_longlong_t dirblk; /* Number of 512-byte blocks reads by the directory search routine to locate an entry for a file. */
u_longlong_t msg; /* Number of interprocess communication (IPC) message operations. */
u_longlong_t sema; /* Number of IPC semaphore operations. */
u_longlong_t minfaults; /* Number of page faults with no I/O. */
u_longlong_t majfaults; /* Number of page faults with disk I/O. */
u_longlong_t puser; /* Raw number of physical processor ticks in user mode. */
u_longlong_t psys; /* Raw number of physical processor ticks in system mode. */
u_longlong_t pidle; /* Raw number of physical processor ticks idle. */
u_longlong_t pwait; /* Raw number of physical processor ticks waiting for I/O. */
u_longlong_t redisp_sd0; /* Number of thread redispatches within the scheduler affinity domain 0. */
u_longlong_t redisp_sd1; /* Number of thread redispatches within the scheduler affinity domain 1. */
u_longlong_t redisp_sd2; /* Number of thread redispatches within the scheduler affinity domain 2. */
u_longlong_t redisp_sd3; /* Number of thread redispatches within the scheduler affinity domain 3. */
u_longlong_t redisp_sd4; /* Number of thread redispatches within the scheduler affinity domain 4. */
u_longlong_t redisp_sd5; /* Number of thread redispatches within the scheduler affinity domain 5. */
u_longlong_t migration_push; /* Number of thread migrations from the local runque to another queue due to starvation load balancing. */
u_longlong_t migration_S3grq; /* Number of thread migrations from the global runque to the local runque resulting in a move across scheduling domain 3. */
u_longlong_t migration_S3pull; /* Number of thread migrations from another processor's runque resulting in a move across scheduling domain 3. */
u_longlong_t invol_cswitch; /* Number of involuntary thread context switches. */
u_longlong_t vol_cswitch; /* Number of voluntary thread context switches. */
u_longlong_t runque; /* Number of threads on the runque. */
u_longlong_t bound; /* Number of bound threads. */
u_longlong_t decrintrs; /* Number of decrementer interrupts. */
u_longlong_t mpcrintrs; /* Number of received interrupts for MPC. */
u_longlong_t mpcsintrs; /* Number of sent interrupts for MPC. */
u_longlong_t devintrs; /* Number of device interrupts. */
u_longlong_t softintrs; /* Number of offlevel handlers called. */
u_longlong_t phantintrs; /* Number of phantom interrupts. */
u_longlong_t idle_donated_purr; /* Number of idle cycles donated by a dedicated partition enabled for donation. */
u_longlong_t idle_donated_spurr; /* Number of idle spurr cycles donated by a dedicated partition enabled for donation. */
u_longlong_t busy_donated_purr; /* Number of busy cycles donated by a dedicated partition enabled for donation. */
u_longlong_t busy_donated_spurr; /* Number of busy spurr cycles donated by a dedicated partition enabled for donation. */
u_longlong_t idle_stolen_purr; /* Number of idle cycles stolen by the hypervisor from a dedicated partition. */
u_longlong_t idle_stolen_spurr; /* Number of idle spurr cycles stolen by the hypervisor from a dedicated partition. */
u_longlong_t busy_stolen_purr; /* Number of busy cycles stolen by the hypervisor from a dedicated partition. */
u_longlong_t busy_stolen_spurr; /* Number of busy spurr cycles stolen by the hypervisor from a dedicated partition.*/
u_longlong_t shcpus_in_sys; /* Number of physical processors allocated for shared processor use, across all shared processors pools. */
u_longlong_t entitled_pool_capacity; /* Entitled processor capacity of partitions pool. */
u_longlong_t pool_max_time; /* Summation of maximum time that can be consumed by the pool (nanoseconds). */
u_longlong_t pool_busy_time; /* Summation of busy (nonidle) time accumulated across all partitions in the pool (nanoseconds). */
u_longlong_t pool_scaled_busy_time; /* Scaled summation of busy (nonidle) time accumulated across all partitions in the pool (nanoseconds). */
u_longlong_t shcpu_tot_time; /* Summation of total time across all physical processors allocated for shared processor use (nanoseconds). */
u_longlong_t shcpu_busy_time; /* Summation of busy (nonidle) time accumulated across all shared processor partitions (nanoseconds). */
u_longlong_t shcpu_scaled_busy_time; /* Scaled summation of busy time accumulated across all shared processor partitions (nanoseconds). */
int ams_pool_id; /* AMS pool ID of the pool the LPAR belongs to. */
int var_mem_weight; /* Variable memory capacity weight. */
u_longlong_t iome; /* I/O memory entitlement of the partition in bytes. */
u_longlong_t pmem; /* Physical memory currently backing the partition's logical memory in bytes. */
u_longlong_t hpi; /* Number of hypervisor page-ins. */
u_longlong_t hpit; /* Time spent in hypervisor page-ins (in nanoseconds). */
u_longlong_t hypv_pagesize; /* Hypervisor page size in KB. */
uint online_lcpus; /* Number of online logical processors. */
uint smt_thrds; /* Number of SMT threads. */
} perfstat_cpu_t;
typedef struct {
char name[IDENTIFIER_LENGTH]; /* Name of the interface. */
char description[IDENTIFIER_LENGTH]; /* Interface description (from ODM, similar to lscfg output). */
uchar type; /* Ethernet, token ring, and so on. Interpretation can be done using the /usr/include/net/if_types.h file. */
u_longlong_t mtu; /* Network frame size. */
u_longlong_t ipacets; /* Number of packets received on interface. */
u_longlong_t ibytes; /* Number of bytes received on interface. */
u_longlong_t ierrors; /* Number of input errors on interface. */
u_longlong_t opackets; /* Number of packets sent on interface. */
u_longlong_t obytes; /* Number of bytes sent on interface. */
u_longlong_t oerrors; /* Number of output errors on interface. */
u_longlong_t collisions; /* Number of collisions on csma interface. */
u_longlong_t bitrate; /* Adapter rating in bit per second. */
u_longlong_t if_iqdrops; /* Dropped on input, this interface. */
u_longlong_t if_arpdrops; /* Dropped because no arp response. */
} perfstat_netinterface_t;
typedef union {
uint w;
@ -797,6 +897,38 @@ typedef struct { /* partition total information AIX 7.1 >= TL1*/
* of perfstat_partition_total_t data structure */
} perfstat_partition_total_t_71_1;
typedef struct {
u_longlong_t version; /* Version number of the data structure. */
u_longlong_t pid; /* Process ID. */
char proc_name[64]; /* Name of the process. */
int proc_priority; /* Process priority. */
u_longlong_t num_threads; /* Thread count. */
u_longlong_t proc_uid; /* Owner information. */
u_longlong_t proc_classid; /* WLM class name. */
u_longlong_t proc_size; /* Virtual size of the process (exclusive usage, leaving all shared library text & shared file pages, shared memory, and memory mapped). */
u_longlong_t proc_real_mem_data; /* Real memory used for data in KB. */
u_longlong_t proc_real_mem_text; /* Real memory used for text in KB. */
u_longlong_t proc_virt_mem_data; /* Virtual memory used for data in KB. */
u_longlong_t proc_virt_mem_text; /* Virtual memory used for text in KB. */
u_longlong_t shared_lib_data_size; /* Data size from shared library in KB. */
u_longlong_t heap_size; /* Heap size in KB. */
u_longlong_t real_inuse; /* The Real memory (in KB) in use by the process including all kind of segments (excluding system segments). This includes text, data, shared library text, shared library data, file pages, shared memory, and memory mapped. */
u_longlong_t virt_inuse; /* The virtual memory (in KB) in use by the process including all kind of segments (excluding system segments). This includes text, data, shared library text, shared library data, file pages, shared memory, and memory mapped. */
u_longlong_t pinned; /* Pinned memory (in KB) for this process inclusive of all segments. */
u_longlong_t pgsp_inuse; /* Paging space used (in KB) inclusive of all segments. */
u_longlong_t filepages; /* File pages used (in KB) including shared pages. */
u_longlong_t real_inuse_map; /* Real memory used (in KB) for shared memory and memory mapped regions */
u_longlong_t virt_inuse_map; /* Virtual memory used (in KB) for shared memory and memory mapped regions. */
u_longlong_t pinned_inuse_map; /* Pinned memory used (in KB) for shared memory and memory mapped regions. */
double ucpu_time; /* User mode CPU time is in percentage or milliseconds, which is based on, whether it is filled by perfstat_process_util or perfstat_process respectively. */
double scpu_time; /* System mode CPU time is in percentage or milliseconds, which is based on whether it is filled by perfstat_process_util or perfstat_process respectively. */
u_longlong_t last_timebase; /* Timebase counter. */
u_longlong_t inBytes; /* Bytes written to disk. */
u_longlong_t outBytes; /* Bytes read from disk. */
u_longlong_t inOps; /* In operations from disk. */
u_longlong_t outOps; /* Out operations from disk */
} perfstat_process_t;
typedef union { /* WPAR Type & Flags */
uint w;
struct {
@ -854,9 +986,14 @@ typedef struct { /* WPAR identifier */
// end: libperfstat.h (AIX 5.2, 5.3, 6.1, 7.1)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define PERFSTAT_PARTITON_TOTAL_T_LATEST perfstat_partition_total_t_71_1/* latest perfstat_partition_total_t structure */
#define PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t_72 /* latest perfstat_cpu_total_t structure */
#define PERFSTAT_WPAR_TOTAL_T_LATEST perfstat_wpar_total_t_71 /* latest perfstat_wpar_total_t structure */
#define PERFSTAT_PARTITON_TOTAL_T_LATEST perfstat_partition_total_t_71_1 /* latest perfstat_partition_total_t structure */
#define PERFSTAT_PROCESS_T_LATEST perfstat_process_t /* latest perfstat_process_t structure */
#define PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t_72 /* latest perfstat_cpu_total_t structure */
#define PERFSTAT_CPU_T_LATEST perfstat_cpu_t /* latest perfstat_cpu_t structure */
#define PERFSTAT_NETINTERFACE_T_LATEST perfstat_netinterface_t /* latest perfstat_netinterface_t structure */
#define PERFSTAT_WPAR_TOTAL_T_LATEST perfstat_wpar_total_t_71 /* latest perfstat_wpar_total_t structure */
typedef PERFSTAT_CPU_TOTAL_T_LATEST perfstat_cpu_total_t;
class libperfstat {
@ -886,6 +1023,14 @@ public:
static cid_t wpar_getcid();
static int perfstat_cpu(perfstat_id_t *name, PERFSTAT_CPU_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number);
static int perfstat_process(perfstat_id_t *name, PERFSTAT_PROCESS_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number);
static int perfstat_netinterface(perfstat_id_t *name, PERFSTAT_NETINTERFACE_T_LATEST* userbuff,
int sizeof_userbuff, int desired_number);
////////////////////////////////////////////////////////////////
// The convenience functions get_partitioninfo(), get_cpuinfo(), get_wparinfo() return

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
* Copyright (c) 2022, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -110,13 +111,7 @@ static StringList g_stringlist;
// eternal - this list is rebuilt on every reload.
// Note that we do not hand out those entries, but copies of them.
struct entry_t {
entry_t* next;
loaded_module_t info;
};
static void print_entry(const entry_t* e, outputStream* os) {
const loaded_module_t* const lm = &(e->info);
static void print_entry(const loaded_module_t* lm, outputStream* os) {
os->print(" %c text: " INTPTR_FORMAT " - " INTPTR_FORMAT
", data: " INTPTR_FORMAT " - " INTPTR_FORMAT " "
"%s",
@ -129,50 +124,50 @@ static void print_entry(const entry_t* e, outputStream* os) {
}
}
static entry_t* g_first = NULL;
static loaded_module_t* g_first = NULL;
static entry_t* find_entry_for_text_address(const void* p) {
for (entry_t* e = g_first; e; e = e->next) {
if ((uintptr_t)p >= (uintptr_t)e->info.text &&
(uintptr_t)p < ((uintptr_t)e->info.text + e->info.text_len)) {
return e;
static loaded_module_t* find_entry_for_text_address(const void* p) {
for (loaded_module_t* lm = g_first; lm; lm = lm->next) {
if ((uintptr_t)p >= (uintptr_t)lm->text &&
(uintptr_t)p < ((uintptr_t)lm->text + lm->text_len)) {
return lm;
}
}
return NULL;
}
static entry_t* find_entry_for_data_address(const void* p) {
for (entry_t* e = g_first; e; e = e->next) {
if ((uintptr_t)p >= (uintptr_t)e->info.data &&
(uintptr_t)p < ((uintptr_t)e->info.data + e->info.data_len)) {
return e;
static loaded_module_t* find_entry_for_data_address(const void* p) {
for (loaded_module_t* lm = g_first; lm; lm = lm->next) {
if ((uintptr_t)p >= (uintptr_t)lm->data &&
(uintptr_t)p < ((uintptr_t)lm->data + lm->data_len)) {
return lm;
}
}
return NULL;
}
// Adds a new entry to the list (ordered by text address ascending).
static void add_entry_to_list(entry_t* e, entry_t** start) {
entry_t* last = NULL;
entry_t* e2 = *start;
while (e2 && e2->info.text < e->info.text) {
last = e2;
e2 = e2->next;
static void add_entry_to_list(loaded_module_t* lm, loaded_module_t** start) {
loaded_module_t* last = NULL;
loaded_module_t* lm2 = *start;
while (lm2 && lm2->text < lm->text) {
last = lm2;
lm2 = lm2->next;
}
if (last) {
last->next = e;
last->next = lm;
} else {
*start = e;
*start = lm;
}
e->next = e2;
lm->next = lm2;
}
static void free_entry_list(entry_t** start) {
entry_t* e = *start;
while (e) {
entry_t* const e2 = e->next;
::free(e);
e = e2;
static void free_entry_list(loaded_module_t** start) {
loaded_module_t* lm = *start;
while (lm) {
loaded_module_t* const lm2 = lm->next;
::free(lm);
lm = lm2;
}
*start = NULL;
}
@ -186,7 +181,7 @@ static bool reload_table() {
trcVerbose("reload module table...");
entry_t* new_list = NULL;
loaded_module_t* new_list = NULL;
const struct ld_info* ldi = NULL;
// Call loadquery(L_GETINFO..) to get a list of all loaded Dlls from AIX. loadquery
@ -214,33 +209,33 @@ static bool reload_table() {
for (;;) {
entry_t* e = (entry_t*) ::malloc(sizeof(entry_t));
if (!e) {
loaded_module_t* lm = (loaded_module_t*) ::malloc(sizeof(loaded_module_t));
if (!lm) {
trcVerbose("OOM.");
goto cleanup;
}
memset(e, 0, sizeof(entry_t));
memset(lm, 0, sizeof(loaded_module_t));
e->info.text = ldi->ldinfo_textorg;
e->info.text_len = ldi->ldinfo_textsize;
e->info.data = ldi->ldinfo_dataorg;
e->info.data_len = ldi->ldinfo_datasize;
lm->text = ldi->ldinfo_textorg;
lm->text_len = ldi->ldinfo_textsize;
lm->data = ldi->ldinfo_dataorg;
lm->data_len = ldi->ldinfo_datasize;
e->info.path = g_stringlist.add(ldi->ldinfo_filename);
if (!e->info.path) {
lm->path = g_stringlist.add(ldi->ldinfo_filename);
if (!lm->path) {
trcVerbose("OOM.");
goto cleanup;
}
// Extract short name
{
const char* p = strrchr(e->info.path, '/');
const char* p = strrchr(lm->path, '/');
if (p) {
p ++;
e->info.shortname = p;
lm->shortname = p;
} else {
e->info.shortname = e->info.path;
lm->shortname = lm->path;
}
}
@ -248,32 +243,32 @@ static bool reload_table() {
const char* p_mbr_name =
ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1;
if (*p_mbr_name) {
e->info.member = g_stringlist.add(p_mbr_name);
if (!e->info.member) {
lm->member = g_stringlist.add(p_mbr_name);
if (!lm->member) {
trcVerbose("OOM.");
goto cleanup;
}
} else {
e->info.member = NULL;
lm->member = NULL;
}
if (strcmp(e->info.shortname, "libjvm.so") == 0) {
if (strcmp(lm->shortname, "libjvm.so") == 0) {
// Note that this, theoretically, is fuzzy. We may accidentally contain
// more than one libjvm.so. But that is improbable, so lets go with this
// solution.
e->info.is_in_vm = true;
lm->is_in_vm = true;
}
trcVerbose("entry: %p " SIZE_FORMAT ", %p " SIZE_FORMAT ", %s %s %s, %d",
e->info.text, e->info.text_len,
e->info.data, e->info.data_len,
e->info.path, e->info.shortname,
(e->info.member ? e->info.member : "NULL"),
e->info.is_in_vm
lm->text, lm->text_len,
lm->data, lm->data_len,
lm->path, lm->shortname,
(lm->member ? lm->member : "NULL"),
lm->is_in_vm
);
// Add to list.
add_entry_to_list(e, &new_list);
add_entry_to_list(lm, &new_list);
// Next entry...
if (ldi->ldinfo_next) {
@ -304,6 +299,23 @@ cleanup:
} // end LoadedLibraries::reload()
// Callback for loaded module information (from os.hpp)
// Input parameters:
// char* module_file_name,
// address module_base_addr,
// address module_top_addr,
// void* param
static bool for_each_internal(os::LoadedModulesCallbackFunc cb, void* param) {
for (const loaded_module_t* lm = g_first; lm; lm = lm->next) {
(*cb)(lm->shortname,
(address) lm->text,
(address) lm->text + lm->text_len,
param);
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// Externals
@ -322,8 +334,8 @@ void LoadedLibraries::print(outputStream* os) {
if (!g_first) {
reload_table();
}
for (entry_t* e = g_first; e; e = e->next) {
print_entry(e, os);
for (loaded_module_t* lm = g_first; lm; lm = lm->next) {
print_entry(lm, os);
os->cr();
}
}
@ -334,14 +346,17 @@ bool LoadedLibraries::find_for_text_address(const void* p,
if (!g_first) {
reload_table();
}
const entry_t* const e = find_entry_for_text_address(p);
if (e) {
if (info) {
*info = e->info;
}
return true;
const loaded_module_t* const lm = find_entry_for_text_address(p);
if (!lm) {
return false;
}
return false;
if (info) {
memcpy(info, lm, sizeof(loaded_module_t));
info->next = nullptr;
}
return true;
}
@ -353,13 +368,30 @@ bool LoadedLibraries::find_for_data_address (
if (!g_first) {
reload_table();
}
const entry_t* const e = find_entry_for_data_address(p);
if (e) {
if (info) {
*info = e->info;
}
return true;
const loaded_module_t* const lm = find_entry_for_data_address(p);
if (!lm) {
return false;
}
return false;
if (info) {
memcpy(info, lm, sizeof(loaded_module_t));
info->next = nullptr;
}
return true;
}
bool LoadedLibraries::for_each(os::LoadedModulesCallbackFunc cb, void* param) {
MiscUtils::AutoCritSect lck(&g_cs);
if (!g_first) {
if (!reload_table()) {
// If the table is not loaded and cannot be initialized,
// then we must quit.
return false;
}
}
return for_each_internal(cb, param);
}

View File

@ -1,4 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -32,6 +33,9 @@
#ifndef OS_AIX_LOADLIB_AIX_HPP
#define OS_AIX_LOADLIB_AIX_HPP
#include "misc_aix.hpp"
#include "runtime/os.hpp"
#include <stddef.h>
class outputStream;
@ -66,6 +70,9 @@ struct loaded_module_t {
// True if this module is part of the vm.
bool is_in_vm;
// Next item in the list, or NULL if no such item exits
loaded_module_t* next;
};
// This class is a singleton holding a map of all loaded binaries
@ -99,6 +106,11 @@ class LoadedLibraries
// Output debug info
static void print(outputStream* os);
// Apply the callback to each loaded_module_t in the list
// Return false if module table is empty and cannot be loaded.
static bool for_each(os::LoadedModulesCallbackFunc cb, void* param);
};
#endif // OS_AIX_LOADLIB_AIX_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -1131,7 +1131,11 @@ void os::get_summary_os_info(char* buf, size_t buflen) {
}
int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
// Not yet implemented.
if (!LoadedLibraries::for_each(callback, param)) {
return -1;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014 SAP SE. All rights reserved.
* Copyright (c) 2022, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +25,7 @@
*/
#include "precompiled.hpp"
#include "memory/metaspace.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/thread.hpp"
@ -34,6 +36,8 @@ frame JavaThread::pd_last_frame() {
address pc = _anchor.last_Java_pc();
// Last_Java_pc ist not set, if we come here from compiled code.
// Assume spill slot for link register contains a suitable pc.
// Should have been filled by method entry code.
if (pc == NULL)
pc = (address) *(sp + 2);
@ -41,16 +45,71 @@ frame JavaThread::pd_last_frame() {
}
bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava) {
ucontext_t* uc = (ucontext_t*) ucontext;
*fr_addr = frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/],
(address)uc->uc_mcontext.jmp_context.iar);
return true;
}
// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC.
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
Unimplemented();
// If we have a last_Java_frame, then we should use it even if
// isInJava == true. It should be more reliable than ucontext info.
if (has_last_Java_frame() && frame_anchor()->walkable()) {
*fr_addr = pd_last_frame();
return true;
}
// At this point, we don't have a last_Java_frame, so
// we try to glean some information out of the ucontext
// if we were running Java code when SIGPROF came in.
if (isInJava) {
ucontext_t* uc = (ucontext_t*) ucontext;
address pc = (address)uc->uc_mcontext.jmp_context.iar;
if (pc == NULL) {
// ucontext wasn't useful
return false;
}
frame ret_frame((intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/], pc);
if (ret_frame.fp() == NULL) {
// The found frame does not have a valid frame pointer.
// Bail out because this will create big trouble later on, either
// - when using istate, calculated as (NULL - ijava_state_size) or
// - when using fp() directly in safe_for_sender()
//
// There is no conclusive description (yet) how this could happen, but it does.
// For more details on what was observed, see thread_linux_s390.cpp
return false;
}
if (ret_frame.is_interpreted_frame()) {
frame::ijava_state *istate = ret_frame.get_ijava_state();
const Method *m = (const Method*)(istate->method);
if (!Method::is_valid_method(m)) return false;
if (!Metaspace::contains(m->constMethod())) return false;
uint64_t reg_bcp = uc->uc_mcontext.jmp_context.gpr[14/*R14_bcp*/];
uint64_t istate_bcp = istate->bcp;
uint64_t code_start = (uint64_t)(m->code_base());
uint64_t code_end = (uint64_t)(m->code_base() + m->code_size());
if (istate_bcp >= code_start && istate_bcp < code_end) {
// we have a valid bcp, don't touch it, do nothing
} else if (reg_bcp >= code_start && reg_bcp < code_end) {
istate->bcp = reg_bcp;
} else {
return false;
}
}
if (!ret_frame.safe_for_sender(this)) {
// nothing else to try if the frame isn't good
return false;
}
*fr_addr = ret_frame;
return true;
}
// nothing else to try
return false;
}
// Forte Analyzer AsyncGetCallTrace profiling support.
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {
return pd_get_top_frame_for_profiling(fr_addr, ucontext, isInJava);
}
void JavaThread::cache_global_variables() { }

View File

@ -821,7 +821,7 @@ javax/script/Test7.java 8239361 generic-
# jdk_jfr
jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990 generic-all
jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990 macosx-all,linux-all,windows-all
jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all
jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all
jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -77,7 +77,10 @@ public class TestNativeLibrariesEvent {
libTemplate = "lib%s.dylib";
} else if (Platform.isLinux()) {
libTemplate = "lib%s.so";
} else if (Platform.isAix()) {
libTemplate = "lib%s.so";
}
if (libTemplate == null) {
throw new Exception("Unsupported OS");
}