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