• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  
2  /*--------------------------------------------------------------------*/
3  /*--- The thread state.                            m_threadstate.c ---*/
4  /*--------------------------------------------------------------------*/
5  
6  /*
7     This file is part of Valgrind, a dynamic binary instrumentation
8     framework.
9  
10     Copyright (C) 2000-2015 Julian Seward
11        jseward@acm.org
12  
13     This program is free software; you can redistribute it and/or
14     modify it under the terms of the GNU General Public License as
15     published by the Free Software Foundation; either version 2 of the
16     License, or (at your option) any later version.
17  
18     This program is distributed in the hope that it will be useful, but
19     WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21     General Public License for more details.
22  
23     You should have received a copy of the GNU General Public License
24     along with this program; if not, write to the Free Software
25     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26     02111-1307, USA.
27  
28     The GNU General Public License is contained in the file COPYING.
29  */
30  
31  #include "pub_core_basics.h"
32  #include "pub_core_vki.h"
33  #include "pub_core_threadstate.h"
34  #include "pub_core_mallocfree.h"    // VG_(malloc)
35  #include "pub_core_libcassert.h"
36  #include "pub_core_inner.h"
37  #if defined(ENABLE_INNER_CLIENT_REQUEST)
38  #include "helgrind/helgrind.h"
39  #endif
40  
41  /*------------------------------------------------------------*/
42  /*--- Data structures.                                     ---*/
43  /*------------------------------------------------------------*/
44  
45  ThreadId VG_(running_tid) = VG_INVALID_THREADID;
46  
47  ThreadState *VG_(threads);
48  UInt VG_N_THREADS;
49  
50  /*------------------------------------------------------------*/
51  /*--- Operations.                                          ---*/
52  /*------------------------------------------------------------*/
53  
VG_(init_Threads)54  void VG_(init_Threads)(void)
55  {
56     ThreadId tid;
57  
58     VG_(threads) = VG_(arena_memalign) (VG_AR_CORE, "init_Threads",
59                                         LibVEX_GUEST_STATE_ALIGN,
60                                         VG_N_THREADS * sizeof VG_(threads)[0]);
61  
62     for (tid = 1; tid < VG_N_THREADS; tid++) {
63        INNER_REQUEST(
64           ANNOTATE_BENIGN_RACE_SIZED(&VG_(threads)[tid].status,
65                                      sizeof(VG_(threads)[tid].status), ""));
66        INNER_REQUEST(
67           ANNOTATE_BENIGN_RACE_SIZED(&VG_(threads)[tid].os_state.exitcode,
68                                      sizeof(VG_(threads)[tid].os_state.exitcode),
69                                      ""));
70     }
71  }
72  
VG_(name_of_ThreadStatus)73  const HChar* VG_(name_of_ThreadStatus) ( ThreadStatus status )
74  {
75     switch (status) {
76     case VgTs_Empty:     return "VgTs_Empty";
77     case VgTs_Init:      return "VgTs_Init";
78     case VgTs_Runnable:  return "VgTs_Runnable";
79     case VgTs_WaitSys:   return "VgTs_WaitSys";
80     case VgTs_Yielding:  return "VgTs_Yielding";
81     case VgTs_Zombie:    return "VgTs_Zombie";
82     default:             return "VgTs_???";
83    }
84  }
85  
VG_(name_of_VgSchedReturnCode)86  const HChar* VG_(name_of_VgSchedReturnCode) ( VgSchedReturnCode retcode )
87  {
88     switch (retcode) {
89     case VgSrc_None:        return "VgSrc_None";
90     case VgSrc_ExitThread:  return "VgSrc_ExitThread";
91     case VgSrc_ExitProcess: return "VgSrc_ExitProcess";
92     case VgSrc_FatalSig:    return "VgSrc_FatalSig";
93     default:                return "VgSrc_???";
94    }
95  }
96  
VG_(get_ThreadState)97  ThreadState *VG_(get_ThreadState)(ThreadId tid)
98  {
99     vg_assert(tid >= 0 && tid < VG_N_THREADS);
100     vg_assert(VG_(threads)[tid].tid == tid);
101     return &VG_(threads)[tid];
102  }
103  
VG_(is_valid_tid)104  Bool VG_(is_valid_tid) ( ThreadId tid )
105  {
106     /* tid is unsigned, hence no < 0 test. */
107     if (tid == 0) return False;
108     if (tid >= VG_N_THREADS) return False;
109     if (VG_(threads)[tid].status == VgTs_Empty) return False;
110     return True;
111  }
112  
113  // This function is for tools to call.
VG_(get_running_tid)114  ThreadId VG_(get_running_tid)(void)
115  {
116     return VG_(running_tid);
117  }
118  
VG_(is_running_thread)119  Bool VG_(is_running_thread)(ThreadId tid)
120  {
121     ThreadState *tst = VG_(get_ThreadState)(tid);
122  
123     return
124  //      tst->os_state.lwpid == VG_(gettid)() &&	// check we're this tid
125        VG_(running_tid) == tid	           &&	// and that we've got the lock
126        tst->status == VgTs_Runnable;		// and we're runnable
127  }
128  
129  /* Return true if the thread is still alive but in the process of exiting. */
VG_(is_exiting)130  inline Bool VG_(is_exiting)(ThreadId tid)
131  {
132     vg_assert(VG_(is_valid_tid)(tid));
133     return VG_(threads)[tid].exitreason != VgSrc_None;
134  }
135  
136  /* Return the number of non-dead Threads */
VG_(count_living_threads)137  Int VG_(count_living_threads)(void)
138  {
139     Int count = 0;
140     ThreadId tid;
141  
142     for(tid = 1; tid < VG_N_THREADS; tid++)
143        if (VG_(threads)[tid].status != VgTs_Empty &&
144  	  VG_(threads)[tid].status != VgTs_Zombie)
145  	 count++;
146  
147     return count;
148  }
149  
150  /* Return the number of threads in VgTs_Runnable state */
VG_(count_runnable_threads)151  Int VG_(count_runnable_threads)(void)
152  {
153     Int count = 0;
154     ThreadId tid;
155  
156     for(tid = 1; tid < VG_N_THREADS; tid++)
157        if (VG_(threads)[tid].status == VgTs_Runnable)
158  	 count++;
159  
160     return count;
161  }
162  
163  /* Given an LWP id (ie, real kernel thread id), find the corresponding
164     ThreadId */
VG_(lwpid_to_vgtid)165  ThreadId VG_(lwpid_to_vgtid)(Int lwp)
166  {
167     ThreadId tid;
168  
169     for(tid = 1; tid < VG_N_THREADS; tid++)
170        if (VG_(threads)[tid].status != VgTs_Empty
171            && VG_(threads)[tid].os_state.lwpid == lwp)
172  	 return tid;
173  
174     return VG_INVALID_THREADID;
175  }
176  
177  /*--------------------------------------------------------------------*/
178  /*--- end                                                          ---*/
179  /*--------------------------------------------------------------------*/
180