// wait until all other threads are dead
extern void VGA_(reap_threads)(ThreadId self);
-// handle an arch-specific client request
-extern Bool VGA_(client_request)(ThreadId tid, UWord *args);
-
// For attaching the debugger
extern Int VGA_(ptrace_setregs_from_tst) ( Int pid, ThreadArchState* arch );
// Used by leakcheck
extern void VGA_(mark_from_registers)(ThreadId tid, void (*marker)(Addr));
-// Set up the libc freeres wrapper
-extern void VGA_(intercept_libc_freeres_wrapper)(Addr);
-
-// Clean up the client by calling before the final reports
-extern void VGA_(final_tidyup)(ThreadId tid);
-
/* ---------------------------------------------------------------------
Finally - autoconf-generated settings
------------------------------------------------------------------ */
vg_assert(i_am_the_only_thread());
}
-/* The we need to know the address of it so it can be
- called at program exit. */
-static Addr __libc_freeres_wrapper;
-
-void VGA_(intercept_libc_freeres_wrapper)(Addr addr)
-{
- __libc_freeres_wrapper = addr;
-}
-
-/* Final clean-up before terminating the process.
- Clean up the client by calling __libc_freeres() (if requested) */
-void VGA_(final_tidyup)(ThreadId tid)
-{
- vg_assert(VG_(is_running_thread)(tid));
-
- if (!VG_(needs).libc_freeres ||
- !VG_(clo_run_libc_freeres) ||
- __libc_freeres_wrapper == 0)
- return; /* can't/won't do it */
-
- if (VG_(clo_verbosity) > 2 ||
- VG_(clo_trace_syscalls) ||
- VG_(clo_trace_sched))
- VG_(message)(Vg_DebugMsg,
- "Caught __NR_exit; running __libc_freeres()");
-
- /* point thread context to point to libc_freeres_wrapper */
- INSTR_PTR(VG_(threads)[tid].arch) = __libc_freeres_wrapper;
- // XXX should we use a special stack?
-
- /* Block all blockable signals by copying the real block state into
- the thread's block state*/
- VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
- VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
-
- /* and restore handlers to default */
- VG_(set_default_handler)(VKI_SIGSEGV);
- VG_(set_default_handler)(VKI_SIGBUS);
- VG_(set_default_handler)(VKI_SIGILL);
- VG_(set_default_handler)(VKI_SIGFPE);
-
- // We were exiting, so assert that...
- vg_assert(VG_(is_exiting)(tid));
- // ...but now we're not again
- VG_(threads)[tid].exitreason = VgSrc_None;
-
- // run until client thread exits - ideally with LIBC_FREERES_DONE,
- // but exit/exitgroup/signal will do
- VG_(scheduler)(tid);
-
- vg_assert(VG_(is_exiting)(tid));
-}
-
-// Arch-specific client requests
-Bool VGA_(client_request)(ThreadId tid, UWord *args)
-{
- Bool handled = True;
-
- vg_assert(VG_(is_running_thread)(tid));
-
- switch(args[0]) {
- case VG_USERREQ__LIBC_FREERES_DONE:
- /* This is equivalent to an exit() syscall, but we don't set the
- exitcode (since it might already be set) */
- if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched))
- VG_(message)(Vg_DebugMsg,
- "__libc_freeres() done; really quitting!");
- VG_(threads)[tid].exitreason = VgSrc_ExitSyscall;
- break;
-
- default:
- handled = False;
- break;
- }
-
- return handled;
-}
-
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
}
+/* The we need to know the address of it so it can be
+ called at program exit. */
+static Addr __libc_freeres_wrapper;
+
+void VGA_(intercept_libc_freeres_wrapper)(Addr addr)
+{
+ __libc_freeres_wrapper = addr;
+}
+
+/* Final clean-up before terminating the process.
+ Clean up the client by calling __libc_freeres() (if requested)
+ This is Linux-specific?
+*/
+static void final_tidyup(ThreadId tid)
+{
+ vg_assert(VG_(is_running_thread)(tid));
+
+ if (!VG_(needs).libc_freeres ||
+ !VG_(clo_run_libc_freeres) ||
+ __libc_freeres_wrapper == 0)
+ return; /* can't/won't do it */
+
+ if (VG_(clo_verbosity) > 2 ||
+ VG_(clo_trace_syscalls) ||
+ VG_(clo_trace_sched))
+ VG_(message)(Vg_DebugMsg,
+ "Caught __NR_exit; running __libc_freeres()");
+
+ /* point thread context to point to libc_freeres_wrapper */
+ INSTR_PTR(VG_(threads)[tid].arch) = __libc_freeres_wrapper;
+ // XXX should we use a special stack?
+
+ /* Block all blockable signals by copying the real block state into
+ the thread's block state*/
+ VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
+ VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
+
+ /* and restore handlers to default */
+ VG_(set_default_handler)(VKI_SIGSEGV);
+ VG_(set_default_handler)(VKI_SIGBUS);
+ VG_(set_default_handler)(VKI_SIGILL);
+ VG_(set_default_handler)(VKI_SIGFPE);
+
+ // We were exiting, so assert that...
+ vg_assert(VG_(is_exiting)(tid));
+ // ...but now we're not again
+ VG_(threads)[tid].exitreason = VgSrc_None;
+
+ // run until client thread exits - ideally with LIBC_FREERES_DONE,
+ // but exit/exitgroup/signal will do
+ VG_(scheduler)(tid);
+
+ vg_assert(VG_(is_exiting)(tid));
+}
+
/* Do everything which needs doing when the last thread exits */
void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
VgSchedReturnCode tids_schedretcode )
VG_(clo_model_pthreads) = False;
// Clean the client up before the final report
- VGA_(final_tidyup)(tid);
+ final_tidyup(tid);
// OK, done
VG_(exit_thread)(tid);
Handle client requests.
------------------------------------------------------------------ */
+// OS-specific(?) client requests
+static Bool os_client_request(ThreadId tid, UWord *args)
+{
+ Bool handled = True;
+
+ vg_assert(VG_(is_running_thread)(tid));
+
+ switch(args[0]) {
+ case VG_USERREQ__LIBC_FREERES_DONE:
+ /* This is equivalent to an exit() syscall, but we don't set the
+ exitcode (since it might already be set) */
+ if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched))
+ VG_(message)(Vg_DebugMsg,
+ "__libc_freeres() done; really quitting!");
+ VG_(threads)[tid].exitreason = VgSrc_ExitSyscall;
+ break;
+
+ default:
+ handled = False;
+ break;
+ }
+
+ return handled;
+}
+
+
/* Do a client request for the thread tid. After the request, tid may
or may not still be runnable; if not, the scheduler will have to
choose a new thread to run.
break;
default:
- if (VGA_(client_request)(tid, arg)) {
- /* architecture handled the client request */
+ if (os_client_request(tid, arg)) {
+ // do nothing, os_client_request() handled it
} else if (VG_(needs).client_requests) {
UWord ret;
/* 64-bit counter for the number of basic blocks done. */
extern ULong VG_(bbs_done);
+// Set up the libc freeres wrapper (XXX: currently unused -- ?!)
+extern void VGA_(intercept_libc_freeres_wrapper)(Addr);
#endif // __PUB_CORE_MAIN_H