Home | History | Annotate | Download | only in callgrind
      1 /*--------------------------------------------------------------------*/
      2 /*--- Callgrind                                                    ---*/
      3 /*---                                                 ct_threads.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Callgrind, a Valgrind tool for call tracing.
      8 
      9    Copyright (C) 2002-2010, Josef Weidendorfer (Josef.Weidendorfer (at) gmx.de)
     10 
     11    This program is free software; you can redistribute it and/or
     12    modify it under the terms of the GNU General Public License as
     13    published by the Free Software Foundation; either version 2 of the
     14    License, or (at your option) any later version.
     15 
     16    This program is distributed in the hope that it will be useful, but
     17    WITHOUT ANY WARRANTY; without even the implied warranty of
     18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     19    General Public License for more details.
     20 
     21    You should have received a copy of the GNU General Public License
     22    along with this program; if not, write to the Free Software
     23    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     24    02111-1307, USA.
     25 
     26    The GNU General Public License is contained in the file COPYING.
     27 */
     28 
     29 #include "global.h"
     30 
     31 #include <pub_tool_threadstate.h>
     32 
     33 /* forward decls */
     34 static exec_state* exec_state_save(void);
     35 static exec_state* exec_state_restore(void);
     36 static exec_state* push_exec_state(int);
     37 static exec_state* top_exec_state(void);
     38 
     39 static exec_stack current_states;
     40 
     41 
     42 /*------------------------------------------------------------*/
     43 /*--- Support for multi-threading                          ---*/
     44 /*------------------------------------------------------------*/
     45 
     46 
     47 /*
     48  * For Valgrind, MT is cooperative (no preemting in our code),
     49  * so we don't need locks...
     50  *
     51  * Per-thread data:
     52  *  - BBCCs
     53  *  - call stack
     54  *  - call hash
     55  *  - event counters: last, current
     56  *
     57  * Even when ignoring MT, we need this functions to set up some
     58  * datastructures for the process (= Thread 1).
     59  */
     60 
     61 /* current running thread */
     62 ThreadId CLG_(current_tid);
     63 
     64 static thread_info* thread[VG_N_THREADS];
     65 
     66 thread_info** CLG_(get_threads)()
     67 {
     68   return thread;
     69 }
     70 
     71 thread_info* CLG_(get_current_thread)()
     72 {
     73   return thread[CLG_(current_tid)];
     74 }
     75 
     76 void CLG_(init_threads)()
     77 {
     78     Int i;
     79     for(i=0;i<VG_N_THREADS;i++)
     80 	thread[i] = 0;
     81     CLG_(current_tid) = VG_INVALID_THREADID;
     82 }
     83 
     84 /* switches through all threads and calls func */
     85 void CLG_(forall_threads)(void (*func)(thread_info*))
     86 {
     87   Int t, orig_tid = CLG_(current_tid);
     88 
     89   for(t=1;t<VG_N_THREADS;t++) {
     90     if (!thread[t]) continue;
     91     CLG_(switch_thread)(t);
     92     (*func)(thread[t]);
     93   }
     94   CLG_(switch_thread)(orig_tid);
     95 }
     96 
     97 
     98 static
     99 thread_info* new_thread(void)
    100 {
    101     thread_info* t;
    102 
    103     t = (thread_info*) CLG_MALLOC("cl.threads.nt.1",
    104                                   sizeof(thread_info));
    105 
    106     /* init state */
    107     CLG_(init_exec_stack)( &(t->states) );
    108     CLG_(init_call_stack)( &(t->calls) );
    109     CLG_(init_fn_stack)  ( &(t->fns) );
    110     /* t->states.entry[0]->cxt = CLG_(get_cxt)(t->fns.bottom); */
    111 
    112     /* event counters */
    113     t->lastdump_cost   = CLG_(get_eventset_cost)( CLG_(sets).full );
    114     t->sighandler_cost = CLG_(get_eventset_cost)( CLG_(sets).full );
    115     CLG_(init_cost)( CLG_(sets).full, t->lastdump_cost );
    116     CLG_(init_cost)( CLG_(sets).full, t->sighandler_cost );
    117 
    118     /* init data containers */
    119     CLG_(init_fn_array)( &(t->fn_active) );
    120     CLG_(init_bbcc_hash)( &(t->bbccs) );
    121     CLG_(init_jcc_hash)( &(t->jccs) );
    122 
    123     return t;
    124 }
    125 
    126 
    127 void CLG_(switch_thread)(ThreadId tid)
    128 {
    129   if (tid == CLG_(current_tid)) return;
    130 
    131   CLG_DEBUG(0, ">> thread %d (was %d)\n", tid, CLG_(current_tid));
    132 
    133   if (CLG_(current_tid) != VG_INVALID_THREADID) {
    134     /* save thread state */
    135     thread_info* t = thread[CLG_(current_tid)];
    136 
    137     CLG_ASSERT(t != 0);
    138 
    139     /* current context (including signal handler contexts) */
    140     exec_state_save();
    141     CLG_(copy_current_exec_stack)( &(t->states) );
    142     CLG_(copy_current_call_stack)( &(t->calls) );
    143     CLG_(copy_current_fn_stack)  ( &(t->fns) );
    144 
    145     CLG_(copy_current_fn_array) ( &(t->fn_active) );
    146     /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
    147     if (!CLG_(clo).separate_threads) t = thread[1];
    148     CLG_(copy_current_bbcc_hash)( &(t->bbccs) );
    149     CLG_(copy_current_jcc_hash) ( &(t->jccs) );
    150   }
    151 
    152   CLG_(current_tid) = tid;
    153   CLG_ASSERT(tid < VG_N_THREADS);
    154 
    155   if (tid != VG_INVALID_THREADID) {
    156     thread_info* t;
    157 
    158     /* load thread state */
    159 
    160     if (thread[tid] == 0) thread[tid] = new_thread();
    161     t = thread[tid];
    162 
    163     /* current context (including signal handler contexts) */
    164     CLG_(set_current_exec_stack)( &(t->states) );
    165     exec_state_restore();
    166     CLG_(set_current_call_stack)( &(t->calls) );
    167     CLG_(set_current_fn_stack)  ( &(t->fns) );
    168 
    169     CLG_(set_current_fn_array)  ( &(t->fn_active) );
    170     /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
    171     if (!CLG_(clo).separate_threads) t = thread[1];
    172     CLG_(set_current_bbcc_hash) ( &(t->bbccs) );
    173     CLG_(set_current_jcc_hash)  ( &(t->jccs) );
    174   }
    175 }
    176 
    177 
    178 void CLG_(run_thread)(ThreadId tid)
    179 {
    180     /* check for dumps needed */
    181     static ULong bbs_done = 0;
    182     static Char buf[512];
    183 
    184     if (CLG_(clo).dump_every_bb >0) {
    185        if (CLG_(stat).bb_executions - bbs_done > CLG_(clo).dump_every_bb) {
    186            VG_(sprintf)(buf, "--dump-every-bb=%llu", CLG_(clo).dump_every_bb);
    187 	   CLG_(dump_profile)(buf, False);
    188            bbs_done = CLG_(stat).bb_executions;
    189        }
    190     }
    191 
    192     CLG_(check_command)();
    193 
    194     /* now check for thread switch */
    195     CLG_(switch_thread)(tid);
    196 }
    197 
    198 void CLG_(pre_signal)(ThreadId tid, Int sigNum, Bool alt_stack)
    199 {
    200     exec_state *es;
    201 
    202     CLG_DEBUG(0, ">> pre_signal(TID %d, sig %d, alt_st %s)\n",
    203 	     tid, sigNum, alt_stack ? "yes":"no");
    204 
    205     /* switch to the thread the handler runs in */
    206     CLG_(switch_thread)(tid);
    207 
    208     /* save current execution state */
    209     exec_state_save();
    210 
    211     /* setup new cxtinfo struct for this signal handler */
    212     es = push_exec_state(sigNum);
    213     CLG_(zero_cost)( CLG_(sets).full, es->cost );
    214     CLG_(current_state).cost = es->cost;
    215     es->call_stack_bottom = CLG_(current_call_stack).sp;
    216 
    217     /* setup current state for a spontaneous call */
    218     CLG_(init_exec_state)( &CLG_(current_state) );
    219     CLG_(current_state).sig = sigNum;
    220     CLG_(push_cxt)(0);
    221 }
    222 
    223 /* Run post-signal if the stackpointer for call stack is at
    224  * the bottom in current exec state (e.g. a signal handler)
    225  *
    226  * Called from CLG_(pop_call_stack)
    227  */
    228 void CLG_(run_post_signal_on_call_stack_bottom)()
    229 {
    230     exec_state* es = top_exec_state();
    231     CLG_ASSERT(es != 0);
    232     CLG_ASSERT(CLG_(current_state).sig >0);
    233 
    234     if (CLG_(current_call_stack).sp == es->call_stack_bottom)
    235 	CLG_(post_signal)( CLG_(current_tid), CLG_(current_state).sig );
    236 }
    237 
    238 void CLG_(post_signal)(ThreadId tid, Int sigNum)
    239 {
    240     exec_state* es;
    241     UInt fn_number, *pactive;
    242 
    243     CLG_DEBUG(0, ">> post_signal(TID %d, sig %d)\n",
    244 	     tid, sigNum);
    245 
    246     /* thread switching potentially needed, eg. with instrumentation off */
    247     CLG_(switch_thread)(tid);
    248     CLG_ASSERT(sigNum == CLG_(current_state).sig);
    249 
    250     /* Unwind call stack of this signal handler.
    251      * This should only be needed at finalisation time
    252      */
    253     es = top_exec_state();
    254     CLG_ASSERT(es != 0);
    255     while(CLG_(current_call_stack).sp > es->call_stack_bottom)
    256       CLG_(pop_call_stack)();
    257 
    258     if (CLG_(current_state).cxt) {
    259       /* correct active counts */
    260       fn_number = CLG_(current_state).cxt->fn[0]->number;
    261       pactive = CLG_(get_fn_entry)(fn_number);
    262       (*pactive)--;
    263       CLG_DEBUG(0, "  set active count of %s back to %d\n",
    264 	       CLG_(current_state).cxt->fn[0]->name, *pactive);
    265     }
    266 
    267     if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom) {
    268 	/* set fn_stack_top back.
    269 	 * top can point to 0 if nothing was executed in the signal handler;
    270 	 * this is possible at end on unwinding handlers.
    271 	 */
    272 	if (*(CLG_(current_fn_stack).top) != 0) {
    273 	    CLG_(current_fn_stack).top--;
    274 	    CLG_ASSERT(*(CLG_(current_fn_stack).top) == 0);
    275 	}
    276       if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom)
    277 	CLG_(current_fn_stack).top--;
    278     }
    279 
    280     /* sum up costs */
    281     CLG_ASSERT(CLG_(current_state).cost == es->cost);
    282     CLG_(add_and_zero_cost)( CLG_(sets).full,
    283 			    thread[CLG_(current_tid)]->sighandler_cost,
    284 			    CLG_(current_state).cost );
    285 
    286     /* restore previous context */
    287     es->sig = -1;
    288     current_states.sp--;
    289     es = top_exec_state();
    290     CLG_(current_state).sig = es->sig;
    291     exec_state_restore();
    292 
    293     /* There is no way to reliable get the thread ID we are switching to
    294      * after this handler returns. So we sync with actual TID at start of
    295      * CLG_(setup_bb)(), which should be the next for callgrind.
    296      */
    297 }
    298 
    299 
    300 
    301 /*------------------------------------------------------------*/
    302 /*--- Execution states in a thread & signal handlers       ---*/
    303 /*------------------------------------------------------------*/
    304 
    305 /* Each thread can be interrupted by a signal handler, and they
    306  * themselves again. But as there's no scheduling among handlers
    307  * of the same thread, we don't need additional stacks.
    308  * So storing execution contexts and
    309  * adding separators in the callstack(needed to not intermix normal/handler
    310  * functions in contexts) should be enough.
    311  */
    312 
    313 /* not initialized: call_stack_bottom, sig */
    314 void CLG_(init_exec_state)(exec_state* es)
    315 {
    316   es->collect = CLG_(clo).collect_atstart;
    317   es->cxt  = 0;
    318   es->jmps_passed = 0;
    319   es->bbcc = 0;
    320   es->nonskipped = 0;
    321 }
    322 
    323 
    324 static exec_state* new_exec_state(Int sigNum)
    325 {
    326     exec_state* es;
    327     es = (exec_state*) CLG_MALLOC("cl.threads.nes.1",
    328                                   sizeof(exec_state));
    329 
    330     /* allocate real cost space: needed as incremented by
    331      * simulation functions */
    332     es->cost       = CLG_(get_eventset_cost)(CLG_(sets).full);
    333     CLG_(zero_cost)( CLG_(sets).full, es->cost );
    334     CLG_(init_exec_state)(es);
    335     es->sig        = sigNum;
    336     es->call_stack_bottom  = 0;
    337 
    338     return es;
    339 }
    340 
    341 void CLG_(init_exec_stack)(exec_stack* es)
    342 {
    343   Int i;
    344 
    345   /* The first element is for the main thread */
    346   es->entry[0] = new_exec_state(0);
    347   for(i=1;i<MAX_SIGHANDLERS;i++)
    348     es->entry[i] = 0;
    349   es->sp = 0;
    350 }
    351 
    352 void CLG_(copy_current_exec_stack)(exec_stack* dst)
    353 {
    354   Int i;
    355 
    356   dst->sp = current_states.sp;
    357   for(i=0;i<MAX_SIGHANDLERS;i++)
    358     dst->entry[i] = current_states.entry[i];
    359 }
    360 
    361 void CLG_(set_current_exec_stack)(exec_stack* dst)
    362 {
    363   Int i;
    364 
    365   current_states.sp = dst->sp;
    366   for(i=0;i<MAX_SIGHANDLERS;i++)
    367     current_states.entry[i] = dst->entry[i];
    368 }
    369 
    370 
    371 /* Get top context info struct of current thread */
    372 static
    373 exec_state* top_exec_state(void)
    374 {
    375   Int sp = current_states.sp;
    376   exec_state* es;
    377 
    378   CLG_ASSERT((sp >= 0) && (sp < MAX_SIGHANDLERS));
    379   es = current_states.entry[sp];
    380   CLG_ASSERT(es != 0);
    381   return es;
    382 }
    383 
    384 /* Allocates a free context info structure for a new entered
    385  * signal handler, putting it on the context stack.
    386  * Returns a pointer to the structure.
    387  */
    388 static exec_state* push_exec_state(int sigNum)
    389 {
    390   Int sp;
    391   exec_state* es;
    392 
    393   current_states.sp++;
    394   sp = current_states.sp;
    395 
    396   CLG_ASSERT((sigNum > 0) && (sigNum <= _VKI_NSIG));
    397   CLG_ASSERT((sp > 0) && (sp < MAX_SIGHANDLERS));
    398   es = current_states.entry[sp];
    399   if (!es) {
    400     es = new_exec_state(sigNum);
    401     current_states.entry[sp] = es;
    402   }
    403   else
    404     es->sig = sigNum;
    405 
    406   return es;
    407 }
    408 
    409 /* Save current context to top cxtinfo struct */
    410 static
    411 exec_state* exec_state_save(void)
    412 {
    413   exec_state* es = top_exec_state();
    414 
    415   es->cxt         = CLG_(current_state).cxt;
    416   es->collect     = CLG_(current_state).collect;
    417   es->jmps_passed = CLG_(current_state).jmps_passed;
    418   es->bbcc        = CLG_(current_state).bbcc;
    419   es->nonskipped  = CLG_(current_state).nonskipped;
    420   CLG_ASSERT(es->cost == CLG_(current_state).cost);
    421 
    422   CLG_DEBUGIF(1) {
    423     CLG_DEBUG(1, "  cxtinfo_save(sig %d): collect %s, jmps_passed %d\n",
    424 	     es->sig, es->collect ? "Yes": "No", es->jmps_passed);
    425     CLG_(print_bbcc)(-9, es->bbcc);
    426     CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
    427   }
    428 
    429   /* signal number does not need to be saved */
    430   CLG_ASSERT(CLG_(current_state).sig == es->sig);
    431 
    432   return es;
    433 }
    434 
    435 static
    436 exec_state* exec_state_restore(void)
    437 {
    438   exec_state* es = top_exec_state();
    439 
    440   CLG_(current_state).cxt     = es->cxt;
    441   CLG_(current_state).collect = es->collect;
    442   CLG_(current_state).jmps_passed = es->jmps_passed;
    443   CLG_(current_state).bbcc    = es->bbcc;
    444   CLG_(current_state).nonskipped = es->nonskipped;
    445   CLG_(current_state).cost    = es->cost;
    446   CLG_(current_state).sig     = es->sig;
    447 
    448   CLG_DEBUGIF(1) {
    449 	CLG_DEBUG(1, "  exec_state_restore(sig %d): collect %s, jmps_passed %d\n",
    450 		  es->sig, es->collect ? "Yes": "No", es->jmps_passed);
    451 	CLG_(print_bbcc)(-9, es->bbcc);
    452 	CLG_(print_cxt)(-9, es->cxt, 0);
    453 	CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
    454   }
    455 
    456   return es;
    457 }
    458 
    459