void hprof_thread_end_event(JNIEnv *env_id) { hprof_thread_t thread_tmp; hprof_thread_t *thread; CALL(RawMonitorEnter)(data_access_lock); #ifdef XXX_HASH_STATS { /* use the code to get current thread hash stats */ static int done = 0; if (!done) { hprof_print_thread_hash_stats(stderr); done = 1; } } #endif /* HASH_STATS */ { /* remove from list of live threads */ live_thread_t **p; p = &live_thread_list; while (*p) { live_thread_t *t = *p; if (t->env == env_id) { *p = t->next; hprof_free(t); break; } p = &(t->next); } num_live_threads--; } thread_tmp.env_id = env_id; thread = hprof_hash_lookup(&hprof_thread_table, &thread_tmp); if (thread == NULL) { fprintf(stderr, "HPROF ERROR : unknown thread ID in thread_end\n"); } else { if (output_format == 'b') { hprof_write_header(HPROF_END_THREAD, 4); hprof_write_u4(thread->serial_num); } else if ((!cpu_timing) || (timing_format != OLD_PROF_OUTPUT_FORMAT)) { /* we don't want thread info for the old prof output format */ hprof_printf("THREAD END (id = %d)\n", thread->serial_num); } if (cpu_timing) { /* bill the thread local table if method timing is on */ hprof_bill_frames_cost_table(env_id); } if (cpu_timing || monitor_tracing) { /* free the thread local table if we allocated one */ hprof_free_thread_local_info(env_id); } hprof_remove_thread(env_id); } CALL(RawMonitorExit)(data_access_lock); }
/* the callback thread */ static void hprof_callback(void *p) { while (hprof_is_on) { jint length; jint seq_num; unsigned char tag; tag = recv_u1(); if (tag == HPROF_CMD_EOF) { /* the cmd socket has closed so the listener thread is done */ break; } seq_num = recv_u4(); length = recv_u4(); switch (tag) { case HPROF_CMD_GC: CALL(RunGC)(); break; case HPROF_CMD_DUMP_HEAP: { hprof_get_heap_dump(); break; } case HPROF_CMD_ALLOC_SITES: { unsigned short flags = recv_u2(); unsigned int i_tmp = recv_u4(); float ratio = *(float *)(&i_tmp); hprof_output_sites(flags, ratio); break; } case HPROF_CMD_HEAP_SUMMARY: { CALL(RawMonitorEnter)(data_access_lock); hprof_write_header(HPROF_HEAP_SUMMARY, 24); hprof_write_u4(total_live_bytes); hprof_write_u4(total_live_instances); hprof_write_u4(jlong_high(total_alloced_bytes)); hprof_write_u4(jlong_low(total_alloced_bytes)); hprof_write_u4(jlong_high(total_alloced_instances)); hprof_write_u4(jlong_low(total_alloced_instances)); CALL(RawMonitorExit)(data_access_lock); break; } case HPROF_CMD_EXIT: hprof_is_on = FALSE; fprintf(stderr, "HPROF: received exit event, exiting ...\n"); CALL(ProfilerExit)((jint)0); case HPROF_CMD_DUMP_TRACES: CALL(RawMonitorEnter)(data_access_lock); hprof_output_unmarked_traces(); CALL(RawMonitorExit)(data_access_lock); break; case HPROF_CMD_CPU_SAMPLES: { unsigned short flags = recv_u2(); unsigned int i_tmp = recv_u4(); float ratio = *(float *)(&i_tmp); hprof_output_trace_cost(ratio, CPU_SAMPLES_RECORD_NAME); break; } case HPROF_CMD_CONTROL: { unsigned short cmd = recv_u2(); if (cmd == 0x0001) { CALL(EnableEvent)(JVMPI_EVENT_OBJ_ALLOC, NULL); } else if (cmd == 0x0002) { CALL(DisableEvent)(JVMPI_EVENT_OBJ_ALLOC, NULL); } else if (cmd == 0x0003) { hprof_objmap_t *thread_id = recv_id(); hprof_cpu_sample_on(thread_id); } else if (cmd == 0x0004) { hprof_objmap_t *thread_id = recv_id(); hprof_cpu_sample_off(thread_id); } else if (cmd == 0x0005) { CALL(RawMonitorEnter)(data_access_lock); hprof_clear_trace_cost(); CALL(RawMonitorExit)(data_access_lock); } else if (cmd == 0x0006) { CALL(RawMonitorEnter)(data_access_lock); hprof_clear_site_table(); CALL(RawMonitorExit)(data_access_lock); } else if (cmd == 0x0007) { max_trace_depth = recv_u2(); } break; } default: if (hprof_is_on) { hprof_is_on = FALSE; fprintf(stderr, "HPROF ERROR : failed to recognize cmd %d, exiting..\n", (int)tag); } CALL(ProfilerExit)((jint)1); } CALL(RawMonitorEnter)(data_access_lock); hprof_flush(); CALL(RawMonitorExit)(data_access_lock); } }
void hprof_thread_start_event(JNIEnv *env_id, char *t_name, char *g_name, char *p_name, jobjectID thread_id, int requested) { hprof_thread_t *result; hprof_name_t *thread_name; hprof_name_t *group_name; hprof_name_t *parent_name; hprof_objmap_t *objmap; CALL(RawMonitorEnter)(data_access_lock); objmap = hprof_fetch_object_info(thread_id); if (objmap == NULL) { fprintf(stderr, "HPROF ERROR: unable to map JVMPI thread ID to hprof " "thread ID in thread_start \n"); goto threadstart_done; } result = hprof_intern_thread(env_id); if (result->thread_id != NULL) { goto threadstart_done; } { live_thread_t *newthread = HPROF_CALLOC(ALLOC_TYPE_LIVE_THREAD, sizeof(live_thread_t)); /* add to the list of live threads */ newthread->next = live_thread_list; newthread->tid = objmap; newthread->env = env_id; newthread->cpu_sampled = 1; live_thread_list = newthread; num_live_threads++; } result = hprof_intern_thread(env_id); if (result->thread_id != NULL) { fprintf(stderr, "HPROF ERROR : thread ID already in use\n"); goto threadstart_done; } result->thread_id = objmap; thread_name = hprof_intern_name(t_name); group_name = hprof_intern_name(g_name); parent_name = hprof_intern_name(p_name); #ifdef HASH_STATS if (cpu_timing) { hprof_thread_local_t *info = (hprof_thread_local_t *)(CALL(GetThreadLocalStorage)(env_id)); info->thread_name = thread_name; info->group_name = group_name; info->parent_name = parent_name; } #endif /* HASH_STATS */ if (output_format == 'b') { int trace_num; if (requested) { trace_num = 0; } else { hprof_trace_t *htrace = hprof_get_trace(env_id, max_trace_depth); if (htrace == NULL) { fprintf(stderr, "HPROF ERROR : got NULL trace in thread_start\n"); goto threadstart_done; } trace_num = htrace->serial_num; } hprof_write_header(HPROF_START_THREAD, sizeof(void *) * 4 + 8); hprof_write_u4(result->serial_num); hprof_write_id(objmap); hprof_write_u4(trace_num); hprof_write_id(thread_name); hprof_write_id(group_name); hprof_write_id(parent_name); } else if ((!cpu_timing) || (timing_format != OLD_PROF_OUTPUT_FORMAT)) { /* we don't want thread info for the old prof output format */ hprof_printf("THREAD START " "(obj=%x, id = %d, name=\"%s\", group=\"%s\")\n", objmap, result->serial_num, thread_name->name, group_name->name); } threadstart_done: CALL(RawMonitorExit)(data_access_lock); }