blob: ea5c189e950b4de3cef67fad9245f35c91a1478a [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*--------------------------------------------------------------------*/
2/*--- Callgrind ---*/
3/*--- ct_threads.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Callgrind, a Valgrind tool for call tracing.
8
njn9f207462009-03-10 22:02:09 +00009 Copyright (C) 2002-2009, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +000010
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 */
34static exec_state* exec_state_save(void);
35static exec_state* exec_state_restore(void);
36static exec_state* push_exec_state(int);
37static exec_state* top_exec_state(void);
38
39static 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 */
62ThreadId CLG_(current_tid);
63
64static thread_info* thread[VG_N_THREADS];
65
66thread_info** CLG_(get_threads)()
67{
68 return thread;
69}
70
71thread_info* CLG_(get_current_thread)()
72{
73 return thread[CLG_(current_tid)];
74}
75
76void 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 */
85void 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
98static
99thread_info* new_thread(void)
100{
101 thread_info* t;
102
sewardj9c606bd2008-09-18 18:12:50 +0000103 t = (thread_info*) CLG_MALLOC("cl.threads.nt.1",
104 sizeof(thread_info));
weidendoa17f2a32006-03-20 10:27:30 +0000105
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
127void 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
178void 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) {
weidendo9e326b72006-03-31 13:16:15 +0000186 VG_(sprintf)(buf, "--dump-every-bb=%llu", CLG_(clo).dump_every_bb);
weidendoa17f2a32006-03-20 10:27:30 +0000187 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
198void 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 */
weidendoafdb0112009-12-10 19:26:32 +0000206 CLG_(switch_thread)(tid);
weidendoa17f2a32006-03-20 10:27:30 +0000207
208 /* save current execution state */
209 exec_state_save();
210
weidendoa17f2a32006-03-20 10:27:30 +0000211 /* setup new cxtinfo struct for this signal handler */
212 es = push_exec_state(sigNum);
weidendoe8914872009-08-11 20:53:59 +0000213 CLG_(zero_cost)( CLG_(sets).full, es->cost );
weidendoa17f2a32006-03-20 10:27:30 +0000214 CLG_(current_state).cost = es->cost;
215 es->call_stack_bottom = CLG_(current_call_stack).sp;
216
weidendo61453242009-07-01 23:56:23 +0000217 /* setup current state for a spontaneous call */
218 CLG_(init_exec_state)( &CLG_(current_state) );
weidendoa17f2a32006-03-20 10:27:30 +0000219 CLG_(current_state).sig = sigNum;
weidendo61453242009-07-01 23:56:23 +0000220 CLG_(push_cxt)(0);
weidendoa17f2a32006-03-20 10:27:30 +0000221}
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 */
228void 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
238void 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
weidendoafdb0112009-12-10 19:26:32 +0000246 /* thread switching potentially needed, eg. with instrumentation off */
247 CLG_(switch_thread)(tid);
weidendoa17f2a32006-03-20 10:27:30 +0000248 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 */
314void 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
324static exec_state* new_exec_state(Int sigNum)
325{
326 exec_state* es;
sewardj9c606bd2008-09-18 18:12:50 +0000327 es = (exec_state*) CLG_MALLOC("cl.threads.nes.1",
328 sizeof(exec_state));
weidendoa17f2a32006-03-20 10:27:30 +0000329
330 /* allocate real cost space: needed as incremented by
331 * simulation functions */
332 es->cost = CLG_(get_eventset_cost)(CLG_(sets).full);
weidendoe8914872009-08-11 20:53:59 +0000333 CLG_(zero_cost)( CLG_(sets).full, es->cost );
weidendoa17f2a32006-03-20 10:27:30 +0000334 CLG_(init_exec_state)(es);
335 es->sig = sigNum;
336 es->call_stack_bottom = 0;
337
338 return es;
339}
340
341void 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
352void 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
361void 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 */
372static
373exec_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 */
388static 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 */
410static
411exec_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;
weidendo61453242009-07-01 23:56:23 +0000420 CLG_ASSERT(es->cost == CLG_(current_state).cost);
weidendoa17f2a32006-03-20 10:27:30 +0000421
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);
weidendo09ee78e2009-02-24 12:26:53 +0000425 CLG_(print_bbcc)(-9, es->bbcc);
weidendoa17f2a32006-03-20 10:27:30 +0000426 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
435static
436exec_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);
weidendo09ee78e2009-02-24 12:26:53 +0000451 CLG_(print_bbcc)(-9, es->bbcc);
weidendoa17f2a32006-03-20 10:27:30 +0000452 CLG_(print_cxt)(-9, es->cxt, 0);
453 CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
454 }
455
456 return es;
457}
458