• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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 
10    Copyright (C) 2000-2011 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 #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  */
55 typedef
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. */
67 typedef
68    enum {
69       VgSrc_None,	 /* not exiting yet */
70       VgSrc_ExitThread,  /* just this thread is exiting */
71       VgSrc_ExitProcess, /* entire process is exiting */
72       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;
82 #elif defined(VGA_ppc32)
83    typedef VexGuestPPC32State VexGuestArchState;
84 #elif defined(VGA_ppc64)
85    typedef VexGuestPPC64State VexGuestArchState;
86 #elif defined(VGA_arm)
87    typedef VexGuestARMState   VexGuestArchState;
88 #elif defined(VGA_s390x)
89    typedef VexGuestS390XState VexGuestArchState;
90 #else
91 #  error Unknown architecture
92 #endif
93 
94 /* Forward declarations */
95 struct SyscallStatus;
96 struct SyscallArgs;
97 
98 /* Architecture-specific thread state */
99 typedef
100    struct {
101       /* --- BEGIN vex-mandated guest state --- */
102 
103       /* Note that for code generation reasons, we require that the
104          guest state area, its two shadows, and the spill area, are
105          16-aligned and have 16-aligned sizes, and there are no holes
106          in between.  This is checked by do_pre_run_checks() in
107          scheduler.c. */
108 
109       /* Saved machine context. */
110       VexGuestArchState vex __attribute__((aligned(16)));
111 
112       /* Saved shadow context (2 copies). */
113       VexGuestArchState vex_shadow1 __attribute__((aligned(16)));
114       VexGuestArchState vex_shadow2 __attribute__((aligned(16)));
115 
116       /* Spill area. */
117       UChar vex_spill[LibVEX_N_SPILL_BYTES] __attribute__((aligned(16)));
118 
119       /* --- END vex-mandated guest state --- */
120    }
121    ThreadArchState;
122 
123 
124 /* OS-specific thread state.  IMPORTANT: if you add fields to this,
125    you _must_ add code to os_state_clear() to initialise those
126    fields. */
127 typedef
128    struct {
129       /* who we are */
130       Int lwpid;        // PID of kernel task  (Darwin: Mach thread)
131       Int threadgroup;  // thread group id
132 
133       ThreadId parent;  // parent tid (if any)
134 
135       /* runtime details */
136       Addr valgrind_stack_base;    // Valgrind's stack (VgStack*)
137       Addr valgrind_stack_init_SP; // starting value for SP
138 
139       /* exit details */
140       Word exitcode; // in the case of exitgroup, set by someone else
141       Int  fatalsig; // fatal signal
142 
143 #     if defined(VGO_darwin)
144       // Mach trap POST handler as chosen by PRE
145       void (*post_mach_trap_fn)(ThreadId tid,
146                                 struct SyscallArgs *, struct SyscallStatus *);
147 
148       // This thread's pthread
149       Addr pthread;
150 
151       // Argument passed when thread started
152       Addr func_arg;
153 
154       // Synchronization between child thread and parent thread's POST wrapper
155       semaphore_t child_go;
156       semaphore_t child_done;
157 
158       // Workqueue re-entry
159       // (setjmp in PRE(workq_ops), longjmp in wqthread_hijack)
160       // DDD: JRS fixme: this comment is no longer correct; wq_jmpbuf is
161       // never used, and there is no such setjmp or longjmp pair.
162       // I guess we could leave wq_jmpbuf_valid in place though, since
163       // it does allow for an assertion in ML_(wqthread_continue_NORETURN).
164       Bool wq_jmpbuf_valid;
165       //jmp_buf wq_jmpbuf;
166 
167       // Values saved from transient Mach RPC messages
168       Addr remote_port;  // destination for original message
169       Int msgh_id;       // outgoing message id
170       union {
171          struct {
172             Addr port;
173          } mach_port;
174          struct {
175             Int right;
176          } mach_port_allocate;
177          struct {
178             Addr port;
179             Int right;
180             Int delta;
181          } mach_port_mod_refs;
182          struct {
183             Addr task;
184             Addr name;
185             Int disposition;
186          } mach_port_insert_right;
187          struct {
188             Addr size;
189             int flags;
190          } vm_allocate;
191          struct {
192             Addr address;
193             Addr size;
194          } vm_deallocate;
195          struct {
196             Addr src;
197             Addr dst;
198             Addr size;
199          } vm_copy;
200          struct {
201             Addr address;
202             Addr size;
203             int set_maximum;
204             UWord new_protection;
205          } vm_protect;
206          struct {
207             Addr addr;
208             SizeT size;
209          } vm_read;
210          struct {
211             ULong addr;
212             ULong size;
213          } mach_vm_read;
214          struct {
215             Addr addr;
216             SizeT size;
217             Addr data;
218          } vm_read_overwrite;
219          struct {
220             Addr size;
221             int copy;
222             UWord protection;
223          } vm_map;
224          struct {
225             Addr size;
226          } vm_remap;
227          struct {
228             ULong size;
229             int flags;
230          } mach_vm_allocate;
231          struct {
232             ULong address;
233             ULong size;
234          } mach_vm_deallocate;
235          struct {
236             ULong address;
237             ULong size;
238             int set_maximum;
239             unsigned int new_protection;
240          } mach_vm_protect;
241          struct {
242             ULong size;
243             int copy;
244             UWord protection;
245          } mach_vm_map;
246          struct {
247             Addr thread;
248             UWord flavor;
249          } thread_get_state;
250          struct {
251             Addr address;
252          } io_connect_unmap_memory;
253          struct {
254             int which_port;
255          } task_get_special_port;
256          struct {
257             char *service_name;
258          } bootstrap_look_up;
259          struct {
260             vki_size_t size;
261          } WindowServer_29828;
262          struct {
263             Int access_rights;
264          } WindowServer_29831;
265          struct {
266             char *path;
267          } io_registry_entry_from_path;
268       } mach_args;
269 #     endif
270 
271    }
272    ThreadOSstate;
273 
274 
275 /* Overall thread state */
276 typedef struct {
277    /* ThreadId == 0 (and hence vg_threads[0]) is NEVER USED.
278       The thread identity is simply the index in vg_threads[].
279       ThreadId == 1 is the root thread and has the special property
280       that we don't try and allocate or deallocate its stack.  For
281       convenience of generating error message, we also put the
282       ThreadId in this tid field, but be aware that it should
283       ALWAYS == the index in vg_threads[]. */
284    ThreadId tid;
285 
286    /* Current scheduling status. */
287    ThreadStatus status;
288 
289    /* This is set if the thread is in the process of exiting for any
290       reason.  The precise details of the exit are in the OS-specific
291       state. */
292    VgSchedReturnCode exitreason;
293 
294    /* Architecture-specific thread state. */
295    ThreadArchState arch;
296 
297    /* This thread's blocked-signals mask.  Semantics is that for a
298       signal to be delivered to this thread, the signal must not be
299       blocked by this signal mask.  If more than one thread accepts a
300       signal, then it will be delivered to one at random.  If all
301       threads block the signal, it will remain pending until either a
302       thread unblocks it or someone uses sigwaitsig/sigtimedwait. */
303    vki_sigset_t sig_mask;
304 
305    /* tmp_sig_mask is usually the same as sig_mask, and is kept in
306       sync whenever sig_mask is changed.  The only time they have
307       different values is during the execution of a sigsuspend, where
308       tmp_sig_mask is the temporary mask which sigsuspend installs.
309       It is only consulted to compute the signal mask applied to a
310       signal handler. */
311    vki_sigset_t tmp_sig_mask;
312 
313    /* A little signal queue for signals we can't get the kernel to
314       queue for us.  This is only allocated as needed, since it should
315       be rare. */
316    struct SigQueue *sig_queue;
317 
318    /* Client stacks.  When a thread slot is freed, we don't deallocate its
319       stack; we just leave it lying around for the next use of the
320       slot.  If the next use of the slot requires a larger stack,
321       only then is the old one deallocated and a new one
322       allocated.
323 
324       For the main thread (threadid == 1), this mechanism doesn't
325       apply.  We don't know the size of the stack since we didn't
326       allocate it, and furthermore we never reallocate it. */
327 
328    /* The allocated size of this thread's stack */
329    SizeT client_stack_szB;
330 
331    /* Address of the highest legitimate word in this stack.  This is
332       used for error messages only -- not critical for execution
333       correctness.  Is is set for all stacks, specifically including
334       ThreadId == 1 (the main thread). */
335    Addr client_stack_highest_word;
336 
337    /* Alternate signal stack */
338    vki_stack_t altstack;
339 
340    /* OS-specific thread state */
341    ThreadOSstate os_state;
342 
343    /* Error disablement level.  A counter which allows selectively
344       disabling error reporting in threads.  When zero, reporting is
345       enabled.  When nonzero, it is disabled.  This is controlled by
346       the client request 'VG_USERREQ__CHANGE_ERR_DISABLEMENT'.  New
347       threads are always created with this as zero (errors
348       enabled). */
349    UInt err_disablement_level;
350 
351    /* Per-thread jmp_buf to resume scheduler after a signal */
352    Bool               sched_jmpbuf_valid;
353    VG_MINIMAL_JMP_BUF(sched_jmpbuf);
354 }
355 ThreadState;
356 
357 
358 /*------------------------------------------------------------*/
359 /*--- The thread table.                                    ---*/
360 /*------------------------------------------------------------*/
361 
362 /* A statically allocated array of threads.  NOTE: [0] is
363    never used, to simplify the simulation of initialisers for
364    LinuxThreads. */
365 extern ThreadState VG_(threads)[VG_N_THREADS];
366 
367 // The running thread.  m_scheduler should be the only other module
368 // to write to this.
369 extern ThreadId VG_(running_tid);
370 
371 
372 /*------------------------------------------------------------*/
373 /*--- Basic operations on the thread table.                ---*/
374 /*------------------------------------------------------------*/
375 
376 // Convert a ThreadStatus to a string.
377 const HChar* VG_(name_of_ThreadStatus) ( ThreadStatus status );
378 
379 /* Get the ThreadState for a particular thread */
380 extern ThreadState *VG_(get_ThreadState) ( ThreadId tid );
381 
382 /* Check that tid is in range and denotes a non-Empty thread. */
383 extern Bool VG_(is_valid_tid) ( ThreadId tid );
384 
385 /* Returns true if a thread is currently running (ie, has the CPU lock) */
386 extern Bool VG_(is_running_thread)(ThreadId tid);
387 
388 /* Returns true if the thread is in the process of exiting */
389 extern Bool VG_(is_exiting)(ThreadId tid);
390 
391 /* Return the number of non-dead Threads */
392 extern Int VG_(count_living_threads)(void);
393 
394 /* Return the number of threads in VgTs_Runnable state */
395 extern Int VG_(count_runnable_threads)(void);
396 
397 /* Given an LWP id (ie, real kernel thread id), find the corresponding
398    ThreadId */
399 extern ThreadId VG_(lwpid_to_vgtid)(Int lwpid);
400 
401 #endif   // __PUB_CORE_THREADSTATE_H
402 
403 /*--------------------------------------------------------------------*/
404 /*--- end                                                          ---*/
405 /*--------------------------------------------------------------------*/
406