hprof_tls.c
来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 1,187 行 · 第 1/3 页
C
1,187 行
/* * @(#)hprof_tls.c 1.54 05/11/17 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */#include "hprof.h"/* Thread Local Storage Table and method entry/exit handling. *//* * The tls table items have a key of it's serial number, but may be * searched via a walk of the table looking for a jthread match. * This isn't a performance * issue because the table index should normally be stored in the * Thread Local Storage for the thread. The table is only searched * when the jthread is seen before the Thread Local Storage is set * (e.g. before VM_INIT or the ThreadStart). * The key is only used when we need to lookup a tls table entry by * way of it's serial number, which should be unique per thread. * * Each active thread that we have seen should have a unique TlsIndex * which is an index into this table. * * For cpu=times, each table entry will have a stack to hold the method * that have been called, effectively keeping an active stack trace * for the thread. As each method exits, the statistics for the trace * associated with the current stack contents is updated. * * For cpu=samples, each thread is checked to see if it's runnable, * and not suspended, and has a stack associated with it, and then * that stack trace is updated with an additional 'hit'. * * This file also contains the dump logic for owned monitors, and for * threads. * *//* * Initial number of stack elements to track per thread. This * value should be set to a reasonable guess as to the number of * methods deep a thread calls. This stack doubles in size for each * reallocation and does not shrink. */#define INITIAL_THREAD_STACK_LIMIT 64typedef struct StackElement { FrameIndex frame_index; /* Frame (method/location(-1)) */ jmethodID method; /* Method ID */ jlong method_start_time; /* method start time */ jlong time_in_callees; /* time in callees */} StackElement;typedef struct TlsInfo { jint sample_status; /* Thread status for cpu sampling */ jboolean agent_thread; /* Is thread our own agent thread? */ jthread globalref; /* Global reference for thread */ Stack *stack; /* Stack of StackElements entry/exit */ MonitorIndex monitor_index; /* last contended mon */ jint tracker_status; /* If we are inside Tracker class */ FrameIndex *frames_buffer; /* Buffer used to create TraceIndex */ jvmtiFrameInfo *jframes_buffer; /* Buffer used to create TraceIndex */ int buffer_depth; /* Frames allowed in buffer */ TraceIndex last_trace; /* Last trace for this thread */ ObjectIndex thread_object_index;/* If heap=dump */ jlong monitor_start_time; /* Start time for monitor */ jint in_heap_dump; /* If we are an object in the dump */} TlsInfo;typedef struct SearchData { JNIEnv *env; jthread thread; TlsIndex found;} SearchData;typedef struct IterateInfo { TlsIndex * ptls_index; jthread * pthreads; jint count;} IterateInfo;typedef struct ThreadList { jthread *threads; SerialNumber *serial_nums; TlsInfo **infos; jint count; JNIEnv *env;} ThreadList;typedef struct SampleData { ObjectIndex thread_object_index; jint sample_status;} SampleData;/* Private internal functions. */static SerialNumberget_key(TlsIndex index){ SerialNumber *pkey; int key_len; if ( index == 0 ) { return 0; } pkey = NULL; key_len = 0; table_get_key(gdata->tls_table, index, (void**)&pkey, &key_len); HPROF_ASSERT(pkey!=NULL); HPROF_ASSERT(key_len==(int)sizeof(SerialNumber)); return *pkey;}static TlsInfo *get_info(TlsIndex index){ return (TlsInfo*)table_get_info(gdata->tls_table, index);}static voiddelete_globalref(JNIEnv *env, TlsInfo *info){ jthread ref; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(info!=NULL); ref = info->globalref; info->globalref = NULL; if ( ref != NULL ) { deleteWeakGlobalReference(env, ref); }}static voidclean_info(TlsInfo *info){ /* Free up any allocated space in this TlsInfo structure */ if ( info->stack != NULL ) { stack_term(info->stack); info->stack = NULL; } if ( info->frames_buffer != NULL ) { HPROF_FREE(info->frames_buffer); info->frames_buffer = NULL; } if ( info->jframes_buffer != NULL ) { HPROF_FREE(info->jframes_buffer); info->jframes_buffer = NULL; }}static voidcleanup_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ TlsInfo * info; info = (TlsInfo*)info_ptr; clean_info(info);}static voiddelete_ref_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ delete_globalref((JNIEnv*)arg, (TlsInfo*)info_ptr);}static voidlist_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ TlsInfo *info; HPROF_ASSERT(info_ptr!=NULL); info = (TlsInfo*)info_ptr; debug_message( "Tls 0x%08x: SN=%u, sample_status=%d, agent=%d, " "thread=%p, monitor=0x%08x, " "tracker_status=%d\n", index, *(SerialNumber*)key_ptr, info->sample_status, info->agent_thread, (void*)info->globalref, info->monitor_index, info->tracker_status);}static voidsearch_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ TlsInfo *info; SearchData *data; jobject lref; HPROF_ASSERT(info_ptr!=NULL); HPROF_ASSERT(arg!=NULL); info = (TlsInfo*)info_ptr; data = (SearchData*)arg; lref = newLocalReference(data->env, info->globalref); if ( lref != NULL ) { if ( isSameObject(data->env, data->thread, lref) ) { HPROF_ASSERT(data->found==0); /* Did we find more than one? */ data->found = index; } deleteLocalReference(data->env, lref); }}static TlsIndexsearch(JNIEnv *env, jthread thread){ SearchData data; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); data.env = env; data.thread = thread; data.found = 0; table_walk_items(gdata->tls_table, &search_item, (void*)&data); return data.found;}static voidgarbage_collect_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ TlsInfo *info; JNIEnv *env; jobject lref; HPROF_ASSERT(info_ptr!=NULL); HPROF_ASSERT(arg!=NULL); info = (TlsInfo*)info_ptr; env = (JNIEnv*)arg; lref = newLocalReference(env, info->globalref); if ( lref == NULL ) { delete_globalref(env, info); clean_info(info); table_free_entry(gdata->tls_table, index); } else { deleteLocalReference(env, lref); }}voidtls_garbage_collect(JNIEnv *env){ HPROF_ASSERT(env!=NULL); rawMonitorEnter(gdata->data_access_lock); { table_walk_items(gdata->tls_table, &garbage_collect_item, (void*)env); } rawMonitorExit(gdata->data_access_lock);}static voidsum_sample_status_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ TlsInfo *info; HPROF_ASSERT(info_ptr!=NULL); info = (TlsInfo*)info_ptr; if ( !info->agent_thread ) { (*(jint*)arg) += info->sample_status; }}static voidsetup_trace_buffers(TlsInfo *info, int max_depth){ int nbytes; int max_frames; if ( info->frames_buffer != NULL && info->buffer_depth >= max_depth ) { return; } if ( info->frames_buffer != NULL ) { HPROF_FREE(info->frames_buffer); } if ( info->jframes_buffer != NULL ) { HPROF_FREE(info->jframes_buffer); } info->buffer_depth = max_depth; max_frames = max_depth + 4; /* Allow for BCI & <init> */ nbytes = (int)sizeof(FrameIndex)*(max_frames+1); info->frames_buffer = HPROF_MALLOC(nbytes); nbytes = (int)sizeof(jvmtiFrameInfo)*(max_frames+1); info->jframes_buffer = HPROF_MALLOC(nbytes);}static TraceIndexget_trace(jthread thread, SerialNumber thread_serial_num, int depth, jboolean skip_init, FrameIndex *frames_buffer, jvmtiFrameInfo *jframes_buffer){ TraceIndex trace_index; trace_index = gdata->system_trace_index; if ( thread != NULL ) { trace_index = trace_get_current(thread, thread_serial_num, depth, skip_init, frames_buffer, jframes_buffer); } return trace_index;}/* Find thread with certain object index */static voidsample_setter(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ TlsInfo *info; HPROF_ASSERT(info_ptr!=NULL); info = (TlsInfo*)info_ptr; if ( info->globalref != NULL && !info->agent_thread ) { SampleData *data; data = (SampleData*)arg; if ( data->thread_object_index == info->thread_object_index ) { info->sample_status = data->sample_status; } }}/* Get various lists on known threads */static voidget_thread_list(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){ SerialNumber thread_serial_num; TlsInfo *info; ThreadList *list; jthread thread; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(info_ptr!=NULL); thread_serial_num = *(SerialNumber*)key_ptr; info = (TlsInfo*)info_ptr; list = (ThreadList*)arg; thread = newLocalReference(list->env, info->globalref); if ( thread != NULL && info->sample_status != 0 && !info->agent_thread ) { if ( list->infos != NULL ) { list->infos[list->count] = info; } if ( list->serial_nums != NULL ) { list->serial_nums[list->count] = thread_serial_num; } list->threads[list->count] = thread; list->count++; /* Local reference gets freed by caller */ } else { /* If we don't use the local reference, delete it now */ if ( thread != NULL ) { deleteLocalReference(list->env, thread); } }}static voidadjust_stats(jlong total_time, jlong self_time, TraceIndex trace_index, StackElement *parent){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?