"Fossies" - the Fresh Open Source Software Archive

Member "FunctionCheck-3.2.0/src/fcmanager/fc_functions.c" (26 May 2012, 6916 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * FunctionCheck profiler
    3  * (C) Copyright 2000-2012 Yannick Perret
    4  * 
    5  *  This program is free software; you can redistribute it and/or
    6  *  modify it under the terms of the GNU General Public License as
    7  *  published by the Free Software Foundation; either version 2 of the
    8  *  License, or (at your option) any later version.
    9  *
   10  *  This program is distributed in the hope that it will be useful,
   11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13  *  General Public License for more details.
   14  *
   15  *  You should have received a copy of the GNU General Public License
   16  *  along with this program; if not, write to the Free Software
   17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18  */
   19 /** fc_functions.c: treat enter/exit actions during profile **/
   20 
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <limits.h>
   24 #include "fc_global.h"
   25 #include "fc_com_manager.h"
   26 #include "fc_functions.h"
   27 #include "fc_context.h"
   28 #include "fc_hash.h"
   29 #include "fc_tools.h"
   30 
   31 #ifndef LLONG_MAX
   32 #define     LLONG_MAX       9223372036854775807LL
   33 #endif // LLONG_MAX
   34 
   35 /* initialize a function (pre-allocated) */
   36 void fc_functions_init(FC_Function *fnc)
   37 {
   38     fnc->symbol = NULL;
   39     fnc->calls = 0;
   40     fnc->local_time = fnc->total_time = 0;
   41     fnc->recursive_state = 0;
   42     fnc->min_time = (LLONG_MAX * 2ULL + 1);
   43     fnc->max_time = 0;
   44     fnc->min_ltime = (LLONG_MAX * 2ULL + 1);
   45     fnc->max_ltime = 0;
   46     fnc->temp_ltime = 0;
   47 }
   48 
   49 /* treat entering in a function */
   50 void fc_functions_enter(void *fnc, void *call_site, unsigned long long time)
   51 {
   52     FC_Function tmp;
   53     FC_Function *func, *pfunc;
   54     unsigned long long ptime;
   55 
   56     /* 1st check if the function exists */
   57     if (fnc == NULL)
   58         func = NULL;
   59     else
   60         func = fc_fhash_find(fc_current_context->functions, fnc);
   61 
   62     if (func == NULL)
   63     {
   64         /* if not create one and insert it in the table */
   65         fc_debug("enter: creating function %p", fnc);
   66         tmp.symbol = fnc;
   67         tmp.calls = 0;
   68         tmp.local_time = 0;
   69         tmp.max_time = 0;
   70         tmp.min_time = (LLONG_MAX * 2ULL + 1);
   71         tmp.min_ltime = (LLONG_MAX * 2ULL + 1);
   72         tmp.max_ltime = 0;
   73         tmp.total_time = 0;
   74         tmp.recursive_state = 0;
   75         if (fnc == NULL)
   76             tmp.faked = 1;
   77         else
   78             tmp.faked = 0;
   79         func = fc_fhash_insert(fc_current_context->functions, &tmp);
   80     }
   81     else
   82         /* debug */
   83         fc_debug("enter: finding function %p", fnc);
   84 
   85     /* clear temporary local time */
   86     if (func->recursive_state == 0)
   87         func->temp_ltime = 0;
   88 
   89     /* do not change the order of these instructions */
   90 
   91     /* insert function in the stack */
   92     fc_stack_push(fc_current_context->stack, func, time, call_site);
   93 
   94     /* if we have a parent, compute local time for the parent */
   95     if (fc_stack_size(fc_current_context->stack) > 1)
   96     {
   97         fc_stack_getp(fc_current_context->stack, &pfunc, &ptime);
   98         fc_debug("enter: prev. func=%p. adding %u to local", pfunc->symbol, time - pfunc->last_time);
   99         /* add the local time */
  100         pfunc->temp_ltime += time - pfunc->last_time;
  101     }
  102 
  103     /* set changes */
  104     func->recursive_state++;
  105     func->calls++;
  106     func->last_time = time; /* last active time */
  107     fc_debug("enter: now: rec=%d, calls=%d, last=%u",
  108              func->recursive_state, func->calls, func->last_time);
  109 }
  110 
  111 /* treat exiting a function */
  112 void fc_functions_exit(void *fnc, void *call_site, unsigned long long time)
  113 {
  114     FC_Function *func;
  115     unsigned long long delta, ftime;
  116     FC_Function *pfunc;
  117     unsigned long long ptime;
  118     void *nuse;
  119 
  120     /* 1st, check if the top of the stack correspond to this function */
  121     fc_stack_get(fc_current_context->stack, &func, &ftime, &nuse);
  122     if (func == NULL) /* empty stack! */
  123     {
  124         fc_message("exit from function %p but stack is empty! ignored.", fnc);
  125         fc_message("  this may means that your program uses fork or");
  126         fc_message("  threads in SINGLE mode or that you are in FORK");
  127         fc_message("  mode with more than 16 exits after a fork()");
  128         return;
  129     }
  130 
  131     if ((func->symbol != fnc) && (func->symbol != NULL))
  132     {
  133         /* special: if it is a faked function, we now get it's
  134              real symbol address. set it and remove 'fake' flag */
  135         if (func->faked)
  136         {
  137             fc_debug("exit from faked %p. now %p.", func->symbol, fnc);
  138             func->symbol = fnc;
  139             func->faked = 0;
  140         }
  141         else /* really a bug! */
  142         {
  143             fc_message("exit from function %p but top of the stack is about function %p! Ignored.", fnc, func->symbol);
  144             return;
  145         }
  146     }
  147 
  148     if (func->symbol == NULL)
  149     {
  150         /* this function is here to allow exit from functions
  151              after a fork in the child context (these functions
  152              cannot be known before the exit time)  */
  153         /* set the symbol, even if it is not exactly the good one */
  154         func->symbol = fnc;
  155         if (fc_stack_size(fc_current_context->stack) > 1)
  156         {
  157             fc_stack_getp(fc_current_context->stack, &pfunc, &ptime);
  158             pfunc->symbol = call_site;
  159         }
  160     }
  161 
  162     /** treat the function **/
  163 
  164     /* compute elapsed time */
  165     delta = time - ftime;
  166     fc_debug("exit: from %p (delta=%u)", func->symbol, delta);
  167 
  168     /* this function may have local time to treat */
  169     func->temp_ltime += time - func->last_time;
  170 
  171     if (func->recursive_state <= 1)
  172         func->local_time += func->temp_ltime;
  173 
  174     /* min/max local time */
  175     if (func->temp_ltime > func->max_ltime)
  176         func->max_ltime = func->temp_ltime;
  177     if (func->temp_ltime < func->min_ltime)
  178         func->min_ltime = func->temp_ltime;
  179 
  180     /* if exist, re-set the last active time */
  181     if (fc_stack_size(fc_current_context->stack) > 1)
  182     {
  183         fc_stack_getp(fc_current_context->stack, &pfunc, &ptime);
  184         /* re-set last time */
  185         fc_debug("exit: re-set last time of %p", pfunc->symbol);
  186         pfunc->last_time = time;
  187     }
  188 
  189     /* treat MIN/MAX */
  190     if (delta > func->max_time)
  191         func->max_time = delta;
  192     if (delta < func->min_time)
  193         func->min_time = delta;
  194 
  195     /* if not a recursive function */
  196     /* NOTE: recursive functions MUST NOT be treated here.
  197     else, a 1s fnc calling itself 4 times will have a total
  198     time of 4+3+2+1=10s. it would generate erroneous total
  199     execution time as a total a 4s is really spend in this
  200     part of the call-tree */
  201     if (func->recursive_state <= 1)
  202     {
  203         /* add total time */
  204         fc_debug("exit: non recursive. adding total");
  205         func->total_time += delta;
  206     }
  207 
  208     /* update the state of the function */
  209     func->recursive_state--;
  210 
  211     /* remove the function from the stack */
  212     fc_stack_pop(fc_current_context->stack);
  213 }
  214 
  215