blob: 3e63da14d656998d354207436ede4cea7b0bd767 [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
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 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"
43
44/*------------------------------------------------------------*/
45/*--- Types ---*/
46/*------------------------------------------------------------*/
47
48/*
49 Thread state machine:
50
51 Empty -> Init -> Runnable <=> WaitSys/Yielding
52 ^ |
53 \---- Zombie -----/
54 */
55typedef
56 enum ThreadStatus {
57 VgTs_Empty, /* this slot is not in use */
58 VgTs_Init, /* just allocated */
59 VgTs_Runnable, /* ready to run */
60 VgTs_WaitSys, /* waiting for a syscall to complete */
61 VgTs_Yielding, /* temporarily yielding the CPU */
62 VgTs_Zombie, /* transient state just before exiting */
63 }
64 ThreadStatus;
65
66/* Return codes from the scheduler. */
67typedef
68 enum {
69 VgSrc_None, /* not exiting yet */
sewardjd8a725e2006-10-17 02:01:12 +000070 VgSrc_ExitThread, /* just this thread is exiting */
71 VgSrc_ExitProcess, /* entire process is exiting */
njnc7561b92005-06-19 01:24:32 +000072 VgSrc_FatalSig /* Killed by the default action of a fatal
73 signal */
74 }
75 VgSchedReturnCode;
76
77
78#if defined(VGA_x86)
79 typedef VexGuestX86State VexGuestArchState;
80#elif defined(VGA_amd64)
81 typedef VexGuestAMD64State VexGuestArchState;
cerion85665ca2005-06-20 15:51:07 +000082#elif defined(VGA_ppc32)
83 typedef VexGuestPPC32State VexGuestArchState;
sewardj2c48c7b2005-11-29 13:05:56 +000084#elif defined(VGA_ppc64)
85 typedef VexGuestPPC64State VexGuestArchState;
sewardj59570ff2010-01-01 11:59:33 +000086#elif defined(VGA_arm)
87 typedef VexGuestARMState VexGuestArchState;
njnc7561b92005-06-19 01:24:32 +000088#else
89# error Unknown architecture
90#endif
91
njnf76d27a2009-05-28 01:53:07 +000092/* Forward declarations */
93struct SyscallStatus;
94struct SyscallArgs;
njnc7561b92005-06-19 01:24:32 +000095
sewardja4068de2006-04-05 23:06:31 +000096/* Architecture-specific thread state */
njnc7561b92005-06-19 01:24:32 +000097typedef
98 struct {
99 /* --- BEGIN vex-mandated guest state --- */
100
sewardj7cf4e6b2008-05-01 20:24:26 +0000101 /* Note that for code generation reasons, we require that the
102 guest state area, its two shadows, and the spill area, are
103 16-aligned and have 16-aligned sizes, and there are no holes
104 in between. This is checked by do_pre_run_checks() in
105 scheduler.c. */
njnc7561b92005-06-19 01:24:32 +0000106
sewardj7cf4e6b2008-05-01 20:24:26 +0000107 /* Saved machine context. */
108 VexGuestArchState vex __attribute__((aligned(16)));
109
110 /* Saved shadow context (2 copies). */
111 VexGuestArchState vex_shadow1 __attribute__((aligned(16)));
112 VexGuestArchState vex_shadow2 __attribute__((aligned(16)));
njnc7561b92005-06-19 01:24:32 +0000113
114 /* Spill area. */
sewardj7cf4e6b2008-05-01 20:24:26 +0000115 UChar vex_spill[LibVEX_N_SPILL_BYTES] __attribute__((aligned(16)));
njnc7561b92005-06-19 01:24:32 +0000116
117 /* --- END vex-mandated guest state --- */
118 }
119 ThreadArchState;
120
sewardja4068de2006-04-05 23:06:31 +0000121
njn99778ee2009-05-19 05:01:27 +0000122/* OS-specific thread state. IMPORTANT: if you add fields to this,
123 you _must_ add code to os_state_clear() to initialise those
124 fields. */
sewardja4068de2006-04-05 23:06:31 +0000125typedef
126 struct {
127 /* who we are */
njnf76d27a2009-05-28 01:53:07 +0000128 Int lwpid; // PID of kernel task (Darwin: Mach thread)
sewardja4068de2006-04-05 23:06:31 +0000129 Int threadgroup; // thread group id
njnc7561b92005-06-19 01:24:32 +0000130
sewardja4068de2006-04-05 23:06:31 +0000131 ThreadId parent; // parent tid (if any)
njnc7561b92005-06-19 01:24:32 +0000132
sewardja4068de2006-04-05 23:06:31 +0000133 /* runtime details */
134 Addr valgrind_stack_base; // Valgrind's stack (VgStack*)
135 Addr valgrind_stack_init_SP; // starting value for SP
njnc7561b92005-06-19 01:24:32 +0000136
sewardja4068de2006-04-05 23:06:31 +0000137 /* exit details */
sewardjd8a725e2006-10-17 02:01:12 +0000138 Word exitcode; // in the case of exitgroup, set by someone else
139 Int fatalsig; // fatal signal
140
141# if defined(VGO_aix5)
142 /* AIX specific fields to make thread cancellation sort-of work */
143 /* What is this thread's current cancellation state a la
144 POSIX (deferred vs async, enable vs disabled) ? */
145 Bool cancel_async; // current cancel mode (async vs deferred)
146 Bool cancel_disabled; // cancellation disabled?
147 /* What's happened so far? */
148 enum { Canc_NoRequest=0, // no cancellation requested
149 Canc_Requested=1, // requested but not actioned
150 Canc_Actioned=2 } // requested and actioned
151 cancel_progress;
152 /* Initial state is False, False, Canc_Normal. */
153# endif
njnf76d27a2009-05-28 01:53:07 +0000154
155# if defined(VGO_darwin)
156 // Mach trap POST handler as chosen by PRE
157 void (*post_mach_trap_fn)(ThreadId tid,
158 struct SyscallArgs *, struct SyscallStatus *);
159
160 // This thread's pthread
161 Addr pthread;
162
163 // Argument passed when thread started
164 Addr func_arg;
165
166 // Synchronization between child thread and parent thread's POST wrapper
167 semaphore_t child_go;
168 semaphore_t child_done;
169
170 // Workqueue re-entry
171 // (setjmp in PRE(workq_ops), longjmp in wqthread_hijack)
172 // DDD: JRS fixme: this comment is no longer correct; wq_jmpbuf is
173 // never used, and there is no such setjmp or longjmp pair.
174 // I guess we could leave wq_jmpbuf_valid in place though, since
175 // it does allow for an assertion in ML_(wqthread_continue_NORETURN).
176 Bool wq_jmpbuf_valid;
177 //jmp_buf wq_jmpbuf;
178
179 // Values saved from transient Mach RPC messages
180 Addr remote_port; // destination for original message
181 Int msgh_id; // outgoing message id
182 union {
183 struct {
184 Addr port;
185 } mach_port;
186 struct {
187 Int right;
188 } mach_port_allocate;
189 struct {
190 Addr port;
191 Int right;
192 Int delta;
193 } mach_port_mod_refs;
194 struct {
195 Addr task;
196 Addr name;
197 Int disposition;
198 } mach_port_insert_right;
199 struct {
200 Addr size;
201 int flags;
202 } vm_allocate;
203 struct {
204 Addr address;
205 Addr size;
206 } vm_deallocate;
207 struct {
208 Addr src;
209 Addr dst;
210 Addr size;
211 } vm_copy;
212 struct {
213 Addr address;
214 Addr size;
215 int set_maximum;
216 UWord new_protection;
217 } vm_protect;
218 struct {
219 Addr addr;
220 SizeT size;
221 } vm_read;
222 struct {
223 ULong addr;
224 ULong size;
225 } mach_vm_read;
226 struct {
227 Addr addr;
228 SizeT size;
229 Addr data;
230 } vm_read_overwrite;
231 struct {
232 Addr size;
233 int copy;
234 UWord protection;
235 } vm_map;
236 struct {
237 Addr size;
238 } vm_remap;
239 struct {
240 ULong size;
241 int flags;
242 } mach_vm_allocate;
243 struct {
244 ULong address;
245 ULong size;
246 } mach_vm_deallocate;
247 struct {
248 ULong address;
249 ULong size;
250 int set_maximum;
251 unsigned int new_protection;
252 } mach_vm_protect;
253 struct {
254 ULong size;
255 int copy;
256 UWord protection;
257 } mach_vm_map;
258 struct {
259 Addr thread;
260 UWord flavor;
261 } thread_get_state;
262 struct {
263 Addr address;
264 } io_connect_unmap_memory;
265 struct {
266 int which_port;
267 } task_get_special_port;
268 struct {
269 char *service_name;
270 } bootstrap_look_up;
271 struct {
272 vki_size_t size;
273 } WindowServer_29828;
274 struct {
275 Int access_rights;
276 } WindowServer_29831;
277 struct {
278 char *path;
279 } io_registry_entry_from_path;
280 } mach_args;
281# endif
282
sewardja4068de2006-04-05 23:06:31 +0000283 }
284 ThreadOSstate;
njnc7561b92005-06-19 01:24:32 +0000285
286
sewardja4068de2006-04-05 23:06:31 +0000287/* Overall thread state */
njnc7561b92005-06-19 01:24:32 +0000288typedef struct {
289 /* ThreadId == 0 (and hence vg_threads[0]) is NEVER USED.
290 The thread identity is simply the index in vg_threads[].
291 ThreadId == 1 is the root thread and has the special property
292 that we don't try and allocate or deallocate its stack. For
293 convenience of generating error message, we also put the
294 ThreadId in this tid field, but be aware that it should
295 ALWAYS == the index in vg_threads[]. */
296 ThreadId tid;
297
298 /* Current scheduling status. */
299 ThreadStatus status;
300
301 /* This is set if the thread is in the process of exiting for any
302 reason. The precise details of the exit are in the OS-specific
303 state. */
304 VgSchedReturnCode exitreason;
305
306 /* Architecture-specific thread state. */
307 ThreadArchState arch;
308
309 /* This thread's blocked-signals mask. Semantics is that for a
310 signal to be delivered to this thread, the signal must not be
311 blocked by this signal mask. If more than one thread accepts a
312 signal, then it will be delivered to one at random. If all
313 threads block the signal, it will remain pending until either a
314 thread unblocks it or someone uses sigwaitsig/sigtimedwait. */
315 vki_sigset_t sig_mask;
316
317 /* tmp_sig_mask is usually the same as sig_mask, and is kept in
318 sync whenever sig_mask is changed. The only time they have
319 different values is during the execution of a sigsuspend, where
320 tmp_sig_mask is the temporary mask which sigsuspend installs.
321 It is only consulted to compute the signal mask applied to a
322 signal handler. */
323 vki_sigset_t tmp_sig_mask;
324
325 /* A little signal queue for signals we can't get the kernel to
326 queue for us. This is only allocated as needed, since it should
327 be rare. */
328 struct SigQueue *sig_queue;
329
330 /* Client stacks. When a thread slot is freed, we don't deallocate its
331 stack; we just leave it lying around for the next use of the
332 slot. If the next use of the slot requires a larger stack,
333 only then is the old one deallocated and a new one
334 allocated.
335
sewardja4068de2006-04-05 23:06:31 +0000336 For the main thread (threadid == 1), this mechanism doesn't
njnc7561b92005-06-19 01:24:32 +0000337 apply. We don't know the size of the stack since we didn't
338 allocate it, and furthermore we never reallocate it. */
339
bart96a0de32008-03-29 09:25:11 +0000340 /* The allocated size of this thread's stack */
njnc7561b92005-06-19 01:24:32 +0000341 SizeT client_stack_szB;
342
343 /* Address of the highest legitimate word in this stack. This is
344 used for error messages only -- not critical for execution
345 correctness. Is is set for all stacks, specifically including
sewardja4068de2006-04-05 23:06:31 +0000346 ThreadId == 1 (the main thread). */
njnc7561b92005-06-19 01:24:32 +0000347 Addr client_stack_highest_word;
348
349 /* Alternate signal stack */
350 vki_stack_t altstack;
351
352 /* OS-specific thread state */
sewardja4068de2006-04-05 23:06:31 +0000353 ThreadOSstate os_state;
njnc7561b92005-06-19 01:24:32 +0000354
njnc7561b92005-06-19 01:24:32 +0000355 /* Per-thread jmp_buf to resume scheduler after a signal */
356 Bool sched_jmpbuf_valid;
357 jmp_buf sched_jmpbuf;
358}
359ThreadState;
360
361
362/*------------------------------------------------------------*/
363/*--- The thread table. ---*/
364/*------------------------------------------------------------*/
365
366/* A statically allocated array of threads. NOTE: [0] is
367 never used, to simplify the simulation of initialisers for
368 LinuxThreads. */
369extern ThreadState VG_(threads)[VG_N_THREADS];
370
371// The running thread. m_scheduler should be the only other module
372// to write to this.
373extern ThreadId VG_(running_tid);
374
njnf76d27a2009-05-28 01:53:07 +0000375
njnc7561b92005-06-19 01:24:32 +0000376/*------------------------------------------------------------*/
377/*--- Basic operations on the thread table. ---*/
378/*------------------------------------------------------------*/
379
380// Convert a ThreadStatus to a string.
381const HChar* VG_(name_of_ThreadStatus) ( ThreadStatus status );
382
383/* Get the ThreadState for a particular thread */
384extern ThreadState *VG_(get_ThreadState) ( ThreadId tid );
385
386/* Check that tid is in range and denotes a non-Empty thread. */
387extern Bool VG_(is_valid_tid) ( ThreadId tid );
388
389/* Returns true if a thread is currently running (ie, has the CPU lock) */
390extern Bool VG_(is_running_thread)(ThreadId tid);
391
392/* Returns true if the thread is in the process of exiting */
393extern Bool VG_(is_exiting)(ThreadId tid);
394
395/* Return the number of non-dead Threads */
396extern Int VG_(count_living_threads)(void);
397
sewardjd8a725e2006-10-17 02:01:12 +0000398/* Return the number of threads in VgTs_Runnable state */
399extern Int VG_(count_runnable_threads)(void);
400
njnc7561b92005-06-19 01:24:32 +0000401/* Given an LWP id (ie, real kernel thread id), find the corresponding
402 ThreadId */
sewardj42781722006-12-17 19:36:06 +0000403extern ThreadId VG_(lwpid_to_vgtid)(Int lwpid);
njnc7561b92005-06-19 01:24:32 +0000404
405#endif // __PUB_CORE_THREADSTATE_H
406
407/*--------------------------------------------------------------------*/
408/*--- end ---*/
409/*--------------------------------------------------------------------*/