From: Julian Seward Date: Tue, 31 May 2005 15:41:42 +0000 (+0000) Subject: Unbreak amd64 build. X-Git-Tag: svn/VALGRIND_3_0_0~494 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=954077adab181ff198caf0a4c4bdeeb14d251704;p=thirdparty%2Fvalgrind.git Unbreak amd64 build. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3824 --- diff --git a/coregrind/m_syscalls/syscalls-amd64-linux.c b/coregrind/m_syscalls/syscalls-amd64-linux.c index ca82fea055..31cc2fa355 100644 --- a/coregrind/m_syscalls/syscalls-amd64-linux.c +++ b/coregrind/m_syscalls/syscalls-amd64-linux.c @@ -30,6 +30,7 @@ #include "core.h" #include "ume.h" /* for jmp_with_stack */ +#include "pub_core_debuglog.h" #include "pub_core_aspacemgr.h" #include "pub_core_sigframe.h" #include "pub_core_syscalls.h" @@ -245,64 +246,116 @@ SSizeT VGA_(stack_unused)(ThreadId tid) return ((Addr)p) - tst->os_state.valgrind_stack_base; } + +/* Run a thread all the way to the end, then do appropriate exit actions + (this is the last-one-out-turn-off-the-lights bit). +*/ +static void run_a_thread_NORETURN ( Word tidW ) +{ + ThreadId tid = (ThreadId)tidW; + + VG_(debugLog)(1, "syscalls-x86-linux", + "run_a_thread_NORETURN(tid=%lld): " + "VGO_(thread_wrapper) called\n", + (ULong)tidW); + + /* Run the thread all the way through. */ + VgSchedReturnCode src = VGO_(thread_wrapper)(tid); + + VG_(debugLog)(1, "syscalls-x86-linux", + "run_a_thread_NORETURN(tid=%lld): " + "VGO_(thread_wrapper) done\n", + (ULong)tidW); + + Int c = VG_(count_living_threads)(); + vg_assert(c >= 1); /* stay sane */ + + if (c == 1) { + + VG_(debugLog)(1, "syscalls-x86-linux", + "run_a_thread_NORETURN(tid=%lld): " + "last one standing\n", + (ULong)tidW); + + /* We are the last one standing. Keep hold of the lock and + carry on to show final tool results, then exit the entire system. */ + VG_(shutdown_actions_NORETURN)(tid, src); + + } else { + + VG_(debugLog)(1, "syscalls-x86-linux", + "run_a_thread_NORETURN(tid=%lld): " + "not last one standing\n", + (ULong)tidW); + + /* OK, thread is dead, but others still exist. Just exit. */ + ThreadState *tst = VG_(get_ThreadState)(tid); + + /* This releases the run lock */ + VG_(exit_thread)(tid); + vg_assert(tst->status == VgTs_Zombie); + + /* We have to use this sequence to terminate the thread to + prevent a subtle race. If VG_(exit_thread)() had left the + ThreadState as Empty, then it could have been reallocated, + reusing the stack while we're doing these last cleanups. + Instead, VG_(exit_thread) leaves it as Zombie to prevent + reallocation. We need to make sure we don't touch the stack + between marking it Empty and exiting. Hence the + assembler. */ + asm volatile ( + "movl %1, %0\n" /* set tst->status = VgTs_Empty */ + "movq %2, %%rax\n" /* set %rax = __NR_exit */ + "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */ + "syscall\n" /* exit(tst->os_state.exitcode) */ + : "=m" (tst->status) + : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)); + + VG_(core_panic)("Thread exit failed?\n"); + } + + /*NOTREACHED*/ + vg_assert(0); +} + + /* - Allocate a stack for the main thread, and call VGA_(thread_wrapper) - on that stack. - */ -void VGA_(main_thread_wrapper)(ThreadId tid) + Allocate a stack for the main thread, and run it all the way to the + end. +*/ +void VGP_(main_thread_wrapper_NORETURN)(ThreadId tid) { + VG_(debugLog)(1, "syscalls-amd64-linux", + "entering VGP_(main_thread_wrapper_NORETURN)\n"); + UWord* rsp = allocstack(tid); - vg_assert(tid == VG_(master_tid)); + /* shouldn't be any other threads around yet */ + vg_assert( VG_(count_living_threads)() == 1 ); call_on_new_stack_0_1( - (Addr)rsp, /* stack */ - 0, /*bogus return address*/ - VGA_(thread_wrapper), /* fn to call */ - (Word)tid /* arg to give it */ + (Addr)rsp, /* stack */ + 0, /*bogus return address*/ + run_a_thread_NORETURN, /* fn to call */ + (Word)tid /* arg to give it */ ); /*NOTREACHED*/ vg_assert(0); } -static Int start_thread(void *arg) + +static Int start_thread_NORETURN ( void* arg ) { - ThreadState *tst = (ThreadState *)arg; - ThreadId tid = tst->tid; - - VGA_(thread_wrapper)(tid); - - /* OK, thread is dead; this releases the run lock */ - VG_(exit_thread)(tid); - - vg_assert(tst->status == VgTs_Zombie); - - /* Poke the reaper */ - if (VG_(clo_trace_signals)) - VG_(message)(Vg_DebugMsg, "Sending SIGVGCHLD to master tid=%d lwp=%d", - VG_(master_tid), VG_(threads)[VG_(master_tid)].os_state.lwpid); - - VG_(tkill)(VG_(threads)[VG_(master_tid)].os_state.lwpid, VKI_SIGVGCHLD); - - /* We have to use this sequence to terminate the thread to prevent - a subtle race. If VG_(exit_thread)() had left the ThreadState - as Empty, then it could have been reallocated, reusing the stack - while we're doing these last cleanups. Instead, - VG_(exit_thread) leaves it as Zombie to prevent reallocation. - We need to make sure we don't touch the stack between marking it - Empty and exiting. Hence the assembler. */ - asm volatile ( - "movl %1, %0\n" /* set tst->status = VgTs_Empty */ - "movq %2, %%rax\n" /* set %rax = __NR_exit */ - "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */ - "syscall\n" /* exit(tst->os_state.exitcode) */ - : "=m" (tst->status) - : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)); - - VG_(core_panic)("Thread exit failed?\n"); + ThreadState* tst = (ThreadState*)arg; + ThreadId tid = tst->tid; + + run_a_thread_NORETURN ( (Word)tid ); + /*NOTREACHED*/ + vg_assert(0); } + /* --------------------------------------------------------------------- clone() handling ------------------------------------------------------------------ */ @@ -398,7 +451,7 @@ static Int do_clone(ThreadId ptid, VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); /* Create the new thread */ - ret = VG_(clone)(start_thread, stack, flags, &VG_(threads)[ctid], + ret = VG_(clone)(start_thread_NORETURN, stack, flags, &VG_(threads)[ctid], child_tidptr, parent_tidptr, NULL); VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);