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