hprof_trace.c

来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 867 行 · 第 1/2 页

C
867
字号
/* * @(#)hprof_trace.c	1.40 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. *//* Trace table. *//* * A trace is an optional thread serial number plus N frames. * * The thread serial number is added to the key only if the user asks for *    threads in traces, which will cause many more traces to be created. *    Without it all threads share the traces. * * This is a variable length Key, depending on the number of frames. *   The frames are FrameIndex values into the frame table. * * It is important that the thread serial number is used and not the *    TlsIndex, threads come and go, and TlsIndex values are re-used *    but the thread serial number is unique per thread. * * The cpu=times and cpu=samples dumps rely heavily on traces, the trace *   dump preceeds the cpu information and uses the trace information. *   Depending on the cpu= request, different sorts are applied to the *   traces that are dumped. * */#include "hprof.h"typedef struct TraceKey {    SerialNumber thread_serial_num; /* Thread serial number */    short        n_frames;          /* Number of frames that follow. */    jvmtiPhase   phase : 8;         /* Makes some traces unique */    FrameIndex   frames[1];         /* Variable length */} TraceKey;typedef struct TraceInfo {    SerialNumber serial_num;        /* Trace serial number */    jint         num_hits;          /* Number of hits this trace has */    jlong        total_cost;        /* Total cost associated with trace */    jlong        self_cost;         /* Total cost without children cost */    jint         status;            /* Status of dump of trace */} TraceInfo;typedef struct IterateInfo {    TraceIndex* traces;    int         count;    jlong       grand_total_cost;} IterateInfo;/* Private internal functions. */static TraceKey*get_pkey(TraceIndex index){    void *      pkey;    int         key_len;    table_get_key(gdata->trace_table, index, &pkey, &key_len);    HPROF_ASSERT(pkey!=NULL);    HPROF_ASSERT(key_len>=(int)sizeof(TraceKey));    HPROF_ASSERT(((TraceKey*)pkey)->n_frames<=1?key_len==(int)sizeof(TraceKey) :	     key_len==(int)sizeof(TraceKey)+		      (int)sizeof(FrameIndex)*(((TraceKey*)pkey)->n_frames-1));    return (TraceKey*)pkey;}static TraceInfo *get_info(TraceIndex index){    TraceInfo *         info;    info        = (TraceInfo*)table_get_info(gdata->trace_table, index);    return info;}static TraceIndexfind_or_create(SerialNumber thread_serial_num, jint n_frames,	    FrameIndex *frames, jvmtiPhase phase, TraceKey *trace_key_buffer){    TraceInfo * info;    TraceKey *  pkey;    int         key_len;    TraceIndex  index;    jboolean    new_one;    static TraceKey empty_key;        HPROF_ASSERT(frames!=NULL);    HPROF_ASSERT(trace_key_buffer!=NULL);    key_len = (int)sizeof(TraceKey);    if ( n_frames > 1 ) {        key_len += (int)((n_frames-1)*(int)sizeof(FrameIndex));    }    pkey = trace_key_buffer;    *pkey = empty_key;    pkey->thread_serial_num = (gdata->thread_in_traces ? thread_serial_num : 0);    pkey->n_frames = (short)n_frames;    pkey->phase = phase;    if ( n_frames > 0 ) {	(void)memcpy(pkey->frames, frames, (n_frames*(int)sizeof(FrameIndex)));    }    new_one = JNI_FALSE;    index = table_find_or_create_entry(gdata->trace_table, 				pkey, key_len, &new_one, NULL);    if ( new_one ) {        info = get_info(index);        info->serial_num = gdata->trace_serial_number_counter++;    }    return index;}static voidlist_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){    TraceInfo *info;    TraceKey         *key;    int               i;    HPROF_ASSERT(key_ptr!=NULL);    HPROF_ASSERT(key_len>0);    HPROF_ASSERT(info_ptr!=NULL);    key = (TraceKey*)key_ptr;    info = (TraceInfo *)info_ptr;        debug_message( "Trace 0x%08x: SN=%u, threadSN=%u, n_frames=%d, frames=(",             index, 	     info->serial_num,             key->thread_serial_num,              key->n_frames);    for ( i = 0 ; i < key->n_frames ; i++ ) {        debug_message( "0x%08x, ", key->frames[i]);    }    debug_message( "), traceSN=%u, num_hits=%d, self_cost=(%d,%d), "			"total_cost=(%d,%d), status=0x%08x\n",                        info->serial_num,                        info->num_hits,                        jlong_high(info->self_cost),                        jlong_low(info->self_cost),                        jlong_high(info->total_cost),                        jlong_low(info->total_cost),                        info->status);}static voidclear_cost(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg){    TraceInfo *info;    HPROF_ASSERT(key_ptr!=NULL);    HPROF_ASSERT(key_len>0);    HPROF_ASSERT(info_ptr!=NULL);    info = (TraceInfo *)info_ptr;    info->num_hits = 0;    info->total_cost = 0;    info->self_cost = 0;}/* Get the names for a frame in order to dump it. */static voidget_frame_details(JNIEnv *env, FrameIndex frame_index, 		SerialNumber *frame_serial_num, char **pcsig, ClassIndex *pcnum,		char **pmname, char **pmsig, char **psname, jint *plineno){    jmethodID method;    jlocation location;    jint      lineno;     HPROF_ASSERT(frame_index!=0);    *pmname = NULL;    *pmsig = NULL;    *pcsig = NULL;    if ( psname != NULL ) {	*psname = NULL;    }    if ( plineno != NULL ) {	*plineno = -1;    }    if ( pcnum != NULL ) {	*pcnum = 0;    }    frame_get_location(frame_index, frame_serial_num, &method, &location, &lineno);    if ( plineno != NULL ) {        *plineno = lineno;    }    WITH_LOCAL_REFS(env, 1) {	jclass klass;		getMethodClass(method, &klass);	getClassSignature(klass, pcsig, NULL);	if ( pcnum != NULL ) {	    LoaderIndex loader_index;	    jobject     loader;            	    loader = getClassLoader(klass);	    loader_index = loader_find_or_create(env, loader);            *pcnum = class_find_or_create(*pcsig, loader_index);	     (void)class_new_classref(env, *pcnum, klass);	}	if ( psname != NULL ) {            getSourceFileName(klass, psname);	}    } END_WITH_LOCAL_REFS;    getMethodName(method, pmname, pmsig);}/* Write out a stack trace.  */static void output_trace(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){    TraceKey *key;    TraceInfo *info;    SerialNumber serial_num;    SerialNumber thread_serial_num;    jint n_frames;    JNIEnv *env;    int i;    char *phase_str;    struct FrameNames {	SerialNumber serial_num;        char * sname;        char * csig;        char * mname;        int    lineno;    } *finfo;    info = (TraceInfo*)info_ptr;    if ( info->status != 0 ) {        return;    }        env = (JNIEnv*)arg;    key = (TraceKey*)key_ptr;    thread_serial_num = key->thread_serial_num;    serial_num = info->serial_num;    info->status = 1;    finfo = NULL;       n_frames = (jint)key->n_frames;    if ( n_frames > 0 ) {	finfo = (struct FrameNames *)HPROF_MALLOC(n_frames*(int)sizeof(struct FrameNames));       	/* Write frames, but save information for trace later */	for (i = 0; i < n_frames; i++) {	    FrameIndex frame_index;	    char *msig;	    ClassIndex cnum;	    	    frame_index = key->frames[i];	    get_frame_details(env, frame_index, &finfo[i].serial_num,			&finfo[i].csig, &cnum,			&finfo[i].mname, &msig, &finfo[i].sname, &finfo[i].lineno);	    	    if (frame_get_status(frame_index) == 0) {		io_write_frame(frame_index, finfo[i].serial_num,			       finfo[i].mname, msig, 			       finfo[i].sname, class_get_serial_number(cnum), 			       finfo[i].lineno);		frame_set_status(frame_index, 1);	    }	    jvmtiDeallocate(msig);	}           }    /* Find phase string */    if ( key->phase == JVMTI_PHASE_LIVE ) {	phase_str = NULL; /* Normal trace, no phase annotation */    } else {        phase_str =  phaseString(key->phase);    }    io_write_trace_header(serial_num, thread_serial_num, n_frames, phase_str);        for (i = 0; i < n_frames; i++) {	io_write_trace_elem(serial_num, key->frames[i], finfo[i].serial_num,			    finfo[i].csig,                             finfo[i].mname, finfo[i].sname, finfo[i].lineno);        jvmtiDeallocate(finfo[i].csig);        jvmtiDeallocate(finfo[i].mname);	jvmtiDeallocate(finfo[i].sname);    }    io_write_trace_footer(serial_num, thread_serial_num, n_frames);       if ( finfo != NULL ) {	HPROF_FREE(finfo);    }}/* Output a specific list of traces. */static void output_list(JNIEnv *env, TraceIndex *list, jint count){    rawMonitorEnter(gdata->data_access_lock); {	int i;	for ( i = 0; i < count ; i++ ) {	    TraceIndex index;	    TraceInfo  *info;	    void *      pkey;	    int         key_len;	    	    index = list[i];            table_get_key(gdata->trace_table, index, &pkey, &key_len);	    info = get_info(index);            output_trace(index, pkey, key_len, info, (void*)env);	}    } rawMonitorExit(gdata->data_access_lock);}static voidcollect_iterator(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg){    TraceInfo *info;    IterateInfo      *iterate;    HPROF_ASSERT(key_ptr!=NULL);    HPROF_ASSERT(key_len>0);    HPROF_ASSERT(arg!=NULL);    HPROF_ASSERT(info_ptr!=NULL);    iterate = (IterateInfo *)arg;    info = (TraceInfo *)info_ptr;    iterate->traces[iterate->count++] = index;    iterate->grand_total_cost += info->self_cost;}static int qsort_compare_cost(const void *p_trace1, const void *p_trace2){    TraceIndex          trace1;    TraceIndex          trace2;    TraceInfo * info1;    TraceInfo * info2;        HPROF_ASSERT(p_trace1!=NULL);    HPROF_ASSERT(p_trace2!=NULL);    trace1 = *(TraceIndex *)p_trace1;    trace2 = *(TraceIndex *)p_trace2;    info1 = get_info(trace1);    info2 = get_info(trace2);    /*LINTED*/    return (int)(info2->self_cost - info1->self_cost);}static int qsort_compare_num_hits(const void *p_trace1, const void *p_trace2){    TraceIndex          trace1;    TraceIndex          trace2;    TraceInfo * info1;    TraceInfo * info2;        HPROF_ASSERT(p_trace1!=NULL);    HPROF_ASSERT(p_trace2!=NULL);    trace1 = *(TraceIndex *)p_trace1;    trace2 = *(TraceIndex *)p_trace2;    info1 = get_info(trace1);    info2 = get_info(trace2);    return info2->num_hits - info1->num_hits;}/* External interfaces. */voidtrace_init(void){    gdata->trace_table = table_initialize("Trace",                            256, 256, 511, (int)sizeof(TraceInfo));}voidtrace_list(void){    debug_message(         "--------------------- Trace Table ------------------------\n");    table_walk_items(gdata->trace_table, &list_item, NULL);    debug_message(        "----------------------------------------------------------\n");}voidtrace_cleanup(void){    table_cleanup(gdata->trace_table, NULL, NULL);    gdata->trace_table = NULL;}SerialNumbertrace_get_serial_number(TraceIndex index){    TraceInfo *info;    if ( index == 0 ) {	return 0;    }    info = get_info(index);    return info->serial_num;}voidtrace_increment_cost(TraceIndex index, jint num_hits, jlong self_cost, jlong total_cost)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?