coregrind/m_demangle/Makefile
coregrind/m_dispatch/Makefile
coregrind/m_replacemalloc/Makefile
+ coregrind/m_scheduler/Makefile
coregrind/m_sigframe/Makefile
coregrind/m_syscalls/Makefile
coregrind/amd64/Makefile
m_demangle \
m_dispatch \
m_replacemalloc \
+ m_scheduler \
m_sigframe \
m_syscalls
pub_core_options.h \
pub_core_redir.h \
pub_core_replacemalloc.h\
+ pub_core_scheduler.h \
pub_core_sigframe.h \
pub_core_skiplist.h \
pub_core_stacktrace.h \
m_transtab.c \
ume.c \
\
- vg_scheduler.c \
vg_main.c \
vg_messages.c \
vg_mylibc.c \
vg_stabs.c \
vg_symtypes.c
+## Nb: libscheduler.a must precede libdispatch.a in this list.
stage2_extra= \
+ m_scheduler/libscheduler.a \
m_dispatch/libdispatch.a \
m_demangle/libdemangle.a \
m_aspacemgr/libaspacemgr.a \
#include "core_os.h" // OS-specific stuff, eg. linux/core_os.h
+#include <setjmp.h> // for jmp_buf
+
#include "pub_core_mallocfree.h" // for type 'ArenaId'
+#include "pub_core_scheduler.h" // for types 'ThreadState', 'ThreadArchState'
#include "pub_core_stacktrace.h" // for type 'StackTrace'
-#include <setjmp.h> /* for jmp_buf */
-
/* ---------------------------------------------------------------------
Global macros.
------------------------------------------------------------------ */
#define VG_WRAPPER_ALIAS(name) "_vgw_" #name
-/* ---------------------------------------------------------------------
- Exports of vg_scheduler.c
- ------------------------------------------------------------------ */
-
-/*
- Thread state machine:
-
- Empty -> Init -> Runnable <=> WaitSys/Yielding
- ^ |
- \---- Zombie -----/
- */
-typedef
- enum ThreadStatus {
- VgTs_Empty, /* this slot is not in use */
- VgTs_Init, /* just allocated */
- VgTs_Runnable, /* ready to run */
- VgTs_WaitSys, /* waiting for a syscall to complete */
- VgTs_Yielding, /* temporarily yielding the CPU */
- VgTs_Zombie, /* transient state just before exiting */
- }
- ThreadStatus;
-
-/* Return codes from the scheduler. */
-typedef
- enum {
- VgSrc_None, /* not exiting yet */
- VgSrc_ExitSyscall, /* client called exit(). This is the normal
- route out. */
- VgSrc_FatalSig /* Killed by the default action of a fatal
- signal */
- }
- VgSchedReturnCode;
-
-
-#if defined(VGA_x86)
- typedef VexGuestX86State VexGuestArchState;
-#elif defined(VGA_amd64)
- typedef VexGuestAMD64State VexGuestArchState;
-#elif defined(VGA_arm)
- typedef VexGuestARMState VexGuestArchState;
-#else
-# error Unknown architecture
-#endif
-
-
-typedef
- struct {
- /* --- BEGIN vex-mandated guest state --- */
-
- /* Saved machine context. */
- VexGuestArchState vex;
-
- /* Saved shadow context. */
- VexGuestArchState vex_shadow;
-
- /* Spill area. */
- UChar vex_spill[LibVEX_N_SPILL_BYTES];
-
- /* --- END vex-mandated guest state --- */
- }
- ThreadArchState;
-
-
-typedef struct {
- /* ThreadId == 0 (and hence vg_threads[0]) is NEVER USED.
- The thread identity is simply the index in vg_threads[].
- ThreadId == 1 is the root thread and has the special property
- that we don't try and allocate or deallocate its stack. For
- convenience of generating error message, we also put the
- ThreadId in this tid field, but be aware that it should
- ALWAYS == the index in vg_threads[]. */
- ThreadId tid;
-
- /* Current scheduling status. */
- ThreadStatus status;
-
- /* This is set if the thread is in the process of exiting for any
- reason. The precise details of the exit are in the OS-specific
- state. */
- VgSchedReturnCode exitreason;
-
- /* Architecture-specific thread state. */
- ThreadArchState arch;
-
- /* This thread's blocked-signals mask. Semantics is that for a
- signal to be delivered to this thread, the signal must not be
- blocked by this signal mask. If more than one thread accepts a
- signal, then it will be delivered to one at random. If all
- threads block the signal, it will remain pending until either a
- thread unblocks it or someone uses sigwaitsig/sigtimedwait. */
- vki_sigset_t sig_mask;
-
- /* tmp_sig_mask is usually the same as sig_mask, and is kept in
- sync whenever sig_mask is changed. The only time they have
- different values is during the execution of a sigsuspend, where
- tmp_sig_mask is the temporary mask which sigsuspend installs.
- It is only consulted to compute the signal mask applied to a
- signal handler. */
- vki_sigset_t tmp_sig_mask;
-
- /* A little signal queue for signals we can't get the kernel to
- queue for us. This is only allocated as needed, since it should
- be rare. */
- struct SigQueue *sig_queue;
-
- /* Syscall the Thread is currently running; -1 if none. Should only
- be set while Thread is in VgTs_WaitSys. */
- Int syscallno;
-
- /* Client stacks. When a thread slot is freed, we don't deallocate its
- stack; we just leave it lying around for the next use of the
- slot. If the next use of the slot requires a larger stack,
- only then is the old one deallocated and a new one
- allocated.
-
- For the main thread (threadid == 0), this mechanism doesn't
- apply. We don't know the size of the stack since we didn't
- allocate it, and furthermore we never reallocate it. */
-
- /* The allocated size of this thread's stack (permanently zero
- if this is ThreadId == 0, since we didn't allocate its stack) */
- SizeT client_stack_szB;
-
- /* Address of the highest legitimate word in this stack. This is
- used for error messages only -- not critical for execution
- correctness. Is is set for all stacks, specifically including
- ThreadId == 0 (the main thread). */
- Addr client_stack_highest_word;
-
- /* Alternate signal stack */
- vki_stack_t altstack;
-
- /* OS-specific thread state */
- os_thread_t os_state;
-
- /* Used in the syscall handlers. Set to True to indicate that the
- PRE routine for a syscall has set the syscall result already and
- so the syscall does not need to be handed to the kernel. */
- Bool syscall_result_set;
-
- /* Per-thread jmp_buf to resume scheduler after a signal */
- Bool sched_jmpbuf_valid;
- jmp_buf sched_jmpbuf;
-}
-ThreadState;
-
-
-/* The thread table. */
-extern ThreadState VG_(threads)[VG_N_THREADS];
-
-/* Allocate a new ThreadState */
-extern ThreadId VG_(alloc_ThreadState)(void);
-
-/* A thread exits. tid must currently be running. */
-extern void VG_(exit_thread)(ThreadId tid);
-
-/* Kill a thread. This interrupts whatever a thread is doing, and
- makes it exit ASAP. This does not set the exitreason or
- exitcode. */
-extern void VG_(kill_thread)(ThreadId tid);
-
-/* Check that tid is in range and denotes a non-Empty thread. */
-extern Bool VG_(is_valid_tid) ( ThreadId tid );
-
-/* Get the ThreadState for a particular thread */
-extern ThreadState *VG_(get_ThreadState)(ThreadId tid);
-
-/* Given an LWP id (ie, real kernel thread id), find the corresponding
- ThreadId */
-extern ThreadId VG_(get_lwp_tid)(Int lwpid);
-
-/* Returns true if a thread is currently running (ie, has the CPU lock) */
-extern Bool VG_(is_running_thread)(ThreadId tid);
-
-/* Returns true if the thread is in the process of exiting */
-extern Bool VG_(is_exiting)(ThreadId tid);
-
-/* Return the number of non-dead Threads */
-extern Int VG_(count_living_threads)(void);
-
-/* Nuke all threads except tid. */
-extern void VG_(nuke_all_threads_except) ( ThreadId me,
- VgSchedReturnCode reason );
-
-/* Make a thread the running thread. The thread must previously been
- sleeping, and not holding the CPU semaphore. This will set the
- thread state to VgTs_Runnable, and the thread will attempt to take
- the CPU semaphore. By the time it returns, tid will be the running
- thread. */
-extern void VG_(set_running) ( ThreadId tid );
-
-/* Set a thread into a sleeping state. Before the call, the thread
- must be runnable, and holding the CPU semaphore. When this call
- returns, the thread will be set to the specified sleeping state,
- and will not be holding the CPU semaphore. Note that another
- thread could be running by the time this call returns, so the
- caller must be careful not to touch any shared state. It is also
- the caller's responsibility to actually block until the thread is
- ready to run again. */
-extern void VG_(set_sleeping) ( ThreadId tid, ThreadStatus state );
-
-/* Yield the CPU for a while */
-extern void VG_(vg_yield)(void);
-
-// The scheduler.
-extern VgSchedReturnCode VG_(scheduler) ( ThreadId tid );
-
-// Do everything which needs doing before the process finally ends,
-// like printing reports, etc
-extern void VG_(shutdown_actions_NORETURN) (
- ThreadId tid,
- VgSchedReturnCode tids_schedretcode
- );
-
-extern void VG_(scheduler_init) ( void );
-
-extern void VG_(pp_sched_status) ( void );
-
-// Longjmp back to the scheduler and thus enter the sighandler immediately.
-extern void VG_(resume_scheduler) ( ThreadId tid );
-
-/* If true, a fault is Valgrind-internal (ie, a bug) */
-extern Bool VG_(my_fault);
-
/* ---------------------------------------------------------------------
Exports of vg_signals.c
------------------------------------------------------------------ */
noinst_LIBRARIES = libos.a
libos_a_SOURCES = \
- core_os.c \
- sema.c
+ core_os.c
#ifndef __LINUX_CORE_OS_H
#define __LINUX_CORE_OS_H
-/* Not really a semaphore, but use a pipe for a token-passing scheme */
-typedef struct {
- Int pipe[2];
- Int owner_thread; /* who currently has it */
-} vg_sema_t;
-
-void VGO_(sema_init)(vg_sema_t *);
-void VGO_(sema_deinit)(vg_sema_t *);
-void VGO_(sema_down)(vg_sema_t *sema);
-void VGO_(sema_up)(vg_sema_t *sema);
-
/* OS-specific thread state */
typedef struct {
/* who we are */
--- /dev/null
+include $(top_srcdir)/Makefile.all.am
+include $(top_srcdir)/Makefile.core-AM_CPPFLAGS.am
+
+noinst_HEADERS = \
+ priv_sema.h
+
+noinst_LIBRARIES = libscheduler.a
+
+libscheduler_a_SOURCES = \
+ scheduler.c \
+ sema.c
+
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- Private scheduler header. priv_sema.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PRIV_SEMA_H
+#define __PRIV_SEMA_H
+
+/* Not really a semaphore, but use a pipe for a token-passing scheme */
+/* Not really a semaphore, but use a pipe for a token-passing scheme */
+typedef struct {
+ Int pipe[2];
+ Int owner_thread; /* who currently has it */
+} vg_sema_t;
+
+// Nb: this may be OS-specific, but let's not factor it out until we
+// implement an OS port for which this isn't ok. Then we can rename them
+// VGO_(sema_init)(), etc.
+void VG_(sema_init) ( vg_sema_t *sema );
+void VG_(sema_deinit) ( vg_sema_t *sema );
+void VG_(sema_down) ( vg_sema_t *sema );
+void VG_(sema_up) ( vg_sema_t *sema );
+
+#endif // __PRIV_SEMA_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
+
/*--------------------------------------------------------------------*/
-/*--- Thread scheduling. vg_scheduler.c ---*/
+/*--- Thread scheduling. scheduler.c ---*/
/*--------------------------------------------------------------------*/
/*
#include "pub_core_errormgr.h"
#include "pub_core_options.h"
#include "pub_core_replacemalloc.h"
+#include "pub_core_scheduler.h"
#include "pub_core_stacktrace.h"
#include "pub_core_syscalls.h"
#include "pub_core_tooliface.h"
#include "pub_core_translate.h"
#include "pub_core_transtab.h"
#include "vki_unistd.h"
+#include "priv_sema.h"
/* ---------------------------------------------------------------------
Types and globals for the scheduler.
tst->status = VgTs_Runnable;
- VGO_(sema_down)(&run_sema);
+ VG_(sema_down)(&run_sema);
if (running_tid != VG_INVALID_THREADID)
VG_(printf)("tid %d found %d running\n", tid, running_tid);
vg_assert(running_tid == VG_INVALID_THREADID);
/* Release the run_sema; this will reschedule any runnable
thread. */
- VGO_(sema_up)(&run_sema);
+ VG_(sema_up)(&run_sema);
if (VG_(clo_trace_sched)) {
Char buf[50];
/* There should still be a valid exitreason for this thread */
vg_assert(VG_(threads)[tid].exitreason != VgSrc_None);
- VGO_(sema_up)(&run_sema);
+ VG_(sema_up)(&run_sema);
}
/* Kill a thread. This interrupts whatever a thread is doing, and
}
/* re-init and take the sema */
- VGO_(sema_deinit)(&run_sema);
- VGO_(sema_init)(&run_sema);
- VGO_(sema_down)(&run_sema);
+ VG_(sema_deinit)(&run_sema);
+ VG_(sema_init)(&run_sema);
+ VG_(sema_down)(&run_sema);
}
Int i;
ThreadId tid_main;
- VGO_(sema_init)(&run_sema);
+ VG_(sema_init)(&run_sema);
for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) {
VG_(threads)[i].sig_queue = NULL;
/*--------------------------------------------------------------------*/
-/*--- end vg_scheduler.c ---*/
+/*--- end ---*/
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
-/*--- Semaphore stuff. linux/sema.c ---*/
+/*--- Semaphore stuff. sema.c ---*/
/*--------------------------------------------------------------------*/
/*
Copyright (C) 2000-2005 Julian Seward
jseward@acm.org
- (except where noted below)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
#include "core.h"
+#include "priv_sema.h"
/*
Slower (than the removed futex-based sema scheme) but more portable
pipe-based token passing scheme.
*/
-void VGO_(sema_init)(vg_sema_t *sema)
+void VG_(sema_init)(vg_sema_t *sema)
{
VG_(pipe)(sema->pipe);
sema->pipe[0] = VG_(safe_fd)(sema->pipe[0]);
VG_(write)(sema->pipe[1], "T", 1);
}
-void VGO_(sema_deinit)(vg_sema_t *sema)
+void VG_(sema_deinit)(vg_sema_t *sema)
{
VG_(close)(sema->pipe[0]);
VG_(close)(sema->pipe[1]);
}
/* get a token */
-void VGO_(sema_down)(vg_sema_t *sema)
+void VG_(sema_down)(vg_sema_t *sema)
{
Char buf[2] = { 'x' };
Int ret;
}
/* put token back */
-void VGO_(sema_up)(vg_sema_t *sema)
+void VG_(sema_up)(vg_sema_t *sema)
{
Int ret;
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- The scheduler. pub_core_scheduler.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_SCHEDULER_H
+#define __PUB_CORE_SCHEDULER_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module is the scheduler, which is the main loop
+// controlling the running of all the program's threads.
+// It's at the centre of everything.
+//--------------------------------------------------------------------
+
+/*
+ Thread state machine:
+
+ Empty -> Init -> Runnable <=> WaitSys/Yielding
+ ^ |
+ \---- Zombie -----/
+ */
+typedef
+ enum ThreadStatus {
+ VgTs_Empty, /* this slot is not in use */
+ VgTs_Init, /* just allocated */
+ VgTs_Runnable, /* ready to run */
+ VgTs_WaitSys, /* waiting for a syscall to complete */
+ VgTs_Yielding, /* temporarily yielding the CPU */
+ VgTs_Zombie, /* transient state just before exiting */
+ }
+ ThreadStatus;
+
+/* Return codes from the scheduler. */
+typedef
+ enum {
+ VgSrc_None, /* not exiting yet */
+ VgSrc_ExitSyscall, /* client called exit(). This is the normal
+ route out. */
+ VgSrc_FatalSig /* Killed by the default action of a fatal
+ signal */
+ }
+ VgSchedReturnCode;
+
+
+#if defined(VGA_x86)
+ typedef VexGuestX86State VexGuestArchState;
+#elif defined(VGA_amd64)
+ typedef VexGuestAMD64State VexGuestArchState;
+#elif defined(VGA_arm)
+ typedef VexGuestARMState VexGuestArchState;
+#else
+# error Unknown architecture
+#endif
+
+
+typedef
+ struct {
+ /* --- BEGIN vex-mandated guest state --- */
+
+ /* Saved machine context. */
+ VexGuestArchState vex;
+
+ /* Saved shadow context. */
+ VexGuestArchState vex_shadow;
+
+ /* Spill area. */
+ UChar vex_spill[LibVEX_N_SPILL_BYTES];
+
+ /* --- END vex-mandated guest state --- */
+ }
+ ThreadArchState;
+
+
+typedef struct {
+ /* ThreadId == 0 (and hence vg_threads[0]) is NEVER USED.
+ The thread identity is simply the index in vg_threads[].
+ ThreadId == 1 is the root thread and has the special property
+ that we don't try and allocate or deallocate its stack. For
+ convenience of generating error message, we also put the
+ ThreadId in this tid field, but be aware that it should
+ ALWAYS == the index in vg_threads[]. */
+ ThreadId tid;
+
+ /* Current scheduling status. */
+ ThreadStatus status;
+
+ /* This is set if the thread is in the process of exiting for any
+ reason. The precise details of the exit are in the OS-specific
+ state. */
+ VgSchedReturnCode exitreason;
+
+ /* Architecture-specific thread state. */
+ ThreadArchState arch;
+
+ /* This thread's blocked-signals mask. Semantics is that for a
+ signal to be delivered to this thread, the signal must not be
+ blocked by this signal mask. If more than one thread accepts a
+ signal, then it will be delivered to one at random. If all
+ threads block the signal, it will remain pending until either a
+ thread unblocks it or someone uses sigwaitsig/sigtimedwait. */
+ vki_sigset_t sig_mask;
+
+ /* tmp_sig_mask is usually the same as sig_mask, and is kept in
+ sync whenever sig_mask is changed. The only time they have
+ different values is during the execution of a sigsuspend, where
+ tmp_sig_mask is the temporary mask which sigsuspend installs.
+ It is only consulted to compute the signal mask applied to a
+ signal handler. */
+ vki_sigset_t tmp_sig_mask;
+
+ /* A little signal queue for signals we can't get the kernel to
+ queue for us. This is only allocated as needed, since it should
+ be rare. */
+ struct SigQueue *sig_queue;
+
+ /* Syscall the Thread is currently running; -1 if none. Should only
+ be set while Thread is in VgTs_WaitSys. */
+ Int syscallno;
+
+ /* Client stacks. When a thread slot is freed, we don't deallocate its
+ stack; we just leave it lying around for the next use of the
+ slot. If the next use of the slot requires a larger stack,
+ only then is the old one deallocated and a new one
+ allocated.
+
+ For the main thread (threadid == 0), this mechanism doesn't
+ apply. We don't know the size of the stack since we didn't
+ allocate it, and furthermore we never reallocate it. */
+
+ /* The allocated size of this thread's stack (permanently zero
+ if this is ThreadId == 0, since we didn't allocate its stack) */
+ SizeT client_stack_szB;
+
+ /* Address of the highest legitimate word in this stack. This is
+ used for error messages only -- not critical for execution
+ correctness. Is is set for all stacks, specifically including
+ ThreadId == 0 (the main thread). */
+ Addr client_stack_highest_word;
+
+ /* Alternate signal stack */
+ vki_stack_t altstack;
+
+ /* OS-specific thread state */
+ os_thread_t os_state;
+
+ /* Used in the syscall handlers. Set to True to indicate that the
+ PRE routine for a syscall has set the syscall result already and
+ so the syscall does not need to be handed to the kernel. */
+ Bool syscall_result_set;
+
+ /* Per-thread jmp_buf to resume scheduler after a signal */
+ Bool sched_jmpbuf_valid;
+ jmp_buf sched_jmpbuf;
+}
+ThreadState;
+
+
+/* The thread table. */
+extern ThreadState VG_(threads)[VG_N_THREADS];
+
+/* Allocate a new ThreadState */
+extern ThreadId VG_(alloc_ThreadState)(void);
+
+/* A thread exits. tid must currently be running. */
+extern void VG_(exit_thread)(ThreadId tid);
+
+/* Kill a thread. This interrupts whatever a thread is doing, and
+ makes it exit ASAP. This does not set the exitreason or
+ exitcode. */
+extern void VG_(kill_thread)(ThreadId tid);
+
+/* Check that tid is in range and denotes a non-Empty thread. */
+extern Bool VG_(is_valid_tid) ( ThreadId tid );
+
+/* Get the ThreadState for a particular thread */
+extern ThreadState *VG_(get_ThreadState)(ThreadId tid);
+
+/* Given an LWP id (ie, real kernel thread id), find the corresponding
+ ThreadId */
+extern ThreadId VG_(get_lwp_tid)(Int lwpid);
+
+/* Returns true if a thread is currently running (ie, has the CPU lock) */
+extern Bool VG_(is_running_thread)(ThreadId tid);
+
+/* Returns true if the thread is in the process of exiting */
+extern Bool VG_(is_exiting)(ThreadId tid);
+
+/* Return the number of non-dead Threads */
+extern Int VG_(count_living_threads)(void);
+
+/* Nuke all threads except tid. */
+extern void VG_(nuke_all_threads_except) ( ThreadId me,
+ VgSchedReturnCode reason );
+
+/* Make a thread the running thread. The thread must previously been
+ sleeping, and not holding the CPU semaphore. This will set the
+ thread state to VgTs_Runnable, and the thread will attempt to take
+ the CPU semaphore. By the time it returns, tid will be the running
+ thread. */
+extern void VG_(set_running) ( ThreadId tid );
+
+/* Set a thread into a sleeping state. Before the call, the thread
+ must be runnable, and holding the CPU semaphore. When this call
+ returns, the thread will be set to the specified sleeping state,
+ and will not be holding the CPU semaphore. Note that another
+ thread could be running by the time this call returns, so the
+ caller must be careful not to touch any shared state. It is also
+ the caller's responsibility to actually block until the thread is
+ ready to run again. */
+extern void VG_(set_sleeping) ( ThreadId tid, ThreadStatus state );
+
+/* Yield the CPU for a while */
+extern void VG_(vg_yield)(void);
+
+// The scheduler.
+extern VgSchedReturnCode VG_(scheduler) ( ThreadId tid );
+
+// Do everything which needs doing before the process finally ends,
+// like printing reports, etc
+extern void VG_(shutdown_actions_NORETURN) (
+ ThreadId tid,
+ VgSchedReturnCode tids_schedretcode
+ );
+
+extern void VG_(scheduler_init) ( void );
+
+extern void VG_(pp_sched_status) ( void );
+
+// Longjmp back to the scheduler and thus enter the sighandler immediately.
+extern void VG_(resume_scheduler) ( ThreadId tid );
+
+/* If true, a fault is Valgrind-internal (ie, a bug) */
+extern Bool VG_(my_fault);
+
+#endif // __PUB_CORE_SCHEDULER_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/