]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/callgrind/threads.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / callgrind / threads.c
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@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