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