< 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 >