threads.c revision 9c606bd8634cd6b67bb41fa645b5c639668cfa2d
1a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*--------------------------------------------------------------------*/
2a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*--- Callgrind                                                    ---*/
3a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*---                                                 ct_threads.c ---*/
4a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*--------------------------------------------------------------------*/
5a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
6a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*
7a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo   This file is part of Callgrind, a Valgrind tool for call tracing.
8a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
94d474d086188fd1f29fa97dbd84d8ea2e589a9b8sewardj   Copyright (C) 2002-2008, 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
31a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo#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
64a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic thread_info* thread[VG_N_THREADS];
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{
78a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    Int i;
79a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    for(i=0;i<VG_N_THREADS;i++)
80a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	thread[i] = 0;
81a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_tid) = VG_INVALID_THREADID;
82a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
83a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
84a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* switches through all threads and calls func */
85a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(forall_threads)(void (*func)(thread_info*))
86a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
87a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  Int t, orig_tid = CLG_(current_tid);
88a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
89a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  for(t=1;t<VG_N_THREADS;t++) {
90a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (!thread[t]) continue;
91a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(switch_thread)(t);
92a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    (*func)(thread[t]);
93a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
94a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(switch_thread)(orig_tid);
95a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
96a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
97a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
98a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic
99a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendothread_info* new_thread(void)
100a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
101a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    thread_info* t;
102a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
1039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj    t = (thread_info*) CLG_MALLOC("cl.threads.nt.1",
1049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                  sizeof(thread_info));
105a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
106a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* init state */
107a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_exec_stack)( &(t->states) );
108a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_call_stack)( &(t->calls) );
109a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_fn_stack)  ( &(t->fns) );
110a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* t->states.entry[0]->cxt = CLG_(get_cxt)(t->fns.bottom); */
111a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
112a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* event counters */
113a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t->lastdump_cost   = CLG_(get_eventset_cost)( CLG_(sets).full );
114a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t->sighandler_cost = CLG_(get_eventset_cost)( CLG_(sets).full );
115a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, t->lastdump_cost );
116a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, t->sighandler_cost );
117a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
118a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* init data containers */
119a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_fn_array)( &(t->fn_active) );
120a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_bbcc_hash)( &(t->bbccs) );
121a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_jcc_hash)( &(t->jccs) );
122a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
123a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    return t;
124a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
125a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
126a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
127a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(switch_thread)(ThreadId tid)
128a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
129a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (tid == CLG_(current_tid)) return;
130a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
131a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_DEBUG(0, ">> thread %d (was %d)\n", tid, CLG_(current_tid));
132a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
133a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (CLG_(current_tid) != VG_INVALID_THREADID) {
134a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* save thread state */
135a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    thread_info* t = thread[CLG_(current_tid)];
136a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
137a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(t != 0);
138a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
139a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* current context (including signal handler contexts) */
140a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_save();
141a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_exec_stack)( &(t->states) );
142a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_call_stack)( &(t->calls) );
143a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_fn_stack)  ( &(t->fns) );
144a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
145a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_fn_array) ( &(t->fn_active) );
146a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
147a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (!CLG_(clo).separate_threads) t = thread[1];
148a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_bbcc_hash)( &(t->bbccs) );
149a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_jcc_hash) ( &(t->jccs) );
150a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
151a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
152a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_tid) = tid;
153a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT(tid < VG_N_THREADS);
154a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
155a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (tid != VG_INVALID_THREADID) {
156a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    thread_info* t;
157a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
158a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* load thread state */
159a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
160a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (thread[tid] == 0) thread[tid] = new_thread();
161a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t = thread[tid];
162a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
163a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* current context (including signal handler contexts) */
164a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_exec_stack)( &(t->states) );
165a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_restore();
166a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_call_stack)( &(t->calls) );
167a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_fn_stack)  ( &(t->fns) );
168a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
169a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_fn_array)  ( &(t->fn_active) );
170a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
171a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (!CLG_(clo).separate_threads) t = thread[1];
172a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_bbcc_hash) ( &(t->bbccs) );
173a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_jcc_hash)  ( &(t->jccs) );
174a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
175a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
176a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
177a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
178a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(run_thread)(ThreadId tid)
179a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
180a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* check for dumps needed */
181a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    static ULong bbs_done = 0;
182a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    static Char buf[512];
183a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
184a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(clo).dump_every_bb >0) {
185a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo       if (CLG_(stat).bb_executions - bbs_done > CLG_(clo).dump_every_bb) {
1869e326b7c9e06d22a868557b8606fc765a2cd6277weidendo           VG_(sprintf)(buf, "--dump-every-bb=%llu", CLG_(clo).dump_every_bb);
187a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	   CLG_(dump_profile)(buf, False);
188a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo           bbs_done = CLG_(stat).bb_executions;
189a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo       }
190a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    }
191a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
192a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(check_command)();
193a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
194a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* now check for thread switch */
195a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(switch_thread)(tid);
196a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
197a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
198a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(pre_signal)(ThreadId tid, Int sigNum, Bool alt_stack)
199a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
200a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state *es;
201a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
202a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_DEBUG(0, ">> pre_signal(TID %d, sig %d, alt_st %s)\n",
203a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	     tid, sigNum, alt_stack ? "yes":"no");
204a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
205a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* switch to the thread the handler runs in */
206a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(run_thread)(tid);
207a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
208a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* save current execution state */
209a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_save();
210a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
211a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* setup current state for a spontaneous call */
212a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_exec_state)( &CLG_(current_state) );
213a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(push_cxt)(0);
214a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
215a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* setup new cxtinfo struct for this signal handler */
216a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = push_exec_state(sigNum);
217a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, es->cost);
218a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_state).cost = es->cost;
219a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->call_stack_bottom = CLG_(current_call_stack).sp;
220a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
221a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_state).sig = sigNum;
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
247a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(tid == CLG_(current_tid));
248a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(sigNum == CLG_(current_state).sig);
249a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
250a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* Unwind call stack of this signal handler.
251a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * This should only be needed at finalisation time
252a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     */
253a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = top_exec_state();
254a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(es != 0);
255a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    while(CLG_(current_call_stack).sp > es->call_stack_bottom)
256a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      CLG_(pop_call_stack)();
257a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
258a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(current_state).cxt) {
259a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      /* correct active counts */
260a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      fn_number = CLG_(current_state).cxt->fn[0]->number;
261a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      pactive = CLG_(get_fn_entry)(fn_number);
262a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      (*pactive)--;
263a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      CLG_DEBUG(0, "  set active count of %s back to %d\n",
264a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	       CLG_(current_state).cxt->fn[0]->name, *pactive);
265a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    }
266a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
267a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom) {
268a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	/* set fn_stack_top back.
269a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	 * top can point to 0 if nothing was executed in the signal handler;
270a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	 * this is possible at end on unwinding handlers.
271a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	 */
272a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	if (*(CLG_(current_fn_stack).top) != 0) {
273a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	    CLG_(current_fn_stack).top--;
274a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	    CLG_ASSERT(*(CLG_(current_fn_stack).top) == 0);
275a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	}
276a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom)
277a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(current_fn_stack).top--;
278a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    }
279a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
280a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* sum up costs */
281a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(CLG_(current_state).cost == es->cost);
282a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(add_and_zero_cost)( CLG_(sets).full,
283a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo			    thread[CLG_(current_tid)]->sighandler_cost,
284a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo			    CLG_(current_state).cost );
285a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
286a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* restore previous context */
287a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->sig = -1;
288a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    current_states.sp--;
289a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = top_exec_state();
290a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_state).sig = es->sig;
291a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_restore();
292a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
293a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* There is no way to reliable get the thread ID we are switching to
294a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * after this handler returns. So we sync with actual TID at start of
295a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * CLG_(setup_bb)(), which should be the next for callgrind.
296a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     */
297a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
298a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
299a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
300a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
301a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*------------------------------------------------------------*/
302a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*--- Execution states in a thread & signal handlers       ---*/
303a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*------------------------------------------------------------*/
304a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
305a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* Each thread can be interrupted by a signal handler, and they
306a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * themselves again. But as there's no scheduling among handlers
307a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * of the same thread, we don't need additional stacks.
308a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * So storing execution contexts and
309a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * adding separators in the callstack(needed to not intermix normal/handler
310a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * functions in contexts) should be enough.
311a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo */
312a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
313a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* not initialized: call_stack_bottom, sig */
314a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(init_exec_state)(exec_state* es)
315a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
316a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->collect = CLG_(clo).collect_atstart;
317a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->cxt  = 0;
318a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->jmps_passed = 0;
319a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->bbcc = 0;
320a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->nonskipped = 0;
321a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
322a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
323a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
324a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic exec_state* new_exec_state(Int sigNum)
325a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
326a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state* es;
3279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj    es = (exec_state*) CLG_MALLOC("cl.threads.nes.1",
3289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                  sizeof(exec_state));
329a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
330a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* allocate real cost space: needed as incremented by
331a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * simulation functions */
332a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->cost       = CLG_(get_eventset_cost)(CLG_(sets).full);
333a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, es->cost );
334a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
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;
421a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
422a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_DEBUGIF(1) {
423a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_DEBUG(1, "  cxtinfo_save(sig %d): collect %s, jmps_passed %d\n",
424a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	     es->sig, es->collect ? "Yes": "No", es->jmps_passed);
425a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(print_bbcc)(-9, es->bbcc, False);
426a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
427a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
428a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
429a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  /* signal number does not need to be saved */
430a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT(CLG_(current_state).sig == es->sig);
431a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
432a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  return es;
433a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
434a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
435a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic
436a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendoexec_state* exec_state_restore(void)
437a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
438a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  exec_state* es = top_exec_state();
439a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
440a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).cxt     = es->cxt;
441a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).collect = es->collect;
442a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).jmps_passed = es->jmps_passed;
443a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).bbcc    = es->bbcc;
444a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).nonskipped = es->nonskipped;
445a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).cost    = es->cost;
446a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).sig     = es->sig;
447a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
448a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_DEBUGIF(1) {
449a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_DEBUG(1, "  exec_state_restore(sig %d): collect %s, jmps_passed %d\n",
450a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo		  es->sig, es->collect ? "Yes": "No", es->jmps_passed);
451a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(print_bbcc)(-9, es->bbcc, False);
452a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(print_cxt)(-9, es->cxt, 0);
453a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
454a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
455a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
456a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  return es;
457a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
458a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
459