hprof_thread.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 581 行 · 第 1/2 页
C
581 行
/* * @(#)hprof_thread.c 1.28 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "hprof.h"static hprof_thread_local_t *hprof_alloc_thread_local_info(void);static void hprof_free_thread_local_info(JNIEnv *env_id);static unsigned int thread_serial_number = 1;static hprof_hash_t hprof_thread_table;/* list of active threads */live_thread_t *live_thread_list = NULL;int num_live_threads = 0;static unsigned int hash_thread(void *_thread){ hprof_thread_t *thread = _thread; return (unsigned int)thread->env_id % hprof_thread_table.size;}static unsigned int size_thread(void *_thread){ return sizeof(hprof_thread_t);}static int compare_thread(void *_thread1, void *_thread2){ hprof_thread_t *thread1 = _thread1; hprof_thread_t *thread2 = _thread2; return ((long)thread1->env_id - (long)thread2->env_id);}void hprof_thread_table_init(void){ /* * With 4005 threads, a size of 1003 yields a 99% occupancy rate * with an average element count value of 4.05. Changing the size * to 1024 and doing the usual bit shifting with HASH_OBJ_SHIFT * results in less than 50% occupancy with an average element count * value almost 8. * * On Win32 the JNIEnv pointer values always have the 0xC bits set * and on Solaris the 0x4 bit is always set. Changing the shift * value to drop the "constant" bits yields better occupancy and * average element count values, but still not as good as the * original table size. */ hprof_hash_init(ALLOC_HASH_THREAD, &hprof_thread_table, 1003, hash_thread, size_thread, compare_thread);}hprof_thread_t * hprof_intern_thread(JNIEnv *env_id){ hprof_thread_t thread_tmp; hprof_thread_t *result; thread_tmp.env_id = env_id; result = hprof_hash_lookup(&hprof_thread_table, &thread_tmp); if (result == NULL) { thread_tmp.serial_num = thread_serial_number++; /* set thread id to NULL, it'll be set to the right value in thread_start_event */ thread_tmp.thread_id = NULL; result = hprof_hash_put(&hprof_thread_table, &thread_tmp); /* We need thread local storage for timing methods or tracking * contended monitor entry. We have to do it here, because we could * get method entry/exit and monitor enter/entered events with * JNIEnv *s that haven't been notified in thread start. */ if (cpu_timing || monitor_tracing) { hprof_thread_local_t *info = hprof_alloc_thread_local_info(); CALL(SetThreadLocalStorage)(env_id, info); } } return result;}static int hprof_remove_thread_helper(void *_thread, void *_env){ hprof_thread_t *thread = _thread; JNIEnv *env_id = _env; return (thread->env_id == env_id);}void hprof_remove_thread(JNIEnv *env_id){ hprof_hash_remove(&hprof_thread_table, hprof_remove_thread_helper, (void *)env_id);}hprof_thread_t *hprof_lookup_thread(JNIEnv *env_id){ hprof_thread_t thread_tmp; hprof_thread_t *result; thread_tmp.env_id = env_id; result = hprof_hash_lookup(&hprof_thread_table, &thread_tmp); return result;} 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); }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);}hprof_thread_t * hprof_fetch_thread_info(JNIEnv *env){ hprof_thread_t *thread = hprof_lookup_thread(env); if (thread == NULL) { jobjectID tobj = CALL(GetThreadObject)(env); if (tobj) { CALL(RequestEvent)(JVMPI_EVENT_THREAD_START, tobj); } thread = hprof_lookup_thread(env); } return thread;}void hprof_print_thread_info(JNIEnv *env, int leading_comma){ hprof_thread_t *thread = hprof_lookup_thread(env);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?