Add bug 467036 Add time cost statistics for Regtest to NEWS
[valgrind.git] / callgrind / threads.c
blob20b23c189965725a7893ce13452dd4d22b023c58
1 /*--------------------------------------------------------------------*/
2 /*--- Callgrind ---*/
3 /*--- ct_threads.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Callgrind, a Valgrind tool for call tracing.
9 Copyright (C) 2002-2017, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
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.
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.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, see <http://www.gnu.org/licenses/>.
24 The GNU General Public License is contained in the file COPYING.
27 #include "global.h"
29 #include "pub_tool_threadstate.h"
31 /* forward decls */
32 static exec_state* exec_state_save(void);
33 static exec_state* exec_state_restore(void);
34 static exec_state* push_exec_state(int);
35 static exec_state* top_exec_state(void);
37 static exec_stack current_states;
40 /*------------------------------------------------------------*/
41 /*--- Support for multi-threading ---*/
42 /*------------------------------------------------------------*/
46 * For Valgrind, MT is cooperative (no preemting in our code),
47 * so we don't need locks...
49 * Per-thread data:
50 * - BBCCs
51 * - call stack
52 * - call hash
53 * - event counters: last, current
55 * Even when ignoring MT, we need this functions to set up some
56 * datastructures for the process (= Thread 1).
59 /* current running thread */
60 ThreadId CLG_(current_tid);
62 static thread_info** thread;
64 thread_info** CLG_(get_threads)()
66 return thread;
69 thread_info* CLG_(get_current_thread)()
71 return thread[CLG_(current_tid)];
74 void CLG_(init_threads)()
76 UInt i;
78 thread = CLG_MALLOC("cl.threads.it.1", VG_N_THREADS * sizeof thread[0]);
80 for(i=0;i<VG_N_THREADS;i++)
81 thread[i] = 0;
82 CLG_(current_tid) = VG_INVALID_THREADID;
85 /* switches through all threads and calls func */
86 void CLG_(forall_threads)(void (*func)(thread_info*))
88 Int t, orig_tid = CLG_(current_tid);
90 for(t=1;t<VG_N_THREADS;t++) {
91 if (!thread[t]) continue;
92 CLG_(switch_thread)(t);
93 (*func)(thread[t]);
95 CLG_(switch_thread)(orig_tid);
99 static
100 thread_info* new_thread(void)
102 thread_info* t;
104 t = (thread_info*) CLG_MALLOC("cl.threads.nt.1",
105 sizeof(thread_info));
107 /* init state */
108 CLG_(init_exec_stack)( &(t->states) );
109 CLG_(init_call_stack)( &(t->calls) );
110 CLG_(init_fn_stack) ( &(t->fns) );
111 /* t->states.entry[0]->cxt = CLG_(get_cxt)(t->fns.bottom); */
113 /* event counters */
114 t->lastdump_cost = CLG_(get_eventset_cost)( CLG_(sets).full );
115 t->sighandler_cost = CLG_(get_eventset_cost)( CLG_(sets).full );
116 CLG_(init_cost)( CLG_(sets).full, t->lastdump_cost );
117 CLG_(init_cost)( CLG_(sets).full, t->sighandler_cost );
119 /* init data containers */
120 CLG_(init_fn_array)( &(t->fn_active) );
121 CLG_(init_bbcc_hash)( &(t->bbccs) );
122 CLG_(init_jcc_hash)( &(t->jccs) );
124 return t;
128 void CLG_(switch_thread)(ThreadId tid)
130 if (tid == CLG_(current_tid)) return;
132 CLG_DEBUG(0, ">> thread %u (was %u)\n", tid, CLG_(current_tid));
134 if (CLG_(current_tid) != VG_INVALID_THREADID) {
135 /* save thread state */
136 thread_info* t = thread[CLG_(current_tid)];
138 CLG_ASSERT(t != 0);
140 /* current context (including signal handler contexts) */
141 exec_state_save();
142 CLG_(copy_current_exec_stack)( &(t->states) );
143 CLG_(copy_current_call_stack)( &(t->calls) );
144 CLG_(copy_current_fn_stack) ( &(t->fns) );
146 CLG_(copy_current_fn_array) ( &(t->fn_active) );
147 /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
148 if (!CLG_(clo).separate_threads) t = thread[1];
149 CLG_(copy_current_bbcc_hash)( &(t->bbccs) );
150 CLG_(copy_current_jcc_hash) ( &(t->jccs) );
153 CLG_(current_tid) = tid;
154 CLG_ASSERT(tid < VG_N_THREADS);
156 if (tid != VG_INVALID_THREADID) {
157 thread_info* t;
159 /* load thread state */
161 if (thread[tid] == 0) thread[tid] = new_thread();
162 t = thread[tid];
164 /* current context (including signal handler contexts) */
165 CLG_(set_current_exec_stack)( &(t->states) );
166 exec_state_restore();
167 CLG_(set_current_call_stack)( &(t->calls) );
168 CLG_(set_current_fn_stack) ( &(t->fns) );
170 CLG_(set_current_fn_array) ( &(t->fn_active) );
171 /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
172 if (!CLG_(clo).separate_threads) t = thread[1];
173 CLG_(set_current_bbcc_hash) ( &(t->bbccs) );
174 CLG_(set_current_jcc_hash) ( &(t->jccs) );
179 void CLG_(run_thread)(ThreadId tid)
181 /* check for dumps needed */
182 static ULong bbs_done = 0;
183 HChar buf[50]; // large enough
185 if (CLG_(clo).dump_every_bb >0) {
186 if (CLG_(stat).bb_executions - bbs_done > CLG_(clo).dump_every_bb) {
187 VG_(sprintf)(buf, "--dump-every-bb=%llu", CLG_(clo).dump_every_bb);
188 CLG_(dump_profile)(buf, False);
189 bbs_done = CLG_(stat).bb_executions;
193 /* now check for thread switch */
194 CLG_(switch_thread)(tid);
197 void CLG_(pre_signal)(ThreadId tid, Int sigNum, Bool alt_stack)
199 exec_state *es;
201 CLG_DEBUG(0, ">> pre_signal(TID %u, sig %d, alt_st %s)\n",
202 tid, sigNum, alt_stack ? "yes":"no");
204 /* switch to the thread the handler runs in */
205 CLG_(switch_thread)(tid);
207 /* save current execution state */
208 exec_state_save();
210 /* setup new cxtinfo struct for this signal handler */
211 es = push_exec_state(sigNum);
212 CLG_(zero_cost)( CLG_(sets).full, es->cost );
213 CLG_(current_state).cost = es->cost;
214 es->call_stack_bottom = CLG_(current_call_stack).sp;
216 /* setup current state for a spontaneous call */
217 CLG_(init_exec_state)( &CLG_(current_state) );
218 CLG_(current_state).sig = sigNum;
219 CLG_(push_cxt)(0);
222 /* Run post-signal if the stackpointer for call stack is at
223 * the bottom in current exec state (e.g. a signal handler)
225 * Called from CLG_(pop_call_stack)
227 void CLG_(run_post_signal_on_call_stack_bottom)()
229 exec_state* es = top_exec_state();
230 CLG_ASSERT(es != 0);
231 CLG_ASSERT(CLG_(current_state).sig >0);
233 if (CLG_(current_call_stack).sp == es->call_stack_bottom)
234 CLG_(post_signal)( CLG_(current_tid), CLG_(current_state).sig );
237 void CLG_(post_signal)(ThreadId tid, Int sigNum)
239 exec_state* es;
240 UInt fn_number, *pactive;
242 CLG_DEBUG(0, ">> post_signal(TID %u, sig %d)\n",
243 tid, sigNum);
245 /* thread switching potentially needed, eg. with instrumentation off */
246 CLG_(switch_thread)(tid);
247 CLG_ASSERT(sigNum == CLG_(current_state).sig);
249 /* Unwind call stack of this signal handler.
250 * This should only be needed at finalisation time
252 es = top_exec_state();
253 CLG_ASSERT(es != 0);
254 while(CLG_(current_call_stack).sp > es->call_stack_bottom)
255 CLG_(pop_call_stack)();
257 if (CLG_(current_state).cxt) {
258 /* correct active counts */
259 fn_number = CLG_(current_state).cxt->fn[0]->number;
260 pactive = CLG_(get_fn_entry)(fn_number);
261 (*pactive)--;
262 CLG_DEBUG(0, " set active count of %s back to %u\n",
263 CLG_(current_state).cxt->fn[0]->name, *pactive);
266 if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom) {
267 /* set fn_stack_top back.
268 * top can point to 0 if nothing was executed in the signal handler;
269 * this is possible at end on unwinding handlers.
271 if (*(CLG_(current_fn_stack).top) != 0) {
272 CLG_(current_fn_stack).top--;
273 CLG_ASSERT(*(CLG_(current_fn_stack).top) == 0);
275 if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom)
276 CLG_(current_fn_stack).top--;
279 /* sum up costs */
280 CLG_ASSERT(CLG_(current_state).cost == es->cost);
281 CLG_(add_and_zero_cost)( CLG_(sets).full,
282 thread[CLG_(current_tid)]->sighandler_cost,
283 CLG_(current_state).cost );
285 /* restore previous context */
286 es->sig = -1;
287 current_states.sp--;
288 es = top_exec_state();
289 CLG_(current_state).sig = es->sig;
290 exec_state_restore();
292 /* There is no way to reliable get the thread ID we are switching to
293 * after this handler returns. So we sync with actual TID at start of
294 * CLG_(setup_bb)(), which should be the next for callgrind.
300 /*------------------------------------------------------------*/
301 /*--- Execution states in a thread & signal handlers ---*/
302 /*------------------------------------------------------------*/
304 /* Each thread can be interrupted by a signal handler, and they
305 * themselves again. But as there's no scheduling among handlers
306 * of the same thread, we don't need additional stacks.
307 * So storing execution contexts and
308 * adding separators in the callstack(needed to not intermix normal/handler
309 * functions in contexts) should be enough.
312 /* not initialized: call_stack_bottom, sig */
313 void CLG_(init_exec_state)(exec_state* es)
315 es->collect = CLG_(clo).collect_atstart;
316 es->cxt = 0;
317 es->jmps_passed = 0;
318 es->bbcc = 0;
319 es->nonskipped = 0;
323 static exec_state* new_exec_state(Int sigNum)
325 exec_state* es;
326 es = (exec_state*) CLG_MALLOC("cl.threads.nes.1",
327 sizeof(exec_state));
329 /* allocate real cost space: needed as incremented by
330 * simulation functions */
331 es->cost = CLG_(get_eventset_cost)(CLG_(sets).full);
332 CLG_(zero_cost)( CLG_(sets).full, es->cost );
333 CLG_(init_exec_state)(es);
334 es->sig = sigNum;
335 es->call_stack_bottom = 0;
337 return es;
340 void CLG_(init_exec_stack)(exec_stack* es)
342 Int i;
344 /* The first element is for the main thread */
345 es->entry[0] = new_exec_state(0);
346 for(i=1;i<MAX_SIGHANDLERS;i++)
347 es->entry[i] = 0;
348 es->sp = 0;
351 void CLG_(copy_current_exec_stack)(exec_stack* dst)
353 Int i;
355 dst->sp = current_states.sp;
356 for(i=0;i<MAX_SIGHANDLERS;i++)
357 dst->entry[i] = current_states.entry[i];
360 void CLG_(set_current_exec_stack)(exec_stack* dst)
362 Int i;
364 current_states.sp = dst->sp;
365 for(i=0;i<MAX_SIGHANDLERS;i++)
366 current_states.entry[i] = dst->entry[i];
370 /* Get top context info struct of current thread */
371 static
372 exec_state* top_exec_state(void)
374 Int sp = current_states.sp;
375 exec_state* es;
377 CLG_ASSERT((sp >= 0) && (sp < MAX_SIGHANDLERS));
378 es = current_states.entry[sp];
379 CLG_ASSERT(es != 0);
380 return es;
383 /* Allocates a free context info structure for a new entered
384 * signal handler, putting it on the context stack.
385 * Returns a pointer to the structure.
387 static exec_state* push_exec_state(int sigNum)
389 Int sp;
390 exec_state* es;
392 current_states.sp++;
393 sp = current_states.sp;
395 CLG_ASSERT((sigNum > 0) && (sigNum <= _VKI_NSIG));
396 CLG_ASSERT((sp > 0) && (sp < MAX_SIGHANDLERS));
397 es = current_states.entry[sp];
398 if (!es) {
399 es = new_exec_state(sigNum);
400 current_states.entry[sp] = es;
402 else
403 es->sig = sigNum;
405 return es;
408 /* Save current context to top cxtinfo struct */
409 static
410 exec_state* exec_state_save(void)
412 exec_state* es = top_exec_state();
414 es->cxt = CLG_(current_state).cxt;
415 es->collect = CLG_(current_state).collect;
416 es->jmps_passed = CLG_(current_state).jmps_passed;
417 es->bbcc = CLG_(current_state).bbcc;
418 es->nonskipped = CLG_(current_state).nonskipped;
419 CLG_ASSERT(es->cost == CLG_(current_state).cost);
421 CLG_DEBUGIF(1) {
422 CLG_DEBUG(1, " cxtinfo_save(sig %d): collect %s, jmps_passed %d\n",
423 es->sig, es->collect ? "Yes": "No", es->jmps_passed);
424 CLG_(print_bbcc)(-9, es->bbcc);
425 CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
428 /* signal number does not need to be saved */
429 CLG_ASSERT(CLG_(current_state).sig == es->sig);
431 return es;
434 static
435 exec_state* exec_state_restore(void)
437 exec_state* es = top_exec_state();
439 CLG_(current_state).cxt = es->cxt;
440 CLG_(current_state).collect = es->collect;
441 CLG_(current_state).jmps_passed = es->jmps_passed;
442 CLG_(current_state).bbcc = es->bbcc;
443 CLG_(current_state).nonskipped = es->nonskipped;
444 CLG_(current_state).cost = es->cost;
445 CLG_(current_state).sig = es->sig;
447 CLG_DEBUGIF(1) {
448 CLG_DEBUG(1, " exec_state_restore(sig %d): collect %s, jmps_passed %d\n",
449 es->sig, es->collect ? "Yes": "No", es->jmps_passed);
450 CLG_(print_bbcc)(-9, es->bbcc);
451 CLG_(print_cxt)(-9, es->cxt, 0);
452 CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
455 return es;