blob: 54dce4a58889bcd4367e7eda957b78b7efc41766 [file] [log] [blame]
njnc7561b92005-06-19 01:24:32 +00001
2/*--------------------------------------------------------------------*/
3/*--- The thread state. pub_core_threadstate.h ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj03f8d3f2012-08-05 15:46:46 +000010 Copyright (C) 2000-2012 Julian Seward
njnc7561b92005-06-19 01:24:32 +000011 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#ifndef __PUB_CORE_THREADSTATE_H
32#define __PUB_CORE_THREADSTATE_H
33
34//--------------------------------------------------------------------
35// PURPOSE: This module defines the ThreadState type and the
36// VG_(threads)[] data structure which holds all the important thread
37// state. It also defines some simple operations on the data structure
38// that don't require any external help. (m_scheduler does the complex
39// stuff).
40//--------------------------------------------------------------------
41
42#include "pub_tool_threadstate.h"
florianc91f5842013-09-15 10:42:26 +000043#include "pub_core_libcsetjmp.h" // VG_MINIMAL_JMP_BUF
florian535fb1b2013-09-15 13:54:34 +000044#include "pub_core_vki.h" // vki_sigset_t
njnc7561b92005-06-19 01:24:32 +000045
46/*------------------------------------------------------------*/
47/*--- Types ---*/
48/*------------------------------------------------------------*/
49
50/*
51 Thread state machine:
52
53 Empty -> Init -> Runnable <=> WaitSys/Yielding
54 ^ |
55 \---- Zombie -----/
56 */
57typedef
58 enum ThreadStatus {
59 VgTs_Empty, /* this slot is not in use */
60 VgTs_Init, /* just allocated */
61 VgTs_Runnable, /* ready to run */
62 VgTs_WaitSys, /* waiting for a syscall to complete */
63 VgTs_Yielding, /* temporarily yielding the CPU */
64 VgTs_Zombie, /* transient state just before exiting */
65 }
66 ThreadStatus;
67
68/* Return codes from the scheduler. */
69typedef
70 enum {
71 VgSrc_None, /* not exiting yet */
sewardjd8a725e2006-10-17 02:01:12 +000072 VgSrc_ExitThread, /* just this thread is exiting */
73 VgSrc_ExitProcess, /* entire process is exiting */
njnc7561b92005-06-19 01:24:32 +000074 VgSrc_FatalSig /* Killed by the default action of a fatal
75 signal */
76 }
77 VgSchedReturnCode;
78
79
80#if defined(VGA_x86)
81 typedef VexGuestX86State VexGuestArchState;
82#elif defined(VGA_amd64)
83 typedef VexGuestAMD64State VexGuestArchState;
cerion85665ca2005-06-20 15:51:07 +000084#elif defined(VGA_ppc32)
85 typedef VexGuestPPC32State VexGuestArchState;
sewardj2c48c7b2005-11-29 13:05:56 +000086#elif defined(VGA_ppc64)
87 typedef VexGuestPPC64State VexGuestArchState;
sewardj59570ff2010-01-01 11:59:33 +000088#elif defined(VGA_arm)
89 typedef VexGuestARMState VexGuestArchState;
sewardjb5b87402011-03-07 16:05:35 +000090#elif defined(VGA_s390x)
91 typedef VexGuestS390XState VexGuestArchState;
sewardj5db15402012-06-07 09:13:21 +000092#elif defined(VGA_mips32)
93 typedef VexGuestMIPS32State VexGuestArchState;
petarj4df0bfc2013-02-27 23:17:33 +000094#elif defined(VGA_mips64)
95 typedef VexGuestMIPS64State VexGuestArchState;
njnc7561b92005-06-19 01:24:32 +000096#else
97# error Unknown architecture
98#endif
99
njnf76d27a2009-05-28 01:53:07 +0000100/* Forward declarations */
101struct SyscallStatus;
102struct SyscallArgs;
njnc7561b92005-06-19 01:24:32 +0000103
sewardja4068de2006-04-05 23:06:31 +0000104/* Architecture-specific thread state */
njnc7561b92005-06-19 01:24:32 +0000105typedef
106 struct {
107 /* --- BEGIN vex-mandated guest state --- */
108
sewardj7cf4e6b2008-05-01 20:24:26 +0000109 /* Note that for code generation reasons, we require that the
110 guest state area, its two shadows, and the spill area, are
sewardj02e97e92012-08-02 22:08:53 +0000111 16-aligned and have 16-aligned sizes, and there are no holes
sewardj7cf4e6b2008-05-01 20:24:26 +0000112 in between. This is checked by do_pre_run_checks() in
113 scheduler.c. */
njnc7561b92005-06-19 01:24:32 +0000114
sewardj7cf4e6b2008-05-01 20:24:26 +0000115 /* Saved machine context. */
sewardj02e97e92012-08-02 22:08:53 +0000116 VexGuestArchState vex __attribute__((aligned(16)));
sewardj7cf4e6b2008-05-01 20:24:26 +0000117
118 /* Saved shadow context (2 copies). */
sewardj02e97e92012-08-02 22:08:53 +0000119 VexGuestArchState vex_shadow1 __attribute__((aligned(16)));
120 VexGuestArchState vex_shadow2 __attribute__((aligned(16)));
njnc7561b92005-06-19 01:24:32 +0000121
122 /* Spill area. */
sewardj02e97e92012-08-02 22:08:53 +0000123 UChar vex_spill[LibVEX_N_SPILL_BYTES] __attribute__((aligned(16)));
njnc7561b92005-06-19 01:24:32 +0000124
125 /* --- END vex-mandated guest state --- */
126 }
127 ThreadArchState;
128
sewardja4068de2006-04-05 23:06:31 +0000129
njn99778ee2009-05-19 05:01:27 +0000130/* OS-specific thread state. IMPORTANT: if you add fields to this,
131 you _must_ add code to os_state_clear() to initialise those
132 fields. */
sewardja4068de2006-04-05 23:06:31 +0000133typedef
134 struct {
135 /* who we are */
njnf76d27a2009-05-28 01:53:07 +0000136 Int lwpid; // PID of kernel task (Darwin: Mach thread)
sewardja4068de2006-04-05 23:06:31 +0000137 Int threadgroup; // thread group id
njnc7561b92005-06-19 01:24:32 +0000138
sewardja4068de2006-04-05 23:06:31 +0000139 ThreadId parent; // parent tid (if any)
njnc7561b92005-06-19 01:24:32 +0000140
sewardja4068de2006-04-05 23:06:31 +0000141 /* runtime details */
142 Addr valgrind_stack_base; // Valgrind's stack (VgStack*)
143 Addr valgrind_stack_init_SP; // starting value for SP
njnc7561b92005-06-19 01:24:32 +0000144
sewardja4068de2006-04-05 23:06:31 +0000145 /* exit details */
sewardjd8a725e2006-10-17 02:01:12 +0000146 Word exitcode; // in the case of exitgroup, set by someone else
147 Int fatalsig; // fatal signal
148
njnf76d27a2009-05-28 01:53:07 +0000149# if defined(VGO_darwin)
150 // Mach trap POST handler as chosen by PRE
151 void (*post_mach_trap_fn)(ThreadId tid,
152 struct SyscallArgs *, struct SyscallStatus *);
153
154 // This thread's pthread
155 Addr pthread;
156
157 // Argument passed when thread started
158 Addr func_arg;
159
160 // Synchronization between child thread and parent thread's POST wrapper
161 semaphore_t child_go;
162 semaphore_t child_done;
163
164 // Workqueue re-entry
165 // (setjmp in PRE(workq_ops), longjmp in wqthread_hijack)
166 // DDD: JRS fixme: this comment is no longer correct; wq_jmpbuf is
167 // never used, and there is no such setjmp or longjmp pair.
168 // I guess we could leave wq_jmpbuf_valid in place though, since
169 // it does allow for an assertion in ML_(wqthread_continue_NORETURN).
170 Bool wq_jmpbuf_valid;
171 //jmp_buf wq_jmpbuf;
172
173 // Values saved from transient Mach RPC messages
174 Addr remote_port; // destination for original message
175 Int msgh_id; // outgoing message id
176 union {
177 struct {
178 Addr port;
179 } mach_port;
180 struct {
181 Int right;
182 } mach_port_allocate;
183 struct {
184 Addr port;
185 Int right;
186 Int delta;
187 } mach_port_mod_refs;
188 struct {
189 Addr task;
190 Addr name;
191 Int disposition;
192 } mach_port_insert_right;
193 struct {
194 Addr size;
195 int flags;
196 } vm_allocate;
197 struct {
198 Addr address;
199 Addr size;
200 } vm_deallocate;
201 struct {
202 Addr src;
203 Addr dst;
204 Addr size;
205 } vm_copy;
206 struct {
207 Addr address;
208 Addr size;
209 int set_maximum;
210 UWord new_protection;
211 } vm_protect;
212 struct {
213 Addr addr;
214 SizeT size;
215 } vm_read;
216 struct {
217 ULong addr;
218 ULong size;
219 } mach_vm_read;
220 struct {
221 Addr addr;
222 SizeT size;
223 Addr data;
224 } vm_read_overwrite;
225 struct {
226 Addr size;
227 int copy;
228 UWord protection;
229 } vm_map;
230 struct {
231 Addr size;
232 } vm_remap;
233 struct {
234 ULong size;
235 int flags;
236 } mach_vm_allocate;
237 struct {
238 ULong address;
239 ULong size;
240 } mach_vm_deallocate;
241 struct {
242 ULong address;
243 ULong size;
244 int set_maximum;
245 unsigned int new_protection;
246 } mach_vm_protect;
247 struct {
248 ULong size;
249 int copy;
250 UWord protection;
251 } mach_vm_map;
252 struct {
253 Addr thread;
254 UWord flavor;
255 } thread_get_state;
256 struct {
257 Addr address;
258 } io_connect_unmap_memory;
259 struct {
260 int which_port;
261 } task_get_special_port;
262 struct {
263 char *service_name;
264 } bootstrap_look_up;
265 struct {
266 vki_size_t size;
267 } WindowServer_29828;
268 struct {
269 Int access_rights;
270 } WindowServer_29831;
271 struct {
272 char *path;
273 } io_registry_entry_from_path;
274 } mach_args;
275# endif
276
sewardja4068de2006-04-05 23:06:31 +0000277 }
278 ThreadOSstate;
njnc7561b92005-06-19 01:24:32 +0000279
280
sewardja4068de2006-04-05 23:06:31 +0000281/* Overall thread state */
njnc7561b92005-06-19 01:24:32 +0000282typedef struct {
283 /* ThreadId == 0 (and hence vg_threads[0]) is NEVER USED.
284 The thread identity is simply the index in vg_threads[].
285 ThreadId == 1 is the root thread and has the special property
286 that we don't try and allocate or deallocate its stack. For
287 convenience of generating error message, we also put the
288 ThreadId in this tid field, but be aware that it should
289 ALWAYS == the index in vg_threads[]. */
290 ThreadId tid;
291
292 /* Current scheduling status. */
293 ThreadStatus status;
294
295 /* This is set if the thread is in the process of exiting for any
296 reason. The precise details of the exit are in the OS-specific
297 state. */
298 VgSchedReturnCode exitreason;
299
300 /* Architecture-specific thread state. */
301 ThreadArchState arch;
302
303 /* This thread's blocked-signals mask. Semantics is that for a
304 signal to be delivered to this thread, the signal must not be
305 blocked by this signal mask. If more than one thread accepts a
306 signal, then it will be delivered to one at random. If all
307 threads block the signal, it will remain pending until either a
308 thread unblocks it or someone uses sigwaitsig/sigtimedwait. */
309 vki_sigset_t sig_mask;
310
311 /* tmp_sig_mask is usually the same as sig_mask, and is kept in
312 sync whenever sig_mask is changed. The only time they have
313 different values is during the execution of a sigsuspend, where
314 tmp_sig_mask is the temporary mask which sigsuspend installs.
315 It is only consulted to compute the signal mask applied to a
316 signal handler. */
317 vki_sigset_t tmp_sig_mask;
318
319 /* A little signal queue for signals we can't get the kernel to
320 queue for us. This is only allocated as needed, since it should
321 be rare. */
322 struct SigQueue *sig_queue;
323
324 /* Client stacks. When a thread slot is freed, we don't deallocate its
325 stack; we just leave it lying around for the next use of the
326 slot. If the next use of the slot requires a larger stack,
327 only then is the old one deallocated and a new one
328 allocated.
329
sewardja4068de2006-04-05 23:06:31 +0000330 For the main thread (threadid == 1), this mechanism doesn't
njnc7561b92005-06-19 01:24:32 +0000331 apply. We don't know the size of the stack since we didn't
332 allocate it, and furthermore we never reallocate it. */
333
bart96a0de32008-03-29 09:25:11 +0000334 /* The allocated size of this thread's stack */
njnc7561b92005-06-19 01:24:32 +0000335 SizeT client_stack_szB;
336
337 /* Address of the highest legitimate word in this stack. This is
338 used for error messages only -- not critical for execution
339 correctness. Is is set for all stacks, specifically including
sewardja4068de2006-04-05 23:06:31 +0000340 ThreadId == 1 (the main thread). */
njnc7561b92005-06-19 01:24:32 +0000341 Addr client_stack_highest_word;
342
343 /* Alternate signal stack */
344 vki_stack_t altstack;
345
346 /* OS-specific thread state */
sewardja4068de2006-04-05 23:06:31 +0000347 ThreadOSstate os_state;
njnc7561b92005-06-19 01:24:32 +0000348
sewardjdc873c02011-07-24 16:02:33 +0000349 /* Error disablement level. A counter which allows selectively
350 disabling error reporting in threads. When zero, reporting is
351 enabled. When nonzero, it is disabled. This is controlled by
352 the client request 'VG_USERREQ__CHANGE_ERR_DISABLEMENT'. New
353 threads are always created with this as zero (errors
354 enabled). */
355 UInt err_disablement_level;
356
njnc7561b92005-06-19 01:24:32 +0000357 /* Per-thread jmp_buf to resume scheduler after a signal */
sewardj6c591e12011-04-11 16:17:51 +0000358 Bool sched_jmpbuf_valid;
sewardj97d3ebb2011-04-11 18:36:34 +0000359 VG_MINIMAL_JMP_BUF(sched_jmpbuf);
njnc7561b92005-06-19 01:24:32 +0000360}
361ThreadState;
362
363
364/*------------------------------------------------------------*/
365/*--- The thread table. ---*/
366/*------------------------------------------------------------*/
367
368/* A statically allocated array of threads. NOTE: [0] is
369 never used, to simplify the simulation of initialisers for
370 LinuxThreads. */
371extern ThreadState VG_(threads)[VG_N_THREADS];
372
373// The running thread. m_scheduler should be the only other module
374// to write to this.
375extern ThreadId VG_(running_tid);
376
njnf76d27a2009-05-28 01:53:07 +0000377
njnc7561b92005-06-19 01:24:32 +0000378/*------------------------------------------------------------*/
379/*--- Basic operations on the thread table. ---*/
380/*------------------------------------------------------------*/
381
bart27233e92012-03-08 14:59:25 +0000382/* Initialize the m_threadstate module. */
383void VG_(init_Threads)(void);
384
njnc7561b92005-06-19 01:24:32 +0000385// Convert a ThreadStatus to a string.
386const HChar* VG_(name_of_ThreadStatus) ( ThreadStatus status );
387
388/* Get the ThreadState for a particular thread */
389extern ThreadState *VG_(get_ThreadState) ( ThreadId tid );
390
391/* Check that tid is in range and denotes a non-Empty thread. */
392extern Bool VG_(is_valid_tid) ( ThreadId tid );
393
394/* Returns true if a thread is currently running (ie, has the CPU lock) */
395extern Bool VG_(is_running_thread)(ThreadId tid);
396
397/* Returns true if the thread is in the process of exiting */
398extern Bool VG_(is_exiting)(ThreadId tid);
399
400/* Return the number of non-dead Threads */
401extern Int VG_(count_living_threads)(void);
402
sewardjd8a725e2006-10-17 02:01:12 +0000403/* Return the number of threads in VgTs_Runnable state */
404extern Int VG_(count_runnable_threads)(void);
405
njnc7561b92005-06-19 01:24:32 +0000406/* Given an LWP id (ie, real kernel thread id), find the corresponding
407 ThreadId */
sewardj42781722006-12-17 19:36:06 +0000408extern ThreadId VG_(lwpid_to_vgtid)(Int lwpid);
njnc7561b92005-06-19 01:24:32 +0000409
410#endif // __PUB_CORE_THREADSTATE_H
411
412/*--------------------------------------------------------------------*/
413/*--- end ---*/
414/*--------------------------------------------------------------------*/