00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "hprof.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #define INITIAL_THREAD_STACK_LIMIT 64
00077
00078 typedef struct StackElement {
00079 FrameIndex frame_index;
00080 jmethodID method;
00081 jlong method_start_time;
00082 jlong time_in_callees;
00083 } StackElement;
00084
00085 typedef struct TlsInfo {
00086 jint sample_status;
00087 jboolean agent_thread;
00088 jthread globalref;
00089 Stack *stack;
00090 MonitorIndex monitor_index;
00091 jint tracker_status;
00092 FrameIndex *frames_buffer;
00093 jvmtiFrameInfo *jframes_buffer;
00094 int buffer_depth;
00095 TraceIndex last_trace;
00096 ObjectIndex thread_object_index;
00097 jlong monitor_start_time;
00098 jint in_heap_dump;
00099 } TlsInfo;
00100
00101 typedef struct SearchData {
00102 JNIEnv *env;
00103 jthread thread;
00104 TlsIndex found;
00105 } SearchData;
00106
00107 typedef struct IterateInfo {
00108 TlsIndex * ptls_index;
00109 jthread * pthreads;
00110 jint count;
00111 } IterateInfo;
00112
00113 typedef struct ThreadList {
00114 jthread *threads;
00115 SerialNumber *serial_nums;
00116 TlsInfo **infos;
00117 jint count;
00118 JNIEnv *env;
00119 } ThreadList;
00120
00121 typedef struct SampleData {
00122 ObjectIndex thread_object_index;
00123 jint sample_status;
00124 } SampleData;
00125
00126
00127
00128 static SerialNumber
00129 get_key(TlsIndex index)
00130 {
00131 SerialNumber *pkey;
00132 int key_len;
00133
00134 if ( index == 0 ) {
00135 return 0;
00136 }
00137 pkey = NULL;
00138 key_len = 0;
00139 table_get_key(gdata->tls_table, index, (void**)&pkey, &key_len);
00140 HPROF_ASSERT(pkey!=NULL);
00141 HPROF_ASSERT(key_len==(int)sizeof(SerialNumber));
00142 return *pkey;
00143 }
00144
00145 static TlsInfo *
00146 get_info(TlsIndex index)
00147 {
00148 return (TlsInfo*)table_get_info(gdata->tls_table, index);
00149 }
00150
00151 static void
00152 delete_globalref(JNIEnv *env, TlsInfo *info)
00153 {
00154 jthread ref;
00155
00156 HPROF_ASSERT(env!=NULL);
00157 HPROF_ASSERT(info!=NULL);
00158 ref = info->globalref;
00159 info->globalref = NULL;
00160 if ( ref != NULL ) {
00161 deleteWeakGlobalReference(env, ref);
00162 }
00163 }
00164
00165 static void
00166 clean_info(TlsInfo *info)
00167 {
00168
00169 if ( info->stack != NULL ) {
00170 stack_term(info->stack);
00171 info->stack = NULL;
00172 }
00173 if ( info->frames_buffer != NULL ) {
00174 HPROF_FREE(info->frames_buffer);
00175 info->frames_buffer = NULL;
00176 }
00177 if ( info->jframes_buffer != NULL ) {
00178 HPROF_FREE(info->jframes_buffer);
00179 info->jframes_buffer = NULL;
00180 }
00181 }
00182
00183 static void
00184 cleanup_item(TableIndex index, void *key_ptr, int key_len,
00185 void *info_ptr, void *arg)
00186 {
00187 TlsInfo * info;
00188
00189 info = (TlsInfo*)info_ptr;
00190 clean_info(info);
00191 }
00192
00193 static void
00194 delete_ref_item(TableIndex index, void *key_ptr, int key_len,
00195 void *info_ptr, void *arg)
00196 {
00197 delete_globalref((JNIEnv*)arg, (TlsInfo*)info_ptr);
00198 }
00199
00200 static void
00201 list_item(TableIndex index, void *key_ptr, int key_len,
00202 void *info_ptr, void *arg)
00203 {
00204 TlsInfo *info;
00205
00206 HPROF_ASSERT(info_ptr!=NULL);
00207
00208 info = (TlsInfo*)info_ptr;
00209 debug_message( "Tls 0x%08x: SN=%u, sample_status=%d, agent=%d, "
00210 "thread=%p, monitor=0x%08x, "
00211 "tracker_status=%d\n",
00212 index,
00213 *(SerialNumber*)key_ptr,
00214 info->sample_status,
00215 info->agent_thread,
00216 (void*)info->globalref,
00217 info->monitor_index,
00218 info->tracker_status);
00219 }
00220
00221 static void
00222 search_item(TableIndex index, void *key_ptr, int key_len,
00223 void *info_ptr, void *arg)
00224 {
00225 TlsInfo *info;
00226 SearchData *data;
00227 jobject lref;
00228
00229 HPROF_ASSERT(info_ptr!=NULL);
00230 HPROF_ASSERT(arg!=NULL);
00231 info = (TlsInfo*)info_ptr;
00232 data = (SearchData*)arg;
00233 lref = newLocalReference(data->env, info->globalref);
00234 if ( lref != NULL ) {
00235 if ( isSameObject(data->env, data->thread, lref) ) {
00236 HPROF_ASSERT(data->found==0);
00237 data->found = index;
00238 }
00239 deleteLocalReference(data->env, lref);
00240 }
00241 }
00242
00243 static TlsIndex
00244 search(JNIEnv *env, jthread thread)
00245 {
00246 SearchData data;
00247
00248 HPROF_ASSERT(env!=NULL);
00249 HPROF_ASSERT(thread!=NULL);
00250
00251 data.env = env;
00252 data.thread = thread;
00253 data.found = 0;
00254 table_walk_items(gdata->tls_table, &search_item, (void*)&data);
00255 return data.found;
00256 }
00257
00258 static void
00259 garbage_collect_item(TableIndex index, void *key_ptr, int key_len,
00260 void *info_ptr, void *arg)
00261 {
00262 TlsInfo *info;
00263 JNIEnv *env;
00264 jobject lref;
00265
00266 HPROF_ASSERT(info_ptr!=NULL);
00267 HPROF_ASSERT(arg!=NULL);
00268 info = (TlsInfo*)info_ptr;
00269 env = (JNIEnv*)arg;
00270 lref = newLocalReference(env, info->globalref);
00271 if ( lref == NULL ) {
00272 delete_globalref(env, info);
00273 clean_info(info);
00274 table_free_entry(gdata->tls_table, index);
00275 } else {
00276 deleteLocalReference(env, lref);
00277 }
00278 }
00279
00280 void
00281 tls_garbage_collect(JNIEnv *env)
00282 {
00283 HPROF_ASSERT(env!=NULL);
00284 rawMonitorEnter(gdata->data_access_lock); {
00285 table_walk_items(gdata->tls_table, &garbage_collect_item, (void*)env);
00286 } rawMonitorExit(gdata->data_access_lock);
00287 }
00288
00289 static void
00290 sum_sample_status_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
00291 {
00292 TlsInfo *info;
00293
00294 HPROF_ASSERT(info_ptr!=NULL);
00295 info = (TlsInfo*)info_ptr;
00296 if ( !info->agent_thread ) {
00297 (*(jint*)arg) += info->sample_status;
00298 }
00299 }
00300
00301 static void
00302 setup_trace_buffers(TlsInfo *info, int max_depth)
00303 {
00304 int nbytes;
00305 int max_frames;
00306
00307 if ( info->frames_buffer != NULL && info->buffer_depth >= max_depth ) {
00308 return;
00309 }
00310 if ( info->frames_buffer != NULL ) {
00311 HPROF_FREE(info->frames_buffer);
00312 }
00313 if ( info->jframes_buffer != NULL ) {
00314 HPROF_FREE(info->jframes_buffer);
00315 }
00316 info->buffer_depth = max_depth;
00317 max_frames = max_depth + 4;
00318 nbytes = (int)sizeof(FrameIndex)*(max_frames+1);
00319 info->frames_buffer = HPROF_MALLOC(nbytes);
00320 nbytes = (int)sizeof(jvmtiFrameInfo)*(max_frames+1);
00321 info->jframes_buffer = HPROF_MALLOC(nbytes);
00322 }
00323
00324 static TraceIndex
00325 get_trace(jthread thread, SerialNumber thread_serial_num,
00326 int depth, jboolean skip_init,
00327 FrameIndex *frames_buffer, jvmtiFrameInfo *jframes_buffer)
00328 {
00329 TraceIndex trace_index;
00330
00331 trace_index = gdata->system_trace_index;
00332 if ( thread != NULL ) {
00333 trace_index = trace_get_current(thread,
00334 thread_serial_num, depth, skip_init,
00335 frames_buffer, jframes_buffer);
00336 }
00337 return trace_index;
00338 }
00339
00340
00341 static void
00342 sample_setter(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
00343 {
00344 TlsInfo *info;
00345
00346 HPROF_ASSERT(info_ptr!=NULL);
00347
00348 info = (TlsInfo*)info_ptr;
00349 if ( info->globalref != NULL && !info->agent_thread ) {
00350 SampleData *data;
00351
00352 data = (SampleData*)arg;
00353 if ( data->thread_object_index == info->thread_object_index ) {
00354 info->sample_status = data->sample_status;
00355 }
00356 }
00357 }
00358
00359
00360 static void
00361 get_thread_list(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
00362 {
00363 SerialNumber thread_serial_num;
00364 TlsInfo *info;
00365 ThreadList *list;
00366 jthread thread;
00367
00368 HPROF_ASSERT(key_ptr!=NULL);
00369 HPROF_ASSERT(info_ptr!=NULL);
00370
00371 thread_serial_num = *(SerialNumber*)key_ptr;
00372 info = (TlsInfo*)info_ptr;
00373 list = (ThreadList*)arg;
00374 thread = newLocalReference(list->env, info->globalref);
00375 if ( thread != NULL && info->sample_status != 0 && !info->agent_thread ) {
00376 if ( list->infos != NULL ) {
00377 list->infos[list->count] = info;
00378 }
00379 if ( list->serial_nums != NULL ) {
00380 list->serial_nums[list->count] = thread_serial_num;
00381 }
00382 list->threads[list->count] = thread;
00383 list->count++;
00384
00385 } else {
00386
00387 if ( thread != NULL ) {
00388 deleteLocalReference(list->env, thread);
00389 }
00390 }
00391 }
00392
00393 static void
00394 adjust_stats(jlong total_time, jlong self_time, TraceIndex trace_index,
00395 StackElement *parent)
00396 {
00397 if ( total_time > 0 && parent != NULL ) {
00398 parent->time_in_callees += total_time;
00399 }
00400 trace_increment_cost(trace_index, 1, self_time, total_time);
00401 }
00402
00403 static void
00404 push_method(Stack *stack, jlong method_start_time, jmethodID method)
00405 {
00406 StackElement new_element;
00407 FrameIndex frame_index;
00408
00409 HPROF_ASSERT(method!=NULL);
00410 HPROF_ASSERT(stack!=NULL);
00411
00412 frame_index = frame_find_or_create(method, -1);
00413 HPROF_ASSERT(frame_index != 0);
00414 new_element.frame_index = frame_index;
00415 new_element.method = method;
00416 new_element.method_start_time= method_start_time;
00417 new_element.time_in_callees = (jlong)0;
00418 stack_push(stack, &new_element);
00419 }
00420
00421 static Stack *
00422 insure_method_on_stack(jthread thread, TlsInfo *info, jlong current_time,
00423 FrameIndex frame_index, jmethodID method)
00424 {
00425 StackElement element;
00426 void *p;
00427 int depth;
00428 int count;
00429 int fcount;
00430 int i;
00431 Stack *new_stack;
00432 Stack *stack;
00433
00434 stack = info->stack;
00435
00436 HPROF_ASSERT(method!=NULL);
00437
00438
00439 depth = stack_depth(stack);
00440 p = stack_top(stack);
00441 if ( p != NULL ) {
00442 element = *(StackElement*)p;
00443 if ( element.frame_index == frame_index ) {
00444 return stack;
00445 }
00446 }
00447 for ( i = 0 ; i < depth ; i++ ) {
00448 p = stack_element(stack, i);
00449 element = *(StackElement*)p;
00450 if ( element.frame_index == frame_index ) {
00451 return stack;
00452 }
00453 }
00454
00455
00456 getFrameCount(thread, &count);
00457 if ( count <= 0 ) {
00458 HPROF_ERROR(JNI_FALSE, "no frames, method can't be on stack");
00459 }
00460 setup_trace_buffers(info, count);
00461 getStackTrace(thread, info->jframes_buffer, count, &fcount);
00462 HPROF_ASSERT(count==fcount);
00463
00464
00465 new_stack = stack_init(INITIAL_THREAD_STACK_LIMIT,
00466 INITIAL_THREAD_STACK_LIMIT,
00467 (int)sizeof(StackElement));
00468 for ( i = count-1; i >= 0 ; i-- ) {
00469 push_method(new_stack, current_time, info->jframes_buffer[i].method);
00470 }
00471 if ( depth > 0 ) {
00472 for ( i = depth-1 ; i >= 0; i-- ) {
00473 stack_push(new_stack, stack_element(stack, i));
00474 }
00475 }
00476 stack_term(stack);
00477 return new_stack;
00478 }
00479
00480 static void
00481 pop_method(TlsIndex index, jlong current_time, jmethodID method, FrameIndex frame_index)
00482 {
00483 SerialNumber thread_serial_num;
00484 TlsInfo * info;
00485 StackElement element;
00486 void *p;
00487 int depth;
00488 int trace_depth;
00489 jlong total_time;
00490 jlong self_time;
00491 int i;
00492 TraceIndex trace_index;
00493
00494 HPROF_ASSERT(method!=NULL);
00495 HPROF_ASSERT(frame_index!=0);
00496
00497 thread_serial_num = get_key(index);
00498 info = get_info(index);
00499 HPROF_ASSERT(info!=NULL);
00500 HPROF_ASSERT(info->stack!=NULL);
00501 depth = stack_depth(info->stack);
00502 p = stack_pop(info->stack);
00503 if (p == NULL) {
00504 HPROF_ERROR(JNI_FALSE, "method return tracked, but stack is empty");
00505 return;
00506 }
00507 element = *(StackElement*)p;
00508 HPROF_ASSERT(element.frame_index!=0);
00509
00510
00511 if (gdata->prof_trace_depth > depth) {
00512 trace_depth = depth;
00513 } else {
00514 trace_depth = gdata->prof_trace_depth;
00515 }
00516
00517
00518 HPROF_ASSERT(info->frames_buffer!=NULL);
00519 HPROF_ASSERT(info->jframes_buffer!=NULL);
00520 setup_trace_buffers(info, trace_depth);
00521 info->frames_buffer[0] = element.frame_index;
00522 for (i = 1; i < trace_depth; i++) {
00523 StackElement e;
00524
00525 e = *(StackElement*)stack_element(info->stack, (depth - i) - 1);
00526 info->frames_buffer[i] = e.frame_index;
00527 HPROF_ASSERT(e.frame_index!=0);
00528 }
00529 trace_index = trace_find_or_create(thread_serial_num,
00530 trace_depth, info->frames_buffer, info->jframes_buffer);
00531
00532
00533 total_time = current_time - element.method_start_time;
00534 if ( total_time < 0 ) {
00535 total_time = 0;
00536 self_time = 0;
00537 } else {
00538 self_time = total_time - element.time_in_callees;
00539 }
00540
00541
00542 p = stack_top(info->stack);
00543 if ( p != NULL ) {
00544 adjust_stats(total_time, self_time, trace_index, (StackElement*)p);
00545 } else {
00546 adjust_stats(total_time, self_time, trace_index, NULL);
00547 }
00548 }
00549
00550 static void
00551 dump_thread_state(TlsIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
00552 {
00553 SerialNumber thread_serial_num;
00554 TlsInfo *info;
00555 jthread thread;
00556 JNIEnv *env;
00557
00558 HPROF_ASSERT(key_ptr!=NULL);
00559 HPROF_ASSERT(info_ptr!=NULL);
00560 env = (JNIEnv*)arg;
00561 thread_serial_num = *(SerialNumber*)key_ptr;
00562 info = (TlsInfo*)info_ptr;
00563 thread = newLocalReference(env, info->globalref);
00564 if ( thread != NULL ) {
00565 jint threadState;
00566 SerialNumber trace_serial_num;
00567
00568 getThreadState(thread, &threadState);
00569
00570
00571
00572
00573 if ( info->last_trace == 0 ) {
00574 trace_serial_num = trace_get_serial_number(gdata->system_trace_index);
00575 } else {
00576 trace_serial_num = trace_get_serial_number(info->last_trace);
00577 }
00578 io_write_monitor_dump_thread_state(thread_serial_num,
00579 trace_serial_num, threadState);
00580 deleteLocalReference(env, thread);
00581 }
00582 }
00583
00584 static SerialNumber
00585 get_serial_number(JNIEnv *env, jthread thread)
00586 {
00587 TlsIndex index;
00588
00589 if ( thread == NULL ) {
00590 return gdata->unknown_thread_serial_num;
00591 }
00592 HPROF_ASSERT(env!=NULL);
00593 index = tls_find_or_create(env, thread);
00594 return get_key(index);
00595 }
00596
00597 static void
00598 dump_monitor_state(TlsIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
00599 {
00600 TlsInfo *info;
00601 jthread thread;
00602 JNIEnv *env;
00603
00604 HPROF_ASSERT(info_ptr!=NULL);
00605 env = (JNIEnv*)arg;
00606 info = (TlsInfo*)info_ptr;
00607 thread = newLocalReference(env, info->globalref);
00608 if ( thread != NULL ) {
00609 jobject *objects;
00610 jint ocount;
00611 int i;
00612
00613 getOwnedMonitorInfo(thread, &objects, &ocount);
00614 if ( ocount > 0 ) {
00615 for ( i = 0 ; i < ocount ; i++ ) {
00616 jvmtiMonitorUsage usage;
00617 SerialNumber *waiter_nums;
00618 SerialNumber *notify_waiter_nums;
00619 int t;
00620 char * sig;
00621
00622 WITH_LOCAL_REFS(env, 1) {
00623 jclass clazz;
00624
00625 clazz = getObjectClass(env, objects[i]);
00626 getClassSignature(clazz, &sig, NULL);
00627 } END_WITH_LOCAL_REFS;
00628
00629 getObjectMonitorUsage(objects[i], &usage);
00630 waiter_nums = HPROF_MALLOC(usage.waiter_count*
00631 (int)sizeof(SerialNumber)+1);
00632 for ( t = 0 ; t < usage.waiter_count ; t++ ) {
00633 waiter_nums[t] =
00634 get_serial_number(env, usage.waiters[t]);
00635 }
00636 notify_waiter_nums = HPROF_MALLOC(usage.notify_waiter_count*
00637 (int)sizeof(SerialNumber)+1);
00638 for ( t = 0 ; t < usage.notify_waiter_count ; t++ ) {
00639 notify_waiter_nums[t] =
00640 get_serial_number(env, usage.notify_waiters[t]);
00641 }
00642 io_write_monitor_dump_state(sig,
00643 get_serial_number(env, usage.owner),
00644 usage.entry_count,
00645 waiter_nums, usage.waiter_count,
00646 notify_waiter_nums, usage.notify_waiter_count);
00647 jvmtiDeallocate(sig);
00648 jvmtiDeallocate(usage.waiters);
00649 jvmtiDeallocate(usage.notify_waiters);
00650 HPROF_FREE(waiter_nums);
00651 HPROF_FREE(notify_waiter_nums);
00652 }
00653 }
00654 jvmtiDeallocate(objects);
00655 deleteLocalReference(env, thread);
00656 }
00657 }
00658
00659 static jlong
00660 monitor_time(void)
00661 {
00662 jlong mtime;
00663
00664 mtime = md_get_timemillis();
00665 return mtime;
00666 }
00667
00668 static jlong
00669 method_time(void)
00670 {
00671 jlong method_time;
00672
00673 method_time = md_get_thread_cpu_timemillis();
00674 return method_time;
00675 }
00676
00677
00678
00679 TlsIndex
00680 tls_find_or_create(JNIEnv *env, jthread thread)
00681 {
00682 SerialNumber thread_serial_num;
00683 static TlsInfo empty_info;
00684 TlsInfo info;
00685 TlsIndex index;
00686
00687 HPROF_ASSERT(env!=NULL);
00688 HPROF_ASSERT(thread!=NULL);
00689
00690
00691 index = (TlsIndex)(ptrdiff_t)getThreadLocalStorage(thread);
00692 if ( index != 0 ) {
00693 HPROF_ASSERT(isSameObject(env, thread, get_info(index)->globalref));
00694 return index;
00695 }
00696 index = search(env, thread);
00697 if ( index != 0 ) {
00698 setThreadLocalStorage(thread, (void*)(ptrdiff_t)index);
00699 return index;
00700 }
00701 thread_serial_num = gdata->thread_serial_number_counter++;
00702 info = empty_info;
00703 info.monitor_index = 0;
00704 info.sample_status = 1;
00705 info.agent_thread = JNI_FALSE;
00706 info.stack = stack_init(INITIAL_THREAD_STACK_LIMIT,
00707 INITIAL_THREAD_STACK_LIMIT,
00708 (int)sizeof(StackElement));
00709 setup_trace_buffers(&info, gdata->max_trace_depth);
00710 info.globalref = newWeakGlobalReference(env, thread);
00711 index = table_create_entry(gdata->tls_table, &thread_serial_num, (int)sizeof(SerialNumber), (void*)&info);
00712 setThreadLocalStorage(thread, (void*)(ptrdiff_t)index);
00713 HPROF_ASSERT(search(env,thread)==index);
00714 return index;
00715 }
00716
00717
00718 void
00719 tls_agent_thread(JNIEnv *env, jthread thread)
00720 {
00721 TlsIndex index;
00722 TlsInfo *info;
00723
00724 index = tls_find_or_create(env, thread);
00725 info = get_info(index);
00726 info->agent_thread = JNI_TRUE;
00727 }
00728
00729 void
00730 tls_init(void)
00731 {
00732 gdata->tls_table = table_initialize("TLS",
00733 16, 16, 16, (int)sizeof(TlsInfo));
00734 }
00735
00736 void
00737 tls_list(void)
00738 {
00739 debug_message(
00740 "--------------------- TLS Table ------------------------\n");
00741 table_walk_items(gdata->tls_table, &list_item, NULL);
00742 debug_message(
00743 "----------------------------------------------------------\n");
00744 }
00745
00746 jint
00747 tls_sum_sample_status(void)
00748 {
00749 jint sample_status_total;
00750
00751 sample_status_total = 0;
00752 table_walk_items(gdata->tls_table, &sum_sample_status_item, (void*)&sample_status_total);
00753 return sample_status_total;
00754 }
00755
00756 void
00757 tls_set_sample_status(ObjectIndex object_index, jint sample_status)
00758 {
00759 SampleData data;
00760
00761 data.thread_object_index = object_index;
00762 data.sample_status = sample_status;
00763 table_walk_items(gdata->tls_table, &sample_setter, (void*)&data);
00764 }
00765
00766 jint
00767 tls_get_tracker_status(JNIEnv *env, jthread thread, jboolean skip_init,
00768 jint **ppstatus, TlsIndex* pindex,
00769 SerialNumber *pthread_serial_num, TraceIndex *ptrace_index)
00770 {
00771 TlsInfo *info;
00772 TlsIndex index;
00773 SerialNumber thread_serial_num;
00774 jint status;
00775
00776 index = tls_find_or_create(env, thread);
00777 info = get_info(index);
00778 *ppstatus = &(info->tracker_status);
00779 status = **ppstatus;
00780 thread_serial_num = get_key(index);
00781
00782 if ( pindex != NULL ) {
00783 *pindex = index;
00784 }
00785 if ( status != 0 ) {
00786 return status;
00787 }
00788 if ( ptrace_index != NULL ) {
00789 setup_trace_buffers(info, gdata->max_trace_depth);
00790 *ptrace_index = get_trace(thread, thread_serial_num,
00791 gdata->max_trace_depth, skip_init,
00792 info->frames_buffer, info->jframes_buffer);
00793 }
00794 if ( pthread_serial_num != NULL ) {
00795 *pthread_serial_num = thread_serial_num;
00796 }
00797 return status;
00798 }
00799
00800 MonitorIndex
00801 tls_get_monitor(TlsIndex index)
00802 {
00803 TlsInfo *info;
00804
00805 info = get_info(index);
00806 return info->monitor_index;
00807 }
00808
00809 void
00810 tls_set_thread_object_index(TlsIndex index, ObjectIndex thread_object_index)
00811 {
00812 TlsInfo *info;
00813
00814 info = get_info(index);
00815 info->thread_object_index = thread_object_index;
00816 }
00817
00818 SerialNumber
00819 tls_get_thread_serial_number(TlsIndex index)
00820 {
00821 return get_key(index);
00822 }
00823
00824 void
00825 tls_set_monitor(TlsIndex index, MonitorIndex monitor_index)
00826 {
00827 TlsInfo *info;
00828
00829 info = get_info(index);
00830 info->monitor_index = monitor_index;
00831 }
00832
00833 void
00834 tls_cleanup(void)
00835 {
00836 table_cleanup(gdata->tls_table, &cleanup_item, NULL);
00837 gdata->tls_table = NULL;
00838 }
00839
00840 void
00841 tls_delete_global_references(JNIEnv *env)
00842 {
00843 table_walk_items(gdata->tls_table, &delete_ref_item, (void*)env);
00844 }
00845
00846 void
00847 tls_thread_ended(JNIEnv *env, TlsIndex index)
00848 {
00849 HPROF_ASSERT(env!=NULL);
00850
00851
00852 table_lock_enter(gdata->tls_table); {
00853 SerialNumber thread_serial_num;
00854 TlsInfo *info;
00855 jthread thread;
00856
00857 thread_serial_num = get_key(index);
00858 info = get_info(index);
00859 thread = newLocalReference(env, info->globalref);
00860 if (gdata->heap_dump && thread!=NULL) {
00861 setup_trace_buffers(info, gdata->max_trace_depth);
00862 info->last_trace = get_trace(thread, thread_serial_num,
00863 gdata->max_trace_depth, JNI_FALSE,
00864 info->frames_buffer, info->jframes_buffer);
00865 }
00866 if ( thread != NULL ) {
00867 deleteLocalReference(env, thread);
00868 }
00869 } table_lock_exit(gdata->tls_table);
00870
00871 }
00872
00873
00874 void
00875 tls_sample_all_threads(JNIEnv *env)
00876 {
00877 ThreadList list;
00878 jthread *threads;
00879 SerialNumber *serial_nums;
00880
00881 table_lock_enter(gdata->tls_table); {
00882 int max_count;
00883 int nbytes;
00884 int i;
00885
00886
00887 max_count = table_element_count(gdata->tls_table);
00888 nbytes = (int)sizeof(jthread)*max_count;
00889 threads = (jthread*)HPROF_MALLOC(nbytes);
00890 nbytes = (int)sizeof(SerialNumber)*max_count;
00891 serial_nums = (SerialNumber*)HPROF_MALLOC(nbytes);
00892
00893
00894 list.threads = threads;
00895 list.infos = NULL;
00896 list.serial_nums = serial_nums;
00897 list.count = 0;
00898 list.env = env;
00899 table_walk_items(gdata->tls_table, &get_thread_list, (void*)&list);
00900
00901
00902 trace_increment_all_sample_costs(list.count, threads, serial_nums,
00903 gdata->max_trace_depth, JNI_FALSE);
00904
00905
00906 for ( i = 0 ; i < list.count ; i++ ) {
00907 if ( threads[i] != NULL ) {
00908 deleteLocalReference(env, threads[i]);
00909 }
00910 }
00911
00912 } table_lock_exit(gdata->tls_table);
00913
00914
00915 HPROF_FREE(threads);
00916 HPROF_FREE(serial_nums);
00917
00918 }
00919
00920 void
00921 tls_push_method(TlsIndex index, jmethodID method)
00922 {
00923 jlong method_start_time;
00924 TlsInfo *info;
00925
00926 HPROF_ASSERT(method!=NULL);
00927 info = get_info(index);
00928 HPROF_ASSERT(info!=NULL);
00929 method_start_time = method_time();
00930 HPROF_ASSERT(info->stack!=NULL);
00931 push_method(info->stack, method_start_time, method);
00932 }
00933
00934 void
00935 tls_pop_exception_catch(TlsIndex index, jthread thread, jmethodID method)
00936 {
00937 TlsInfo *info;
00938 StackElement element;
00939 void *p;
00940 FrameIndex frame_index;
00941 jlong current_time;
00942
00943 HPROF_ASSERT(method!=NULL);
00944 frame_index = frame_find_or_create(method, -1);
00945 HPROF_ASSERT(frame_index != 0);
00946
00947 info = get_info(index);
00948
00949 HPROF_ASSERT(info!=NULL);
00950 HPROF_ASSERT(info->stack!=NULL);
00951 HPROF_ASSERT(frame_index!=0);
00952 current_time = method_time();
00953 info->stack = insure_method_on_stack(thread, info, current_time,
00954 frame_index, method);
00955 p = stack_top(info->stack);
00956 if (p == NULL) {
00957 HPROF_ERROR(JNI_FALSE, "expection pop, nothing on stack");
00958 return;
00959 }
00960 element = *(StackElement*)p;
00961 HPROF_ASSERT(element.frame_index!=0);
00962 while ( element.frame_index != frame_index ) {
00963 pop_method(index, current_time, element.method, frame_index);
00964 p = stack_top(info->stack);
00965 if ( p == NULL ) {
00966 break;
00967 }
00968 element = *(StackElement*)p;
00969 }
00970 if (p == NULL) {
00971 HPROF_ERROR(JNI_FALSE, "exception pop stack empty");
00972 }
00973 }
00974
00975 void
00976 tls_pop_method(TlsIndex index, jthread thread, jmethodID method)
00977 {
00978 TlsInfo *info;
00979 StackElement element;
00980 void *p;
00981 FrameIndex frame_index;
00982 jlong current_time;
00983
00984 HPROF_ASSERT(method!=NULL);
00985 frame_index = frame_find_or_create(method, -1);
00986 HPROF_ASSERT(frame_index != 0);
00987
00988 info = get_info(index);
00989 HPROF_ASSERT(info!=NULL);
00990 HPROF_ASSERT(info->stack!=NULL);
00991 current_time = method_time();
00992 HPROF_ASSERT(frame_index!=0);
00993 info->stack = insure_method_on_stack(thread, info, current_time,
00994 frame_index, method);
00995 p = stack_top(info->stack);
00996 HPROF_ASSERT(p!=NULL);
00997 element = *(StackElement*)p;
00998 while ( element.frame_index != frame_index ) {
00999 pop_method(index, current_time, element.method, frame_index);
01000 p = stack_top(info->stack);
01001 if ( p == NULL ) {
01002 break;
01003 }
01004 element = *(StackElement*)p;
01005 }
01006 pop_method(index, current_time, method, frame_index);
01007 }
01008
01009
01010 static void
01011 update_all_last_traces(JNIEnv *env)
01012 {
01013 jthread *threads;
01014 TlsInfo **infos;
01015 SerialNumber *serial_nums;
01016 TraceIndex *traces;
01017
01018 if ( gdata->max_trace_depth == 0 ) {
01019 return;
01020 }
01021
01022 table_lock_enter(gdata->tls_table); {
01023
01024 ThreadList list;
01025 int max_count;
01026 int nbytes;
01027 int i;
01028
01029
01030 max_count = table_element_count(gdata->tls_table);
01031 nbytes = (int)sizeof(jthread)*max_count;
01032 threads = (jthread*)HPROF_MALLOC(nbytes);
01033 nbytes = (int)sizeof(SerialNumber)*max_count;
01034 serial_nums = (SerialNumber*)HPROF_MALLOC(nbytes);
01035 nbytes = (int)sizeof(TlsInfo*)*max_count;
01036 infos = (TlsInfo**)HPROF_MALLOC(nbytes);
01037
01038
01039 list.threads = threads;
01040 list.serial_nums = serial_nums;
01041 list.infos = infos;
01042 list.count = 0;
01043 list.env = env;
01044 table_walk_items(gdata->tls_table, &get_thread_list, (void*)&list);
01045
01046
01047 nbytes = (int)sizeof(TraceIndex)*max_count;
01048 traces = (TraceIndex*)HPROF_MALLOC(nbytes);
01049 trace_get_all_current(list.count, threads, serial_nums,
01050 gdata->max_trace_depth, JNI_FALSE,
01051 traces, JNI_TRUE);
01052
01053
01054 for ( i = 0 ; i < list.count ; i++ ) {
01055 if ( threads[i] != NULL ) {
01056 deleteLocalReference(env, threads[i]);
01057 }
01058 infos[i]->last_trace = traces[i];
01059 }
01060
01061 } table_lock_exit(gdata->tls_table);
01062
01063
01064 HPROF_FREE(threads);
01065 HPROF_FREE(serial_nums);
01066 HPROF_FREE(infos);
01067 HPROF_FREE(traces);
01068
01069 }
01070
01071 void
01072 tls_dump_traces(JNIEnv *env)
01073 {
01074 rawMonitorEnter(gdata->data_access_lock); {
01075 update_all_last_traces(env);
01076 trace_output_unmarked(env);
01077 } rawMonitorExit(gdata->data_access_lock);
01078 }
01079
01080 void
01081 tls_dump_monitor_state(JNIEnv *env)
01082 {
01083 HPROF_ASSERT(env!=NULL);
01084
01085 rawMonitorEnter(gdata->data_access_lock); {
01086 tls_dump_traces(env);
01087 io_write_monitor_dump_header();
01088 table_walk_items(gdata->tls_table, &dump_thread_state, (void*)env);
01089 table_walk_items(gdata->tls_table, &dump_monitor_state, (void*)env);
01090 io_write_monitor_dump_footer();
01091 } rawMonitorExit(gdata->data_access_lock);
01092 }
01093
01094 void
01095 tls_monitor_start_timer(TlsIndex index)
01096 {
01097 TlsInfo *info;
01098
01099 info = get_info(index);
01100 HPROF_ASSERT(info!=NULL);
01101 HPROF_ASSERT(info->globalref!=NULL);
01102 info->monitor_start_time = monitor_time();
01103 }
01104
01105 jlong
01106 tls_monitor_stop_timer(TlsIndex index)
01107 {
01108 TlsInfo *info;
01109 jlong t;
01110
01111 info = get_info(index);
01112 HPROF_ASSERT(info!=NULL);
01113 t = monitor_time() - info->monitor_start_time;
01114 info->monitor_start_time = 0;
01115 return t;
01116 }
01117
01118 TraceIndex
01119 tls_get_trace(TlsIndex index, JNIEnv *env, int depth, jboolean skip_init)
01120 {
01121 SerialNumber thread_serial_num;
01122 TraceIndex trace_index;
01123 TlsInfo *info;
01124 jthread thread;
01125
01126 thread_serial_num = get_key(index);
01127 info = get_info(index);
01128 HPROF_ASSERT(info!=NULL);
01129 setup_trace_buffers(info, depth);
01130 thread = newLocalReference(env, info->globalref);
01131 if ( thread != NULL ) {
01132 trace_index = get_trace(thread, thread_serial_num, depth, skip_init,
01133 info->frames_buffer, info->jframes_buffer);
01134 deleteLocalReference(env, thread);
01135 } else {
01136 trace_index = gdata->system_trace_index;
01137 }
01138 return trace_index;
01139 }
01140
01141 void
01142 tls_set_in_heap_dump(TlsIndex index, jint in_heap_dump)
01143 {
01144 TlsInfo *info;
01145
01146 info = get_info(index);
01147 info->in_heap_dump = in_heap_dump;
01148 }
01149
01150 jint
01151 tls_get_in_heap_dump(TlsIndex index)
01152 {
01153 TlsInfo *info;
01154
01155 info = get_info(index);
01156 return info->in_heap_dump;
01157 }
01158
01159 static void
01160 clean_in_heap_dump(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
01161 {
01162 TlsInfo *info;
01163
01164 HPROF_ASSERT(info_ptr!=NULL);
01165 info = (TlsInfo*)info_ptr;
01166 info->in_heap_dump = 0;
01167 }
01168
01169 void
01170 tls_clear_in_heap_dump(void)
01171 {
01172 table_walk_items(gdata->tls_table, &clean_in_heap_dump, NULL);
01173 }
01174
01175 TlsIndex
01176 tls_find(SerialNumber thread_serial_num)
01177 {
01178 TlsIndex index;
01179
01180 if ( thread_serial_num == 0 ) {
01181 return 0;
01182 }
01183 index = table_find_entry(gdata->tls_table,
01184 (void*)&thread_serial_num, (int)sizeof(SerialNumber));
01185 return index;
01186 }