threads.c revision 4d474d086188fd1f29fa97dbd84d8ea2e589a9b8
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
103a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t = (thread_info*) CLG_MALLOC(sizeof(thread_info));
104a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
105a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* init state */
106a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_exec_stack)( &(t->states) );
107a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_call_stack)( &(t->calls) );
108a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_fn_stack)  ( &(t->fns) );
109a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* t->states.entry[0]->cxt = CLG_(get_cxt)(t->fns.bottom); */
110a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
111a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* event counters */
112a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t->lastdump_cost   = CLG_(get_eventset_cost)( CLG_(sets).full );
113a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t->sighandler_cost = CLG_(get_eventset_cost)( CLG_(sets).full );
114a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, t->lastdump_cost );
115a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, t->sighandler_cost );
116a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
117a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* init data containers */
118a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_fn_array)( &(t->fn_active) );
119a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_bbcc_hash)( &(t->bbccs) );
120a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_jcc_hash)( &(t->jccs) );
121a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
122a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    return t;
123a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
124a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
125a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
126a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(switch_thread)(ThreadId tid)
127a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
128a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (tid == CLG_(current_tid)) return;
129a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
130a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_DEBUG(0, ">> thread %d (was %d)\n", tid, CLG_(current_tid));
131a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
132a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (CLG_(current_tid) != VG_INVALID_THREADID) {
133a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* save thread state */
134a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    thread_info* t = thread[CLG_(current_tid)];
135a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
136a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(t != 0);
137a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
138a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* current context (including signal handler contexts) */
139a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_save();
140a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_exec_stack)( &(t->states) );
141a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_call_stack)( &(t->calls) );
142a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_fn_stack)  ( &(t->fns) );
143a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
144a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_fn_array) ( &(t->fn_active) );
145a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
146a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (!CLG_(clo).separate_threads) t = thread[1];
147a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_bbcc_hash)( &(t->bbccs) );
148a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(copy_current_jcc_hash) ( &(t->jccs) );
149a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
150a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
151a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_tid) = tid;
152a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT(tid < VG_N_THREADS);
153a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
154a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (tid != VG_INVALID_THREADID) {
155a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    thread_info* t;
156a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
157a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* load thread state */
158a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
159a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (thread[tid] == 0) thread[tid] = new_thread();
160a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    t = thread[tid];
161a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
162a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* current context (including signal handler contexts) */
163a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_exec_stack)( &(t->states) );
164a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_restore();
165a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_call_stack)( &(t->calls) );
166a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_fn_stack)  ( &(t->fns) );
167a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
168a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_fn_array)  ( &(t->fn_active) );
169a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* If we cumulate costs of threads, use TID 1 for all jccs/bccs */
170a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (!CLG_(clo).separate_threads) t = thread[1];
171a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_bbcc_hash) ( &(t->bbccs) );
172a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(set_current_jcc_hash)  ( &(t->jccs) );
173a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
174a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
175a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
176a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
177a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(run_thread)(ThreadId tid)
178a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
179a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* check for dumps needed */
180a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    static ULong bbs_done = 0;
181a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    static Char buf[512];
182a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
183a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(clo).dump_every_bb >0) {
184a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo       if (CLG_(stat).bb_executions - bbs_done > CLG_(clo).dump_every_bb) {
1859e326b7c9e06d22a868557b8606fc765a2cd6277weidendo           VG_(sprintf)(buf, "--dump-every-bb=%llu", CLG_(clo).dump_every_bb);
186a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	   CLG_(dump_profile)(buf, False);
187a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo           bbs_done = CLG_(stat).bb_executions;
188a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo       }
189a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    }
190a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
191a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(check_command)();
192a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
193a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* now check for thread switch */
194a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(switch_thread)(tid);
195a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
196a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
197a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(pre_signal)(ThreadId tid, Int sigNum, Bool alt_stack)
198a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
199a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state *es;
200a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
201a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_DEBUG(0, ">> pre_signal(TID %d, sig %d, alt_st %s)\n",
202a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	     tid, sigNum, alt_stack ? "yes":"no");
203a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
204a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* switch to the thread the handler runs in */
205a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(run_thread)(tid);
206a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
207a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* save current execution state */
208a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_save();
209a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
210a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* setup current state for a spontaneous call */
211a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_exec_state)( &CLG_(current_state) );
212a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(push_cxt)(0);
213a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
214a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* setup new cxtinfo struct for this signal handler */
215a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = push_exec_state(sigNum);
216a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, es->cost);
217a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_state).cost = es->cost;
218a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->call_stack_bottom = CLG_(current_call_stack).sp;
219a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
220a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_state).sig = sigNum;
221a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
222a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
223a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* Run post-signal if the stackpointer for call stack is at
224a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * the bottom in current exec state (e.g. a signal handler)
225a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo *
226a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * Called from CLG_(pop_call_stack)
227a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo */
228a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(run_post_signal_on_call_stack_bottom)()
229a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
230a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state* es = top_exec_state();
231a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(es != 0);
232a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(CLG_(current_state).sig >0);
233a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
234a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(current_call_stack).sp == es->call_stack_bottom)
235a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(post_signal)( CLG_(current_tid), CLG_(current_state).sig );
236a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
237a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
238a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(post_signal)(ThreadId tid, Int sigNum)
239a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
240a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state* es;
241a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    UInt fn_number, *pactive;
242a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
243a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_DEBUG(0, ">> post_signal(TID %d, sig %d)\n",
244a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	     tid, sigNum);
245a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
246a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(tid == CLG_(current_tid));
247a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(sigNum == CLG_(current_state).sig);
248a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
249a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* Unwind call stack of this signal handler.
250a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * This should only be needed at finalisation time
251a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     */
252a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = top_exec_state();
253a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(es != 0);
254a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    while(CLG_(current_call_stack).sp > es->call_stack_bottom)
255a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      CLG_(pop_call_stack)();
256a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
257a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(current_state).cxt) {
258a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      /* correct active counts */
259a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      fn_number = CLG_(current_state).cxt->fn[0]->number;
260a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      pactive = CLG_(get_fn_entry)(fn_number);
261a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      (*pactive)--;
262a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      CLG_DEBUG(0, "  set active count of %s back to %d\n",
263a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	       CLG_(current_state).cxt->fn[0]->name, *pactive);
264a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    }
265a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
266a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom) {
267a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	/* set fn_stack_top back.
268a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	 * top can point to 0 if nothing was executed in the signal handler;
269a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	 * this is possible at end on unwinding handlers.
270a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	 */
271a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	if (*(CLG_(current_fn_stack).top) != 0) {
272a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	    CLG_(current_fn_stack).top--;
273a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	    CLG_ASSERT(*(CLG_(current_fn_stack).top) == 0);
274a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	}
275a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo      if (CLG_(current_fn_stack).top > CLG_(current_fn_stack).bottom)
276a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(current_fn_stack).top--;
277a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    }
278a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
279a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* sum up costs */
280a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_ASSERT(CLG_(current_state).cost == es->cost);
281a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(add_and_zero_cost)( CLG_(sets).full,
282a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo			    thread[CLG_(current_tid)]->sighandler_cost,
283a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo			    CLG_(current_state).cost );
284a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
285a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* restore previous context */
286a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->sig = -1;
287a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    current_states.sp--;
288a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = top_exec_state();
289a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(current_state).sig = es->sig;
290a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state_restore();
291a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
292a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* There is no way to reliable get the thread ID we are switching to
293a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * after this handler returns. So we sync with actual TID at start of
294a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * CLG_(setup_bb)(), which should be the next for callgrind.
295a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     */
296a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
297a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
298a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
299a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
300a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*------------------------------------------------------------*/
301a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*--- Execution states in a thread & signal handlers       ---*/
302a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/*------------------------------------------------------------*/
303a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
304a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* Each thread can be interrupted by a signal handler, and they
305a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * themselves again. But as there's no scheduling among handlers
306a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * of the same thread, we don't need additional stacks.
307a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * So storing execution contexts and
308a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * adding separators in the callstack(needed to not intermix normal/handler
309a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * functions in contexts) should be enough.
310a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo */
311a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
312a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* not initialized: call_stack_bottom, sig */
313a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(init_exec_state)(exec_state* es)
314a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
315a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->collect = CLG_(clo).collect_atstart;
316a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->cxt  = 0;
317a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->jmps_passed = 0;
318a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->bbcc = 0;
319a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->nonskipped = 0;
320a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
321a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
322a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
323a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic exec_state* new_exec_state(Int sigNum)
324a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
325a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    exec_state* es;
326a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = (exec_state*) CLG_MALLOC(sizeof(exec_state));
327a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
328a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    /* allocate real cost space: needed as incremented by
329a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo     * simulation functions */
330a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->cost       = CLG_(get_eventset_cost)(CLG_(sets).full);
331a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_cost)( CLG_(sets).full, es->cost );
332a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
333a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(init_exec_state)(es);
334a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->sig        = sigNum;
335a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->call_stack_bottom  = 0;
336a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
337a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    return es;
338a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
339a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
340a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(init_exec_stack)(exec_stack* es)
341a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
342a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  Int i;
343a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
344a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  /* The first element is for the main thread */
345a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->entry[0] = new_exec_state(0);
346a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  for(i=1;i<MAX_SIGHANDLERS;i++)
347a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->entry[i] = 0;
348a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->sp = 0;
349a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
350a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
351a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(copy_current_exec_stack)(exec_stack* dst)
352a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
353a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  Int i;
354a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
355a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  dst->sp = current_states.sp;
356a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  for(i=0;i<MAX_SIGHANDLERS;i++)
357a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    dst->entry[i] = current_states.entry[i];
358a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
359a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
360a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendovoid CLG_(set_current_exec_stack)(exec_stack* dst)
361a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
362a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  Int i;
363a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
364a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  current_states.sp = dst->sp;
365a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  for(i=0;i<MAX_SIGHANDLERS;i++)
366a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    current_states.entry[i] = dst->entry[i];
367a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
368a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
369a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
370a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* Get top context info struct of current thread */
371a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic
372a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendoexec_state* top_exec_state(void)
373a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
374a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  Int sp = current_states.sp;
375a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  exec_state* es;
376a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
377a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT((sp >= 0) && (sp < MAX_SIGHANDLERS));
378a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es = current_states.entry[sp];
379a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT(es != 0);
380a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  return es;
381a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
382a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
383a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* Allocates a free context info structure for a new entered
384a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * signal handler, putting it on the context stack.
385a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo * Returns a pointer to the structure.
386a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo */
387a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic exec_state* push_exec_state(int sigNum)
388a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
389a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  Int sp;
390a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  exec_state* es;
391a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
392a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  current_states.sp++;
393a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  sp = current_states.sp;
394a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
395a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT((sigNum > 0) && (sigNum <= _VKI_NSIG));
396a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT((sp > 0) && (sp < MAX_SIGHANDLERS));
397a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es = current_states.entry[sp];
398a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  if (!es) {
399a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es = new_exec_state(sigNum);
400a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    current_states.entry[sp] = es;
401a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
402a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  else
403a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    es->sig = sigNum;
404a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
405a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  return es;
406a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
407a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
408a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo/* Save current context to top cxtinfo struct */
409a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic
410a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendoexec_state* exec_state_save(void)
411a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
412a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  exec_state* es = top_exec_state();
413a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
414a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->cxt         = CLG_(current_state).cxt;
415a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->collect     = CLG_(current_state).collect;
416a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->jmps_passed = CLG_(current_state).jmps_passed;
417a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->bbcc        = CLG_(current_state).bbcc;
418a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  es->nonskipped  = CLG_(current_state).nonskipped;
419a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
420a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_DEBUGIF(1) {
421a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_DEBUG(1, "  cxtinfo_save(sig %d): collect %s, jmps_passed %d\n",
422a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	     es->sig, es->collect ? "Yes": "No", es->jmps_passed);
423a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(print_bbcc)(-9, es->bbcc, False);
424a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo    CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
425a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
426a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
427a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  /* signal number does not need to be saved */
428a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_ASSERT(CLG_(current_state).sig == es->sig);
429a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
430a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  return es;
431a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
432a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
433a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendostatic
434a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendoexec_state* exec_state_restore(void)
435a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo{
436a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  exec_state* es = top_exec_state();
437a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
438a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).cxt     = es->cxt;
439a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).collect = es->collect;
440a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).jmps_passed = es->jmps_passed;
441a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).bbcc    = es->bbcc;
442a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).nonskipped = es->nonskipped;
443a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).cost    = es->cost;
444a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_(current_state).sig     = es->sig;
445a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
446a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  CLG_DEBUGIF(1) {
447a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_DEBUG(1, "  exec_state_restore(sig %d): collect %s, jmps_passed %d\n",
448a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo		  es->sig, es->collect ? "Yes": "No", es->jmps_passed);
449a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(print_bbcc)(-9, es->bbcc, False);
450a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(print_cxt)(-9, es->cxt, 0);
451a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo	CLG_(print_cost)(-9, CLG_(sets).full, es->cost);
452a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  }
453a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
454a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo  return es;
455a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo}
456a17f2a36b7fde9ee842f92412eacbf94b66af59dweidendo
457