diff options
Diffstat (limited to 'dbug')
-rw-r--r-- | dbug/dbug.c | 102 | ||||
-rw-r--r-- | dbug/dbug_analyze.c | 608 | ||||
-rwxr-xr-x | dbug/remove_function_from_trace.pl | 11 |
3 files changed, 45 insertions, 676 deletions
diff --git a/dbug/dbug.c b/dbug/dbug.c index 2c06eeff95a..da8733c803f 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -53,9 +53,6 @@ * Enhanced Software Technologies, Tempe, AZ * asuvax!mcdphx!estinc!fnf * - * Binayak Banerjee (profiling enhancements) - * seismo!bpa!sjuvax!bbanerje - * * Michael Widenius: * DBUG_DUMP - To dump a block of memory. * PUSH_FLAG "O" - To be used insted of "o" if we @@ -84,8 +81,8 @@ in pthread_mutex_lock */ -#undef SAFE_MUTEX #include <my_global.h> +#undef SAFE_MUTEX #include <m_string.h> #include <errno.h> @@ -125,7 +122,6 @@ #define DEPTH_ON (1 << 4) /* Function nest level print enabled */ #define PROCESS_ON (1 << 5) /* Process name print enabled */ #define NUMBER_ON (1 << 6) /* Number each line of output */ -#define PROFILE_ON (1 << 7) /* Print out profiling code */ #define PID_ON (1 << 8) /* Identify each line with process id */ #define TIMESTAMP_ON (1 << 9) /* timestamp every line of output */ #define FLUSH_ON_WRITE (1 << 10) /* Flush on every write */ @@ -134,7 +130,6 @@ #define TRACING (cs->stack->flags & TRACE_ON) #define DEBUGGING (cs->stack->flags & DEBUG_ON) -#define PROFILING (cs->stack->flags & PROFILE_ON) /* * Typedefs to make things more obvious. @@ -151,24 +146,6 @@ #define AUTO auto /* Names to be allocated on stack */ #define REGISTER register /* Names to be placed in registers */ -/* - * The default file for profiling. Could also add another flag - * (G?) which allowed the user to specify this. - * - * If the automatic variables get allocated on the stack in - * reverse order from their declarations, then define AUTOS_REVERSE to 1. - * This is used by the code that keeps track of stack usage. For - * forward allocation, the difference in the dbug frame pointers - * represents stack used by the callee function. For reverse allocation, - * the difference represents stack used by the caller function. - * - */ - -#define PROF_FILE "dbugmon.out" -#define PROF_EFMT "E\t%ld\t%s\n" -#define PROF_SFMT "S\t%lx\t%lx\t%s\n" -#define PROF_XFMT "X\t%ld\t%s\n" - #ifdef M_I386 /* predefined by xenix 386 compiler */ #define AUTOS_REVERSE 1 #else @@ -219,10 +196,8 @@ struct settings { uint delay; /* Delay after each output line */ uint sub_level; /* Sub this from code_state->level */ FILE *out_file; /* Current output stream */ - FILE *prof_file; /* Current profiling stream */ char name[FN_REFLEN]; /* Name of output file */ struct link *functions; /* List of functions */ - struct link *p_functions; /* List of profiled functions */ struct link *keywords; /* List of debug keywords */ struct link *processes; /* List of process names */ struct settings *next; /* Next settings in the list */ @@ -279,7 +254,7 @@ typedef struct _db_code_state_ { #define ListDel(A,B,C) ListAddDel(A,B,C,EXCLUDE) static struct link *ListAddDel(struct link *, const char *, const char *, int); static struct link *ListCopy(struct link *); -static int InList(struct link *linkp,const char *cp); +static int InList(struct link *linkp,const char *cp, int exact_match); static uint ListFlags(struct link *linkp); static void FreeList(struct link *linkp); @@ -453,25 +428,29 @@ int DbugParse(CODE_STATE *cs, const char *control) const char *end; int rel, f_used=0; struct settings *stack; + int org_cs_locked; stack= cs->stack; + if (!(org_cs_locked= cs->locked)) + { + cs->locked= 1; + pthread_mutex_lock(&THR_LOCK_dbug); + } + if (control[0] == '-' && control[1] == '#') control+=2; rel= control[0] == '+' || control[0] == '-'; if ((!rel || (!stack->out_file && !stack->next))) { - /* Free memory associated with the state before resetting its members */ FreeState(cs, stack, 0); stack->flags= 0; stack->delay= 0; stack->maxdepth= 0; stack->sub_level= 0; stack->out_file= stderr; - stack->prof_file= NULL; stack->functions= NULL; - stack->p_functions= NULL; stack->keywords= NULL; stack->processes= NULL; } @@ -482,7 +461,6 @@ int DbugParse(CODE_STATE *cs, const char *control) stack->maxdepth= stack->next->maxdepth; stack->sub_level= stack->next->sub_level; strcpy(stack->name, stack->next->name); - stack->prof_file= stack->next->prof_file; if (stack->next == &init_settings) { /* @@ -493,7 +471,6 @@ int DbugParse(CODE_STATE *cs, const char *control) */ stack->out_file= stderr; stack->functions= ListCopy(init_settings.functions); - stack->p_functions= ListCopy(init_settings.p_functions); stack->keywords= ListCopy(init_settings.keywords); stack->processes= ListCopy(init_settings.processes); } @@ -501,7 +478,6 @@ int DbugParse(CODE_STATE *cs, const char *control) { stack->out_file= stack->next->out_file; stack->functions= stack->next->functions; - stack->p_functions= stack->next->p_functions; stack->keywords= stack->next->keywords; stack->processes= stack->next->processes; } @@ -513,7 +489,8 @@ int DbugParse(CODE_STATE *cs, const char *control) int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0; if (sign) control++; c= *control++; - if (*control == ',') control++; + if (*control == ',') + control++; /* XXX when adding new cases here, don't forget _db_explain_ ! */ switch (c) { case 'd': @@ -531,7 +508,7 @@ int DbugParse(CODE_STATE *cs, const char *control) { if (DEBUGGING) stack->keywords= ListDel(stack->keywords, control, end); - break; + break; } stack->keywords= ListAdd(stack->keywords, control, end); stack->flags |= DEBUG_ON; @@ -664,9 +641,14 @@ int DbugParse(CODE_STATE *cs, const char *control) control=end+1; end= DbugStrTok(control); } + if (!org_cs_locked) + { + pthread_mutex_unlock(&THR_LOCK_dbug); + cs->locked= 0; + } return !rel || f_used; } - + #define framep_trace_flag(cs, frp) (frp ? \ frp->level & TRACE_ON : \ (ListFlags(cs->stack->functions) & INCLUDE) ? \ @@ -815,7 +797,7 @@ void _db_set_(const char *control) * * Given pointer to a debug control string in "control", pushes * the current debug settings, parses the control string, and sets - * up a new debug settings with DbugParse() + * up a new debug settings * */ @@ -919,7 +901,7 @@ void _db_pop_() } while (0) #define str_to_buf(S) do { \ char_to_buf(','); \ - buf=strnmov(buf, (S), len+1); \ + buf=strnmov(buf, (S), (uint) (end-buf)); \ if (buf >= end) goto overflow; \ } while (0) #define list_to_buf(l, f) do { \ @@ -1004,7 +986,6 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len) op_list_to_buf('f', cs->stack->functions, cs->stack->functions); op_bool_to_buf('F', cs->stack->flags & FILE_ON); op_bool_to_buf('i', cs->stack->flags & PID_ON); - op_list_to_buf('g', cs->stack->p_functions, PROFILING); op_bool_to_buf('L', cs->stack->flags & LINE_ON); op_bool_to_buf('n', cs->stack->flags & DEPTH_ON); op_bool_to_buf('N', cs->stack->flags & NUMBER_ON); @@ -1259,11 +1240,11 @@ void _db_doprnt_(const char *format,...) va_start(args,format); + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); if (_db_keyword_(cs, cs->u_keyword, 0)) { int save_errno=errno; - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix(cs, cs->u_line); if (TRACING) Indent(cs, cs->level + 1); @@ -1274,6 +1255,9 @@ void _db_doprnt_(const char *format,...) DbugFlush(cs); errno=save_errno; } + else if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); + va_end(args); } @@ -1315,10 +1299,10 @@ void _db_dump_(uint _line_, const char *keyword, CODE_STATE *cs; get_code_state_or_return; + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); if (_db_keyword_(cs, keyword, 0)) { - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix(cs, _line_); if (TRACING) { @@ -1348,6 +1332,8 @@ void _db_dump_(uint _line_, const char *keyword, (void) fputc('\n',cs->stack->out_file); DbugFlush(cs); } + else if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); } @@ -1492,13 +1478,13 @@ static struct link *ListCopy(struct link *orig) * */ -static int InList(struct link *linkp, const char *cp) +static int InList(struct link *linkp, const char *cp, int exact_match) { int result; for (result=MATCHED; linkp != NULL; linkp= linkp->next_link) { - if (!fnmatch(linkp->str, cp, 0)) + if (!(exact_match ? strcmp(linkp->str,cp) : fnmatch(linkp->str, cp, 0))) return linkp->flags; if (!(linkp->flags & EXCLUDE)) result=NOT_MATCHED; @@ -1548,7 +1534,7 @@ static void PushState(CODE_STATE *cs) struct settings *new_malloc; new_malloc= (struct settings *) DbugMalloc(sizeof(struct settings)); - bzero(new_malloc, sizeof(struct settings)); + bzero(new_malloc, sizeof(*new_malloc)); new_malloc->next= cs->stack; cs->stack= new_malloc; } @@ -1578,19 +1564,12 @@ static void FreeState(CODE_STATE *cs, struct settings *state, int free_state) FreeList(state->functions); if (!is_shared(state, processes)) FreeList(state->processes); - if (!is_shared(state, p_functions)) - FreeList(state->p_functions); if (!is_shared(state, out_file)) DBUGCloseFile(cs, state->out_file); else (void) fflush(state->out_file); - if (!is_shared(state, prof_file)) - DBUGCloseFile(cs, state->prof_file); - else - (void) fflush(state->prof_file); - if (free_state) free((void*) state); } @@ -1638,12 +1617,10 @@ void _db_end_() pthread_mutex_lock(&THR_LOCK_dbug); init_settings.flags= OPEN_APPEND; init_settings.out_file= stderr; - init_settings.prof_file= stderr; init_settings.maxdepth= 0; init_settings.delay= 0; init_settings.sub_level= 0; init_settings.functions= 0; - init_settings.p_functions= 0; init_settings.keywords= 0; init_settings.processes= 0; pthread_mutex_unlock(&THR_LOCK_dbug); @@ -1667,8 +1644,8 @@ void _db_end_() static int DoTrace(CODE_STATE *cs) { if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) && - InList(cs->stack->processes, cs->process) & (MATCHED|INCLUDE)) - switch(InList(cs->stack->functions, cs->func)) { + InList(cs->stack->processes, cs->process, 0) & (MATCHED|INCLUDE)) + switch(InList(cs->stack->functions, cs->func, 0)) { case INCLUDE|SUBDIR: return ENABLE_TRACE; case INCLUDE: return DO_TRACE; case MATCHED|SUBDIR: @@ -1711,11 +1688,11 @@ FILE *_db_fp_(void) BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict) { + int match= strict ? INCLUDE : INCLUDE|MATCHED; get_code_state_if_not_set_or_return FALSE; - strict=strict ? INCLUDE : INCLUDE|MATCHED; - return DEBUGGING && DoTrace(cs) & DO_TRACE && - InList(cs->stack->keywords, keyword) & strict; + return (DEBUGGING && DoTrace(cs) & DO_TRACE && + InList(cs->stack->keywords, keyword, strict) & match); } /* @@ -1937,9 +1914,10 @@ static void DBUGOpenFile(CODE_STATE *cs, static void DBUGCloseFile(CODE_STATE *cs, FILE *fp) { - if (fp != NULL && fp != stderr && fp != stdout && fclose(fp) == EOF) + if (fp && fp != stderr && fp != stdout && fclose(fp) == EOF) { - pthread_mutex_lock(&THR_LOCK_dbug); + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); (void) fprintf(cs->stack->out_file, ERR_CLOSE, cs->process); perror(""); DbugFlush(cs); diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c deleted file mode 100644 index 3d5713758ae..00000000000 --- a/dbug/dbug_analyze.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Analyze the profile file (cmon.out) written out by the dbug - * routines with profiling enabled. - * - * Copyright June 1987, Binayak Banerjee - * All rights reserved. - * - * This program may be freely distributed under the same terms and - * conditions as Fred Fish's Dbug package. - * - * Compile with -- cc -O -s -o %s analyze.c - * - * Analyze will read an trace file created by the dbug package - * (when run with traceing enabled). It will then produce a - * summary on standard output listing the name of each traced - * function, the number of times it was called, the percentage - * of total calls, the time spent executing the function, the - * proportion of the total time and the 'importance'. The last - * is a metric which is obtained by multiplying the proportions - * of calls and the proportions of time for each function. The - * greater the importance, the more likely it is that a speedup - * could be obtained by reducing the time taken by that function. - * - * Note that the timing values that you obtain are only rough - * measures. The overhead of the dbug package is included - * within. However, there is no need to link in special profiled - * libraries and the like. - * - * CHANGES: - * - * 2-Mar-89: fnf - * Changes to support tracking of stack usage. This required - * reordering the fields in the profile log file to make - * parsing of different record types easier. Corresponding - * changes made in dbug runtime library. Also used this - * opportunity to reformat the code more to my liking (my - * apologies to Binayak Banerjee for "uglifying" his code). - * - * 24-Jul-87: fnf - * Because I tend to use functions names like - * "ExternalFunctionDoingSomething", I've rearranged the - * printout to put the function name last in each line, so - * long names don't screw up the formatting unless they are - * *very* long and wrap around the screen width... - * - * 24-Jul-87: fnf - * Modified to put out table very similar to Unix profiler - * by default, but also puts out original verbose table - * if invoked with -v flag. - */ - -#include <my_global.h> -#include <m_string.h> -#include <my_pthread.h> - -static char *my_name; -static int verbose; - -/* - * Structure of the stack. - */ - -#define PRO_FILE "dbugmon.out" /* Default output file name */ -#define STACKSIZ 100 /* Maximum function nesting */ -#define MAXPROCS 10000 /* Maximum number of function calls */ - -# ifdef BSD -# include <sysexits.h> -# else -# define EX_SOFTWARE 1 -# define EX_DATAERR 1 -# define EX_USAGE 1 -# define EX_OSERR 1 -# define EX_IOERR 1 -#ifndef EX_OK -# define EX_OK 0 -#endif -# endif - -#define __MERF_OO_ "%s: Malloc Failed in %s: %d\n" - -#define MALLOC(Ptr,Num,Typ) do /* Malloc w/error checking & exit */ \ - if (!(Ptr = (Typ *)malloc((Num)*(sizeof(Typ))))) \ - {fprintf(stderr,__MERF_OO_,my_name,__FILE__,__LINE__);\ - exit(EX_OSERR);} while(0) - -#define Malloc(Ptr,Num,Typ) do /* Weaker version of above */\ - if (!(Ptr = (Typ *)malloc((Num)*(sizeof(Typ))))) \ - fprintf(stderr,__MERF_OO_,my_name,__FILE__,__LINE__);\ - while(0) - -#define FILEOPEN(Fp,Fn,Mod) do /* File open with error exit */ \ - if (!(Fp = fopen(Fn,Mod)))\ - {fprintf(stderr,"%s: Couldn't open %s\n",my_name,Fn);\ - exit(EX_IOERR);} while(0) - -#define Fileopen(Fp,Fn,Mod) do /* Weaker version of above */ \ - if(!(Fp = fopen(Fn,Mod))) \ - fprintf(stderr,"%s: Couldn't open %s\n",my_name,Fn);\ - while(0) - - -struct stack_t { - unsigned int pos; /* which function? */ - unsigned long time; /* Time that this was entered */ - unsigned long children; /* Time spent in called funcs */ -}; - -static struct stack_t fn_stack[STACKSIZ+1]; - -static unsigned int stacktop = 0; /* Lowest stack position is a dummy */ - -static unsigned long tot_time = 0; -static unsigned long tot_calls = 0; -static unsigned long highstack = 0; -static unsigned long lowstack = (ulong) ~0; - -/* - * top() returns a pointer to the top item on the stack. - * (was a function, now a macro) - */ - -#define top() &fn_stack[stacktop] - -/* - * Push - Push the given record on the stack. - */ - -void push (name_pos, time_entered) -register unsigned int name_pos; -register unsigned long time_entered; -{ - register struct stack_t *t; - - DBUG_ENTER("push"); - if (++stacktop > STACKSIZ) { - fprintf (DBUG_FILE,"%s: stack overflow (%s:%d)\n", - my_name, __FILE__, __LINE__); - exit (EX_SOFTWARE); - } - DBUG_PRINT ("push", ("%d %ld",name_pos,time_entered)); - t = &fn_stack[stacktop]; - t -> pos = name_pos; - t -> time = time_entered; - t -> children = 0; - DBUG_VOID_RETURN; -} - -/* - * Pop - pop the top item off the stack, assigning the field values - * to the arguments. Returns 0 on stack underflow, or on popping first - * item off stack. - */ - -unsigned int pop (name_pos, time_entered, child_time) -register unsigned int *name_pos; -register unsigned long *time_entered; -register unsigned long *child_time; -{ - register struct stack_t *temp; - register unsigned int rtnval; - - DBUG_ENTER ("pop"); - - if (stacktop < 1) { - rtnval = 0; - } else { - temp = &fn_stack[stacktop]; - *name_pos = temp->pos; - *time_entered = temp->time; - *child_time = temp->children; - DBUG_PRINT ("pop", ("%d %lu %lu",*name_pos,*time_entered,*child_time)); - rtnval = stacktop--; - } - DBUG_RETURN (rtnval); -} - -/* - * We keep the function info in another array (serves as a simple - * symbol table) - */ - -struct module_t { - char *name; - unsigned long m_time; - unsigned long m_calls; - unsigned long m_stkuse; -}; - -static struct module_t modules[MAXPROCS]; - -/* - * We keep a binary search tree in order to look up function names - * quickly (and sort them at the end. - */ - -struct bnode { - unsigned int lchild; /* Index of left subtree */ - unsigned int rchild; /* Index of right subtree */ - unsigned int pos; /* Index of module_name entry */ -}; - -static struct bnode s_table[MAXPROCS]; - -static unsigned int n_items = 0; /* No. of items in the array so far */ - -/* - * Need a function to allocate space for a string and squirrel it away. - */ - -char *strsave (s) -char *s; -{ - register char *retval; - register unsigned int len; - - DBUG_ENTER ("strsave"); - DBUG_PRINT ("strsave", ("%s",s)); - if (!s || (len = strlen (s)) == 0) { - DBUG_RETURN (0); - } - MALLOC (retval, ++len, char); - strcpy (retval, s); - DBUG_RETURN (retval); -} - -/* - * add() - adds m_name to the table (if not already there), and returns - * the index of its location in the table. Checks s_table (which is a - * binary search tree) to see whether or not it should be added. - */ - -unsigned int add (m_name) -char *m_name; -{ - register unsigned int ind = 0; - register int cmp; - - DBUG_ENTER ("add"); - if (n_items == 0) { /* First item to be added */ - s_table[0].pos = ind; - s_table[0].lchild = s_table[0].rchild = MAXPROCS; - addit: - modules[n_items].name = strsave (m_name); - modules[n_items].m_time = 0; - modules[n_items].m_calls = 0; - modules[n_items].m_stkuse = 0; - DBUG_RETURN (n_items++); - } - while ((cmp = strcmp (m_name,modules[ind].name))) { - if (cmp < 0) { /* In left subtree */ - if (s_table[ind].lchild == MAXPROCS) { - /* Add as left child */ - if (n_items >= MAXPROCS) { - fprintf (DBUG_FILE, - "%s: Too many functions being profiled\n", - my_name); - exit (EX_SOFTWARE); - } - s_table[n_items].pos = s_table[ind].lchild = n_items; - s_table[n_items].lchild = s_table[n_items].rchild = MAXPROCS; -#ifdef notdef - modules[n_items].name = strsave (m_name); - modules[n_items].m_time = modules[n_items].m_calls = 0; - DBUG_RETURN (n_items++); -#else - goto addit; -#endif - - } - ind = s_table[ind].lchild; /* else traverse l-tree */ - } else { - if (s_table[ind].rchild == MAXPROCS) { - /* Add as right child */ - if (n_items >= MAXPROCS) { - fprintf (DBUG_FILE, - "%s: Too many functions being profiled\n", - my_name); - exit (EX_SOFTWARE); - } - s_table[n_items].pos = s_table[ind].rchild = n_items; - s_table[n_items].lchild = s_table[n_items].rchild = MAXPROCS; -#ifdef notdef - modules[n_items].name = strsave (m_name); - modules[n_items].m_time = modules[n_items].m_calls = 0; - DBUG_RETURN (n_items++); -#else - goto addit; -#endif - - } - ind = s_table[ind].rchild; /* else traverse r-tree */ - } - } - DBUG_RETURN (ind); -} - -/* - * process() - process the input file, filling in the modules table. - */ - -void process (inf) -FILE *inf; -{ - char buf[BUFSIZ]; - char fn_name[64]; /* Max length of fn_name */ - unsigned long fn_time; - unsigned long fn_sbot; - unsigned long fn_ssz; - unsigned long lastuse; - unsigned int pos; - unsigned long local_time; - unsigned int oldpos; - unsigned long oldtime; - unsigned long oldchild; - struct stack_t *t; - - DBUG_ENTER ("process"); - while (fgets (buf,BUFSIZ,inf) != NULL) { - switch (buf[0]) { - case 'E': - sscanf (buf+2, "%ld %64s", &fn_time, fn_name); - DBUG_PRINT ("erec", ("%ld %s", fn_time, fn_name)); - pos = add (fn_name); - push (pos, fn_time); - break; - case 'X': - sscanf (buf+2, "%ld %64s", &fn_time, fn_name); - DBUG_PRINT ("xrec", ("%ld %s", fn_time, fn_name)); - pos = add (fn_name); - /* - * An exited function implies that all stacked - * functions are also exited, until the matching - * function is found on the stack. - */ - while (pop (&oldpos, &oldtime, &oldchild)) { - DBUG_PRINT ("popped", ("%lu %lu", oldtime, oldchild)); - local_time = fn_time - oldtime; - t = top (); - t -> children += local_time; - DBUG_PRINT ("update", ("%s", modules[t -> pos].name)); - DBUG_PRINT ("update", ("%lu", t -> children)); - local_time -= oldchild; - modules[oldpos].m_time += local_time; - modules[oldpos].m_calls++; - tot_time += local_time; - tot_calls++; - if (pos == oldpos) { - goto next_line; /* Should be a break2 */ - } - } - /* - * Assume that item seen started at time 0. - * (True for function main). But initialize - * it so that it works the next time too. - */ - t = top (); - local_time = fn_time - t -> time - t -> children; - t -> time = fn_time; t -> children = 0; - modules[pos].m_time += local_time; - modules[pos].m_calls++; - tot_time += local_time; - tot_calls++; - break; - case 'S': - sscanf (buf+2, "%lx %lx %64s", &fn_sbot, &fn_ssz, fn_name); - DBUG_PRINT ("srec", ("%lx %lx %s", fn_sbot, fn_ssz, fn_name)); - pos = add (fn_name); - lastuse = modules[pos].m_stkuse; -#if 0 - /* - * Needs further thought. Stack use is determined by - * difference in stack between two functions with DBUG_ENTER - * macros. If A calls B calls C, where A and C have the - * macros, and B doesn't, then B's stack use will be lumped - * in with either A's or C's. If somewhere else A calls - * C directly, the stack use will seem to change. Just - * take the biggest for now... - */ - if (lastuse > 0 && lastuse != fn_ssz) { - fprintf (stderr, - "warning - %s stack use changed (%lx to %lx)\n", - fn_name, lastuse, fn_ssz); - } -#endif - if (fn_ssz > lastuse) { - modules[pos].m_stkuse = fn_ssz; - } - if (fn_sbot > highstack) { - highstack = fn_sbot; - } else if (fn_sbot < lowstack) { - lowstack = fn_sbot; - } - break; - default: - fprintf (stderr, "unknown record type '%c'\n", buf[0]); - break; - } - next_line:; - } - - /* - * Now, we've hit eof. If we still have stuff stacked, then we - * assume that the user called exit, so give everything the exited - * time of fn_time. - */ - while (pop (&oldpos,&oldtime,&oldchild)) { - local_time = fn_time - oldtime; - t = top (); - t -> children += local_time; - local_time -= oldchild; - modules[oldpos].m_time += local_time; - modules[oldpos].m_calls++; - tot_time += local_time; - tot_calls++; - } - DBUG_VOID_RETURN; -} - -/* - * out_header () -- print out the header of the report. - */ - -void out_header (outf) -FILE *outf; -{ - DBUG_ENTER ("out_header"); - if (verbose) { - fprintf (outf, "Profile of Execution\n"); - fprintf (outf, "Execution times are in milliseconds\n\n"); - fprintf (outf, " Calls\t\t\t Time\n"); - fprintf (outf, " -----\t\t\t ----\n"); - fprintf (outf, "Times\tPercentage\tTime Spent\tPercentage\n"); - fprintf (outf, "Called\tof total\tin Function\tof total Importance\tFunction\n"); - fprintf (outf, "======\t==========\t===========\t========== ==========\t========\t\n"); - } else { - fprintf (outf, "%ld bytes of stack used, from %lx down to %lx\n\n", - highstack - lowstack, highstack, lowstack); - fprintf (outf, - " %%time sec #call ms/call %%calls weight stack name\n"); - } - DBUG_VOID_RETURN; -} - -/* - * out_trailer () - writes out the summary line of the report. - */ - -void out_trailer (outf,sum_calls,sum_time) -FILE *outf; -unsigned long int sum_calls, sum_time; -{ - DBUG_ENTER ("out_trailer"); - if (verbose) - { - fprintf(outf, "======\t==========\t===========\t==========\t========\n"); - fprintf(outf, "%6ld\t%10.2f\t%11ld\t%10.2f\t\t%-15s\n", - sum_calls, 100.0, sum_time, 100.0, "Totals"); - } - DBUG_VOID_RETURN; -} - -/* - * out_item () - prints out the output line for a single entry, - * and sets the calls and time fields appropriately. - */ - -void out_item (outf, m,called,timed) -FILE *outf; -register struct module_t *m; -unsigned long int *called, *timed; -{ - char *name = m -> name; - register unsigned int calls = m -> m_calls; - register unsigned long local_time = m -> m_time; - register unsigned long stkuse = m -> m_stkuse; - unsigned int import; - double per_time = 0.0; - double per_calls = 0.0; - double ms_per_call, local_ftime; - - DBUG_ENTER ("out_item"); - - if (tot_time > 0) { - per_time = (double) (local_time * 100) / (double) tot_time; - } - if (tot_calls > 0) { - per_calls = (double) (calls * 100) / (double) tot_calls; - } - import = (unsigned int) (per_time * per_calls); - - if (verbose) { - fprintf (outf, "%6d\t%10.2f\t%11ld\t%10.2f %10d\t%-15s\n", - calls, per_calls, local_time, per_time, import, name); - } else { - ms_per_call = local_time; - ms_per_call /= calls; - local_ftime = local_time; - local_ftime /= 1000; - fprintf(outf, "%8.2f%8.3f%8u%8.3f%8.2f%8u%8lu %-s\n", - per_time, local_ftime, calls, ms_per_call, per_calls, import, - stkuse, name); - } - *called = calls; - *timed = local_time; - DBUG_VOID_RETURN; -} - -/* - * out_body (outf, root,s_calls,s_time) -- Performs an inorder traversal - * on the binary search tree (root). Calls out_item to actually print - * the item out. - */ - -void out_body (outf, root,s_calls,s_time) -FILE *outf; -register unsigned int root; -register unsigned long int *s_calls, *s_time; -{ - unsigned long int calls, local_time; - - DBUG_ENTER ("out_body"); - DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time)); - if (root == MAXPROCS) { - DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time)); - } else { - while (root != MAXPROCS) { - out_body (outf, s_table[root].lchild,s_calls,s_time); - out_item (outf, &modules[s_table[root].pos],&calls,&local_time); - DBUG_PRINT ("out_body", ("-- %lu -- %lu --", calls, local_time)); - *s_calls += calls; - *s_time += local_time; - root = s_table[root].rchild; - } - DBUG_PRINT ("out_body", ("%lu,%lu", *s_calls, *s_time)); - } - DBUG_VOID_RETURN; -} - -/* - * output () - print out a nice sorted output report on outf. - */ - -void output (outf) -FILE *outf; -{ - unsigned long int sum_calls = 0; - unsigned long int sum_time = 0; - - DBUG_ENTER ("output"); - if (n_items == 0) { - fprintf (outf, "%s: No functions to trace\n", my_name); - exit (EX_DATAERR); - } - out_header (outf); - out_body (outf, 0,&sum_calls,&sum_time); - out_trailer (outf, sum_calls,sum_time); - DBUG_VOID_RETURN; -} - - -#define usage() fprintf (DBUG_FILE,"Usage: %s [-v] [prof-file]\n",my_name) - -extern int optind; -extern char *optarg; - -int main (int argc, char **argv) -{ - register int c; - int badflg = 0; - FILE *infile; - FILE *outfile = {stdout}; - -#if defined(HAVE_PTHREAD_INIT) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif - my_thread_global_init(); - { - DBUG_ENTER ("main"); - DBUG_PROCESS (argv[0]); - my_name = argv[0]; - while ((c = getopt (argc,argv,"#:v")) != EOF) { - switch (c) { - case '#': /* Debugging Macro enable */ - DBUG_PUSH (optarg); - break; - case 'v': /* Verbose mode */ - verbose++; - break; - default: - badflg++; - break; - } - } - if (badflg) { - usage (); - DBUG_RETURN (EX_USAGE); - } - if (optind < argc) { - FILEOPEN (infile, argv[optind], "r"); - } else { - FILEOPEN (infile, PRO_FILE, "r"); - } - process (infile); - output (outfile); - DBUG_RETURN (EX_OK); - } -} diff --git a/dbug/remove_function_from_trace.pl b/dbug/remove_function_from_trace.pl index 1da9e25f9ba..380df168caf 100755 --- a/dbug/remove_function_from_trace.pl +++ b/dbug/remove_function_from_trace.pl @@ -1,6 +1,5 @@ #!/usr/bin/perl - die <<EEE unless @ARGV; Usage: $0 func1 [func2 [ ...] ] @@ -11,16 +10,16 @@ DBUG_ENTER() and DBUG_POP(); right before DBUG_RETURN in every such a function. EEE $re=join('|', @ARGV); -$skip=''; while(<STDIN>) { - print unless $skip; + ($thd) = /^(T@\d+)/; + print unless $skip{$thd}; next unless /^(?:.*: )*((?:\| )*)([<>])($re)\n/o; if ($2 eq '>') { - $skip=$1.$3 unless $skip; + $skip{$thd}=$1.$3 unless $skip{$thd}; next; } - next if $skip ne $1.$3; - $skip=''; + next if $skip{$thd} ne $1.$3; + delete $skip{$thd}; print; } |