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 + -
显示快捷键?