< prev index next >
test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitor.c
Print this page
rev 49264 : [mq]: event-only
rev 49266 : [mq]: event4
rev 49267 : [mq]: event5
rev 49268 : [mq]: event6
*** 58,77 ****
size_t frame_count;
jthread thread;
} ObjectTrace;
typedef struct _EventStorage {
- int compaction_required;
int live_object_size;
int live_object_count;
ObjectTrace** live_objects;
int garbage_history_size;
int garbage_history_index;
ObjectTrace** garbage_collected_objects;
! pthread_mutex_t mutex;
} EventStorage;
typedef struct _ExpectedContentFrame {
const char *name;
const char *signature;
--- 58,81 ----
size_t frame_count;
jthread thread;
} ObjectTrace;
typedef struct _EventStorage {
int live_object_size;
int live_object_count;
ObjectTrace** live_objects;
int garbage_history_size;
int garbage_history_index;
ObjectTrace** garbage_collected_objects;
! // Two separate mutexes to separate storage data race and the compaction field
! // data race.
! pthread_mutex_t storage_mutex;
!
! int compaction_required;
! pthread_mutex_t compaction_mutex;
} EventStorage;
typedef struct _ExpectedContentFrame {
const char *name;
const char *signature;
*** 232,262 ****
// Internal storage system implementation.
static EventStorage global_event_storage;
static void event_storage_set_compaction_required(EventStorage* storage) {
! pthread_mutex_lock(&storage->mutex);
storage->compaction_required = 1;
! pthread_mutex_unlock(&storage->mutex);
}
static int event_storage_get_compaction_required(EventStorage* storage) {
! pthread_mutex_lock(&storage->mutex);
int result = storage->compaction_required;
! pthread_mutex_unlock(&storage->mutex);
return result;
}
static void event_storage_set_garbage_history(EventStorage* storage, int value) {
! pthread_mutex_lock(&storage->mutex);
global_event_storage.garbage_history_size = value;
free(global_event_storage.garbage_collected_objects);
size_t size =
sizeof(*global_event_storage.garbage_collected_objects) * value;
global_event_storage.garbage_collected_objects = malloc(size);
memset(global_event_storage.garbage_collected_objects, 0, size);
! pthread_mutex_unlock(&storage->mutex);
}
// No mutex here, it is handled by the caller.
static void event_storage_add_garbage_collected_object(EventStorage* storage,
ObjectTrace* object) {
--- 236,266 ----
// Internal storage system implementation.
static EventStorage global_event_storage;
static void event_storage_set_compaction_required(EventStorage* storage) {
! pthread_mutex_lock(&storage->compaction_mutex);
storage->compaction_required = 1;
! pthread_mutex_unlock(&storage->compaction_mutex);
}
static int event_storage_get_compaction_required(EventStorage* storage) {
! pthread_mutex_lock(&storage->compaction_mutex);
int result = storage->compaction_required;
! pthread_mutex_unlock(&storage->compaction_mutex);
return result;
}
static void event_storage_set_garbage_history(EventStorage* storage, int value) {
! pthread_mutex_lock(&storage->storage_mutex);
global_event_storage.garbage_history_size = value;
free(global_event_storage.garbage_collected_objects);
size_t size =
sizeof(*global_event_storage.garbage_collected_objects) * value;
global_event_storage.garbage_collected_objects = malloc(size);
memset(global_event_storage.garbage_collected_objects, 0, size);
! pthread_mutex_unlock(&storage->storage_mutex);
}
// No mutex here, it is handled by the caller.
static void event_storage_add_garbage_collected_object(EventStorage* storage,
ObjectTrace* object) {
*** 265,317 ****
storage->garbage_collected_objects[idx] = object;
storage->garbage_history_index = (idx + 1) % storage->garbage_history_size;
}
static int event_storage_get_count(EventStorage* storage) {
! pthread_mutex_lock(&storage->mutex);
int result = storage->live_object_count;
! pthread_mutex_unlock(&storage->mutex);
return result;
}
static double event_storage_get_average_rate(EventStorage* storage) {
double accumulation = 0;
! pthread_mutex_lock(&storage->mutex);
int max_size = storage->live_object_count;
! for (int i = 0; i < max_size; i++) {
accumulation += storage->live_objects[i]->size;
}
! pthread_mutex_unlock(&storage->mutex);
return accumulation / max_size;
}
static jboolean event_storage_contains(JNIEnv* env,
EventStorage* storage,
ExpectedContentFrame* frames,
size_t size) {
! pthread_mutex_lock(&storage->mutex);
fprintf(stderr, "Checking storage count %d\n", storage->live_object_count);
int i;
for (i = 0; i < storage->live_object_count; i++) {
ObjectTrace* trace = storage->live_objects[i];
if (check_sample_content(env, trace, frames, size, PRINT_OUT)) {
! pthread_mutex_unlock(&storage->mutex);
return TRUE;
}
}
! pthread_mutex_unlock(&storage->mutex);
return FALSE;
}
static jboolean event_storage_garbage_contains(JNIEnv* env,
EventStorage* storage,
ExpectedContentFrame* frames,
size_t size) {
! pthread_mutex_lock(&storage->mutex);
fprintf(stderr, "Checking garbage storage count %d\n",
storage->garbage_history_size);
int i;
for (i = 0; i < storage->garbage_history_size; i++) {
ObjectTrace* trace = storage->garbage_collected_objects[i];
--- 269,322 ----
storage->garbage_collected_objects[idx] = object;
storage->garbage_history_index = (idx + 1) % storage->garbage_history_size;
}
static int event_storage_get_count(EventStorage* storage) {
! pthread_mutex_lock(&storage->storage_mutex);
int result = storage->live_object_count;
! pthread_mutex_unlock(&storage->storage_mutex);
return result;
}
static double event_storage_get_average_rate(EventStorage* storage) {
double accumulation = 0;
! pthread_mutex_lock(&storage->storage_mutex);
int max_size = storage->live_object_count;
! int i;
! for (i = 0; i < max_size; i++) {
accumulation += storage->live_objects[i]->size;
}
! pthread_mutex_unlock(&storage->storage_mutex);
return accumulation / max_size;
}
static jboolean event_storage_contains(JNIEnv* env,
EventStorage* storage,
ExpectedContentFrame* frames,
size_t size) {
! pthread_mutex_lock(&storage->storage_mutex);
fprintf(stderr, "Checking storage count %d\n", storage->live_object_count);
int i;
for (i = 0; i < storage->live_object_count; i++) {
ObjectTrace* trace = storage->live_objects[i];
if (check_sample_content(env, trace, frames, size, PRINT_OUT)) {
! pthread_mutex_unlock(&storage->storage_mutex);
return TRUE;
}
}
! pthread_mutex_unlock(&storage->storage_mutex);
return FALSE;
}
static jboolean event_storage_garbage_contains(JNIEnv* env,
EventStorage* storage,
ExpectedContentFrame* frames,
size_t size) {
! pthread_mutex_lock(&storage->storage_mutex);
fprintf(stderr, "Checking garbage storage count %d\n",
storage->garbage_history_size);
int i;
for (i = 0; i < storage->garbage_history_size; i++) {
ObjectTrace* trace = storage->garbage_collected_objects[i];
*** 319,333 ****
if (trace == NULL) {
continue;
}
if (check_sample_content(env, trace, frames, size, PRINT_OUT)) {
! pthread_mutex_unlock(&storage->mutex);
return TRUE;
}
}
! pthread_mutex_unlock(&storage->mutex);
return FALSE;
}
// No mutex here, handled by the caller.
static void event_storage_augment_storage(EventStorage* storage) {
--- 324,338 ----
if (trace == NULL) {
continue;
}
if (check_sample_content(env, trace, frames, size, PRINT_OUT)) {
! pthread_mutex_unlock(&storage->storage_mutex);
return TRUE;
}
}
! pthread_mutex_unlock(&storage->storage_mutex);
return FALSE;
}
// No mutex here, handled by the caller.
static void event_storage_augment_storage(EventStorage* storage) {
*** 352,387 ****
jint count;
jvmtiError err;
err = (*jvmti)->GetStackTrace(jvmti, thread, 0, 64, frames, &count);
if (err == JVMTI_ERROR_NONE && count >= 1) {
! pthread_mutex_lock(&storage->mutex);
!
! if (storage->live_object_count >= storage->live_object_size) {
! event_storage_augment_storage(storage);
! }
! assert(storage->live_object_count < storage->live_object_size);
!
! jvmtiFrameInfo* allocated_frames = malloc(count * sizeof(*allocated_frames));
memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
! ObjectTrace* live_object = malloc(sizeof(*live_object));
live_object->frames = allocated_frames;
live_object->frame_count = count;
live_object->size = size;
live_object->thread = thread;
live_object->object = (*jni)->NewWeakGlobalRef(jni, object);
storage->live_objects[storage->live_object_count] = live_object;
storage->live_object_count++;
! pthread_mutex_unlock(&storage->mutex);
}
}
static void event_storage_compact(EventStorage* storage, JNIEnv* jni) {
! pthread_mutex_lock(&storage->mutex);
storage->compaction_required = 0;
int max = storage->live_object_count;
int i, dest;
ObjectTrace** live_objects = storage->live_objects;
--- 357,397 ----
jint count;
jvmtiError err;
err = (*jvmti)->GetStackTrace(jvmti, thread, 0, 64, frames, &count);
if (err == JVMTI_ERROR_NONE && count >= 1) {
! jvmtiFrameInfo* allocated_frames = (jvmtiFrameInfo*) malloc(count * sizeof(*allocated_frames));
memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
! ObjectTrace* live_object = (ObjectTrace*) malloc(sizeof(*live_object));
live_object->frames = allocated_frames;
live_object->frame_count = count;
live_object->size = size;
live_object->thread = thread;
live_object->object = (*jni)->NewWeakGlobalRef(jni, object);
+
+ // Only now lock and get things done quickly.
+ pthread_mutex_lock(&storage->storage_mutex);
+
+ if (storage->live_object_count >= storage->live_object_size) {
+ event_storage_augment_storage(storage);
+ }
+ assert(storage->live_object_count < storage->live_object_size);
+
storage->live_objects[storage->live_object_count] = live_object;
storage->live_object_count++;
! pthread_mutex_unlock(&storage->storage_mutex);
}
}
static void event_storage_compact(EventStorage* storage, JNIEnv* jni) {
! pthread_mutex_lock(&storage->compaction_mutex);
storage->compaction_required = 0;
+ pthread_mutex_unlock(&storage->compaction_mutex);
+
+ pthread_mutex_lock(&storage->storage_mutex);
int max = storage->live_object_count;
int i, dest;
ObjectTrace** live_objects = storage->live_objects;
*** 398,419 ****
event_storage_add_garbage_collected_object(storage, live_object);
}
}
storage->live_object_count = dest;
! pthread_mutex_unlock(&storage->mutex);
}
static void event_storage_free_objects(ObjectTrace** array, int max) {
int i;
for (i = 0; i < max; i++) {
free(array[i]), array[i] = NULL;
}
}
static void event_storage_reset(EventStorage* storage) {
! pthread_mutex_lock(&storage->mutex);
// Reset everything except the mutex and the garbage collection.
event_storage_free_objects(storage->live_objects,
storage->live_object_count);
storage->live_object_size = 0;
--- 408,429 ----
event_storage_add_garbage_collected_object(storage, live_object);
}
}
storage->live_object_count = dest;
! pthread_mutex_unlock(&storage->storage_mutex);
}
static void event_storage_free_objects(ObjectTrace** array, int max) {
int i;
for (i = 0; i < max; i++) {
free(array[i]), array[i] = NULL;
}
}
static void event_storage_reset(EventStorage* storage) {
! pthread_mutex_lock(&storage->storage_mutex);
// Reset everything except the mutex and the garbage collection.
event_storage_free_objects(storage->live_objects,
storage->live_object_count);
storage->live_object_size = 0;
*** 424,434 ****
storage->garbage_history_size);
storage->compaction_required = 0;
storage->garbage_history_index = 0;
! pthread_mutex_unlock(&storage->mutex);
}
// Start of the JVMTI agent code.
static const char *EXC_CNAME = "java/lang/Exception";
--- 434,444 ----
storage->garbage_history_size);
storage->compaction_required = 0;
storage->garbage_history_index = 0;
! pthread_mutex_unlock(&storage->storage_mutex);
}
// Start of the JVMTI agent code.
static const char *EXC_CNAME = "java/lang/Exception";
*** 521,531 ****
if (res != JNI_OK || jvmti == NULL) {
printf(" Error: wrong result of a valid call to GetEnv!\n");
return JNI_ERR;
}
! pthread_mutex_init(&global_event_storage.mutex, 0);
event_storage_set_garbage_history(&global_event_storage, 200);
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.SampledObjectAlloc = &SampledObjectAlloc;
--- 531,542 ----
if (res != JNI_OK || jvmti == NULL) {
printf(" Error: wrong result of a valid call to GetEnv!\n");
return JNI_ERR;
}
! pthread_mutex_init(&global_event_storage.storage_mutex, 0);
! pthread_mutex_init(&global_event_storage.compaction_mutex, 0);
event_storage_set_garbage_history(&global_event_storage, 200);
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.SampledObjectAlloc = &SampledObjectAlloc;
*** 533,553 ****
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
// Get line numbers, sample heap, sample events, and filename for the test.
caps.can_get_line_numbers = 1;
! caps.can_sample_heap = 1;
caps.can_get_source_file_name = 1;
caps.can_generate_garbage_collection_events = 1;
if (check_error((*jvmti)->AddCapabilities(jvmti, &caps), "Add capabilities")){
return JNI_ERR;
}
- if (enable_notifications()) {
- return JNI_ERR;
- }
-
if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
sizeof(jvmtiEventCallbacks)),
" Set Event Callbacks")) {
return JNI_ERR;
}
--- 544,560 ----
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
// Get line numbers, sample heap, sample events, and filename for the test.
caps.can_get_line_numbers = 1;
! caps.can_generate_sampled_alloc_events = 1;
caps.can_get_source_file_name = 1;
caps.can_generate_garbage_collection_events = 1;
if (check_error((*jvmti)->AddCapabilities(jvmti, &caps), "Add capabilities")){
return JNI_ERR;
}
if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
sizeof(jvmtiEventCallbacks)),
" Set Event Callbacks")) {
return JNI_ERR;
}
*** 620,630 ****
JNIEXPORT jboolean JNICALL
Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
jclass cls) {
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
! caps.can_sample_heap= 1;
if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
"Add capabilities\n")){
return FALSE;
}
--- 627,637 ----
JNIEXPORT jboolean JNICALL
Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
jclass cls) {
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
! caps.can_generate_sampled_alloc_events = 1;
if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
"Add capabilities\n")){
return FALSE;
}
*** 694,704 ****
}
JNIEXPORT jboolean JNICALL
Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
jint num_threads) {
! pthread_mutex_lock(&global_event_storage.mutex);
jint trace_counter;
ThreadsFound thread_data;
thread_data.num_threads = 0;
thread_data.threads = malloc(sizeof(jthread) * num_threads);
--- 701,711 ----
}
JNIEXPORT jboolean JNICALL
Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
jint num_threads) {
! pthread_mutex_lock(&global_event_storage.storage_mutex);
jint trace_counter;
ThreadsFound thread_data;
thread_data.num_threads = 0;
thread_data.threads = malloc(sizeof(jthread) * num_threads);
*** 709,719 ****
find_threads_in_array(&thread_data,
global_event_storage.garbage_collected_objects,
global_event_storage.garbage_history_size);
free(thread_data.threads);
! pthread_mutex_unlock(&global_event_storage.mutex);
return thread_data.num_threads == num_threads;
}
#ifdef __cplusplus
}
--- 716,726 ----
find_threads_in_array(&thread_data,
global_event_storage.garbage_collected_objects,
global_event_storage.garbage_history_size);
free(thread_data.threads);
! pthread_mutex_unlock(&global_event_storage.storage_mutex);
return thread_data.num_threads == num_threads;
}
#ifdef __cplusplus
}
< prev index next >