void cpu_sample_term(JNIEnv *env) { gdata->pause_cpu_sampling = JNI_FALSE; rawMonitorEnter(gdata->cpu_sample_lock); { /* Notify the CPU sampling thread to get out of any sampling Wait */ rawMonitorNotifyAll(gdata->cpu_sample_lock); } rawMonitorExit(gdata->cpu_sample_lock); rawMonitorEnter(gdata->cpu_loop_lock); { if ( gdata->cpu_loop_running ) { gdata->cpu_loop_running = JNI_FALSE; /* Wait for cpu_loop_function() thread to tell us it completed. */ rawMonitorWait(gdata->cpu_loop_lock, 0); } } rawMonitorExit(gdata->cpu_loop_lock); }
void cpu_sample_on(JNIEnv *env, ObjectIndex object_index) { if ( gdata->cpu_loop_lock == NULL ) { cpu_sample_init(env); } if (object_index == 0) { gdata->cpu_sampling = JNI_TRUE; gdata->pause_cpu_sampling = JNI_FALSE; } else { jint count; tls_set_sample_status(object_index, 1); count = tls_sum_sample_status(); if ( count > 0 ) { gdata->pause_cpu_sampling = JNI_FALSE; } } /* Notify the CPU sampling thread that sampling is on */ rawMonitorEnter(gdata->cpu_sample_lock); { rawMonitorNotifyAll(gdata->cpu_sample_lock); } rawMonitorExit(gdata->cpu_sample_lock); }
void site_heapdump(JNIEnv *env) { rawMonitorEnter(gdata->data_access_lock); { jvmtiHeapCallbacks heapCallbacks; /* Remove class dumped status, all classes must be dumped */ class_all_status_remove(CLASS_DUMPED); /* Clear in_heap_dump flag */ tls_clear_in_heap_dump(); /* Dump the last thread traces and get the lists back we need */ tls_dump_traces(env); /* Write header for heap dump */ io_heap_header(gdata->total_live_instances, gdata->total_live_bytes); /* Setup a clean reference table */ reference_init(); /* Walk over all reachable objects and dump out roots */ gdata->gref_serial_number_counter = gdata->gref_serial_number_start; /* Issue thread object for fake non-existent unknown thread * just in case someone refers to it. Real threads are handled * during iterate over reachable objects. */ io_heap_root_thread_object(0, gdata->unknown_thread_serial_num, trace_get_serial_number(gdata->system_trace_index)); /* Iterate over heap and get the real stuff */ (void)memset(&heapCallbacks, 0, sizeof(heapCallbacks)); /* Select callbacks */ heapCallbacks.heap_reference_callback = &cbReference; if ( gdata->primfields == JNI_TRUE ) { heapCallbacks.primitive_field_callback = &cbPrimFieldData; } if ( gdata->primarrays == JNI_TRUE ) { heapCallbacks.array_primitive_value_callback = &cbPrimArrayData; } followReferences(&heapCallbacks, (void*)NULL); /* Process reference information. */ object_reference_dump(env); object_clear_references(); reference_cleanup(); /* Dump the last thread traces and get the lists back we need */ tls_dump_traces(env); /* Write out footer for heap dump */ io_heap_footer(); } rawMonitorExit(gdata->data_access_lock); }
void site_heapdump(JNIEnv *env) { rawMonitorEnter(gdata->data_access_lock); { struct { int i; } user_data; /* FIXUP */ user_data.i = 0; /* Remove class dumped status, all classes must be dumped */ class_all_status_remove(CLASS_DUMPED); /* Clear in_heap_dump flag */ tls_clear_in_heap_dump(); /* Dump the last thread traces and get the lists back we need */ tls_dump_traces(env); /* Write header for heap dump */ io_heap_header(gdata->total_live_instances, gdata->total_live_bytes); /* Setup a clean reference table */ reference_init(); /* Walk over all reachable objects and dump out roots */ gdata->gref_serial_number_counter = gdata->gref_serial_number_start; /* Issue thread object for fake non-existent unknown thread * just in case someone refers to it. Real threads are handled * during iterate over reachable objects. */ io_heap_root_thread_object(0, gdata->unknown_thread_serial_num, trace_get_serial_number(gdata->system_trace_index)); /* Iterate over heap and get the real stuff */ iterateOverReachableObjects(&root_object, &stack_object, &reference_object, (void*)&user_data); /* Process reference information. */ object_reference_dump(env); object_clear_references(); reference_cleanup(); /* Dump the last thread traces and get the lists back we need */ tls_dump_traces(env); /* Write out footer for heap dump */ io_heap_footer(); } rawMonitorExit(gdata->data_access_lock); }
void cpu_sample_init(JNIEnv *env) { gdata->cpu_sampling = JNI_TRUE; /* Create the raw monitors needed */ gdata->cpu_loop_lock = createRawMonitor("HPROF cpu loop lock"); gdata->cpu_sample_lock = createRawMonitor("HPROF cpu sample lock"); rawMonitorEnter(gdata->cpu_loop_lock); { createAgentThread(env, "HPROF cpu sampling thread", &cpu_loop_function); /* Wait for cpu_loop_function() to notify us it has started. */ rawMonitorWait(gdata->cpu_loop_lock, 0); } rawMonitorExit(gdata->cpu_loop_lock); }
void site_heapdump(JNIEnv *env) { rawMonitorEnter(gdata->data_access_lock); { struct { int i; } user_data; /* FIXUP */ user_data.i = 0; /* Dump the last thread traces and get the lists back we need */ tls_dump_traces(env); /* Write header for heap dump */ io_heap_header(gdata->total_live_instances, gdata->total_live_bytes); /* Write out the thread roots first (threads that ended already did) */ tls_output_heap_threads(); /* Setup a clean reference table */ reference_init(); /* Walk over all reachable objects and dump out roots */ gdata->gref_serial_number_counter = gdata->gref_serial_number_start; iterateOverReachableObjects(&root_object, &stack_object, &reference_object, (void*)&user_data); /* Process reference information. */ object_reference_dump(env); object_clear_references(); reference_cleanup(); /* Dump the last thread traces and get the lists back we need */ tls_dump_traces(env); /* Write out footer for heap dump */ io_heap_footer(); } rawMonitorExit(gdata->data_access_lock); }
void site_write(JNIEnv *env, int flags, double cutoff) { HPROF_ASSERT(gdata->site_table!=NULL); LOG3("site_write", "flags", flags); if (flags & SITE_FORCE_GC) { runGC(); } HPROF_ASSERT(gdata->total_live_bytes!=0); rawMonitorEnter(gdata->data_access_lock); { IterateInfo iterate; int site_table_size; double accum_percent; void * comment_str; int i; int cutoff_count; int nbytes; accum_percent = 0; site_table_size = table_element_count(gdata->site_table); (void)memset(&iterate, 0, sizeof(iterate)); nbytes = site_table_size * (int)sizeof(SiteIndex); if ( nbytes > 0 ) { iterate.site_nums = HPROF_MALLOC(nbytes); (void)memset(iterate.site_nums, 0, nbytes); } iterate.count = 0; iterate.changed_only = flags & SITE_DUMP_INCREMENTAL; table_walk_items(gdata->site_table, &collect_iterator, &iterate); site_table_size = iterate.count; if (flags & SITE_SORT_BY_ALLOC) { comment_str = "allocated bytes"; qsort(iterate.site_nums, site_table_size, sizeof(SiteIndex), &qsort_compare_allocated_bytes); } else { comment_str = "live bytes"; qsort(iterate.site_nums, site_table_size, sizeof(SiteIndex), &qsort_compare_live_bytes); } trace_output_unmarked(env); cutoff_count = 0; for (i = 0; i < site_table_size; i++) { SiteInfo *info; SiteIndex index; double ratio; index= iterate.site_nums[i]; HPROF_ASSERT(index!=0); info = get_info(index); ratio = (double)info->n_live_bytes / (double)gdata->total_live_bytes; if (ratio < cutoff) { break; } cutoff_count++; } io_write_sites_header( comment_str, flags, cutoff, gdata->total_live_bytes, gdata->total_live_instances, gdata->total_alloced_bytes, gdata->total_alloced_instances, cutoff_count); for (i = 0; i < cutoff_count; i++) { SiteInfo *info; SiteKey *pkey; SiteIndex index; char *class_signature; double ratio; index = iterate.site_nums[i]; pkey = get_pkey(index); info = get_info(index); ratio = (double)info->n_live_bytes / (double)gdata->total_live_bytes; accum_percent += ratio; class_signature = string_get(class_get_signature(pkey->cnum)); io_write_sites_elem(i + 1, ratio, accum_percent, class_signature, class_get_serial_number(pkey->cnum), trace_get_serial_number(pkey->trace_index), info->n_live_bytes, info->n_live_instances, info->n_alloced_bytes, info->n_alloced_instances); } io_write_sites_footer(); table_walk_items(gdata->site_table, &mark_unchanged_iterator, NULL); if ( iterate.site_nums != NULL ) { HPROF_FREE(iterate.site_nums); } } rawMonitorExit(gdata->data_access_lock); }
static void JNICALL cpu_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p) { int loop_trip_counter; jboolean cpu_loop_running; loop_trip_counter = 0; rawMonitorEnter(gdata->cpu_loop_lock); { gdata->cpu_loop_running = JNI_TRUE; cpu_loop_running = gdata->cpu_loop_running; /* Notify cpu_sample_init() that we have started */ rawMonitorNotifyAll(gdata->cpu_loop_lock); } rawMonitorExit(gdata->cpu_loop_lock); rawMonitorEnter(gdata->cpu_sample_lock); /* Only waits inside loop let go */ while ( cpu_loop_running ) { ++loop_trip_counter; LOG3("cpu_loop()", "iteration", loop_trip_counter); /* If a dump is in progress, we pause sampling. */ rawMonitorEnter(gdata->dump_lock); { if (gdata->dump_in_process) { gdata->pause_cpu_sampling = JNI_TRUE; } } rawMonitorExit(gdata->dump_lock); /* Check to see if we need to pause sampling (listener_loop command) */ if (gdata->pause_cpu_sampling) { /* * Pause sampling for now. Reset sample controls if * sampling is resumed again. */ rawMonitorWait(gdata->cpu_sample_lock, 0); rawMonitorEnter(gdata->cpu_loop_lock); { cpu_loop_running = gdata->cpu_loop_running; } rawMonitorExit(gdata->cpu_loop_lock); /* Continue the while loop, which will terminate if done. */ continue; } /* This is the normal short timed wait before getting a sample */ rawMonitorWait(gdata->cpu_sample_lock, (jlong)gdata->sample_interval); /* Make sure we really want to continue */ rawMonitorEnter(gdata->cpu_loop_lock); { cpu_loop_running = gdata->cpu_loop_running; } rawMonitorExit(gdata->cpu_loop_lock); /* Break out if we are done */ if ( !cpu_loop_running ) { break; } /* * If a dump request came in after we checked at the top of * the while loop, then we catch that fact here. We * don't want to perturb the data that is being dumped so * we just ignore the data from this sampling loop. */ rawMonitorEnter(gdata->dump_lock); { if (gdata->dump_in_process) { gdata->pause_cpu_sampling = JNI_TRUE; } } rawMonitorExit(gdata->dump_lock); /* Sample all the threads and update trace costs */ if ( !gdata->pause_cpu_sampling) { tls_sample_all_threads(env); } /* Check to see if we need to finish */ rawMonitorEnter(gdata->cpu_loop_lock); { cpu_loop_running = gdata->cpu_loop_running; } rawMonitorExit(gdata->cpu_loop_lock); } rawMonitorExit(gdata->cpu_sample_lock); rawMonitorEnter(gdata->cpu_loop_lock); { /* Notify cpu_sample_term() that we are done. */ rawMonitorNotifyAll(gdata->cpu_loop_lock); } rawMonitorExit(gdata->cpu_loop_lock); LOG2("cpu_loop()", "clean termination"); }