]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Factor out some common code in m_syswrap.
authorNicholas Nethercote <njn@valgrind.org>
Wed, 9 Nov 2005 04:49:28 +0000 (04:49 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Wed, 9 Nov 2005 04:49:28 +0000 (04:49 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5049

coregrind/m_syswrap/priv_syswrap-linux.h
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-ppc32-linux.c
coregrind/m_syswrap/syswrap-x86-linux.c

index 22babd859fb8e3bc3d7254ad424916104d540772..5229d149d9956eb85c12eaf54e3b2ae390451776 100644 (file)
 // Run a thread from beginning to end. 
 extern VgSchedReturnCode ML_(thread_wrapper)(Word /*ThreadId*/ tid);
 
+extern Int  ML_(start_thread_NORETURN) ( void* arg );
+extern void ML_(run_a_thread_NORETURN) ( Word tidW );
+extern Addr ML_(allocstack)            ( ThreadId tid );
+extern void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr,
+                                        void (*f)(Word), Word arg1 );
+
 DECL_TEMPLATE(linux, sys_mount);
 DECL_TEMPLATE(linux, sys_oldumount);
 DECL_TEMPLATE(linux, sys_umount);
index d2d82d6d409548caadb5e3e547fc12e3b8320c79..c54340b92d94c0224d90c2aa667e54b3908fbf3a 100644 (file)
    Note.  Why is this stuff here?
    ------------------------------------------------------------------ */
 
-/* Allocate a stack for this thread.  They're allocated lazily, and
-   never freed. */
-
-/* Allocate a stack for this thread, if it doesn't already have one.
-   Returns the initial stack pointer value to use, or 0 if allocation
-   failed. */
-
-static Addr allocstack(ThreadId tid)
-{
-   ThreadState* tst = VG_(get_ThreadState)(tid);
-   VgStack*     stack;
-   Addr         initial_SP;
-
-   /* Either the stack_base and stack_init_SP are both zero (in which
-      case a stack hasn't been allocated) or they are both non-zero,
-      in which case it has. */
-
-   if (tst->os_state.valgrind_stack_base == 0)
-      vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
-
-   if (tst->os_state.valgrind_stack_base != 0)
-      vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
-
-   /* If no stack is present, allocate one. */
-
-   if (tst->os_state.valgrind_stack_base == 0) {
-      stack = VG_(am_alloc_VgStack)( &initial_SP );
-      if (stack) {
-         tst->os_state.valgrind_stack_base    = (Addr)stack;
-         tst->os_state.valgrind_stack_init_SP = initial_SP;
-      }
-   }
-
-   if (0)
-      VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
-                   tid, 
-                   (void*)tst->os_state.valgrind_stack_base, 
-                   (void*)tst->os_state.valgrind_stack_init_SP );
-                  
-   return tst->os_state.valgrind_stack_init_SP;
-}
-
-
-/* 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;
-   VgSchedReturnCode src;
-   Int c;
-
-   VG_(debugLog)(1, "syswrap-amd64-linux", 
-                    "run_a_thread_NORETURN(tid=%lld): "
-                       "ML_(thread_wrapper) called\n",
-                       (ULong)tidW);
-
-   /* Run the thread all the way through. */
-   src = ML_(thread_wrapper)(tid);  
-
-   VG_(debugLog)(1, "syswrap-amd64-linux", 
-                    "run_a_thread_NORETURN(tid=%lld): "
-                       "ML_(thread_wrapper) done\n",
-                       (ULong)tidW);
-
-   c = VG_(count_living_threads)();
-   vg_assert(c >= 1); /* stay sane */
-
-   if (c == 1) {
-
-      VG_(debugLog)(1, "syswrap-amd64-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. 
-         Use the continuation pointer set at startup in m_main. */
-      ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
-
-   } else {
-
-      ThreadState *tst;
-
-      VG_(debugLog)(1, "syswrap-amd64-linux", 
-                       "run_a_thread_NORETURN(tid=%lld): "
-                          "not last one standing\n",
-                          (ULong)tidW);
-
-      /* OK, thread is dead, but others still exist.  Just exit. */
-      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);
-}
-
-
 /* Call f(arg1), but first switch stacks, using 'stack' as the new
    stack, and use 'retaddr' as f's return-to address.  Also, clear all
    the integer registers before entering f.  */
 __attribute__((noreturn))
-void call_on_new_stack_0_1 ( Addr stack,
-                            Addr retaddr,
-                            void (*f)(Word),
-                             Word arg1 );
+void ML_(call_on_new_stack_0_1) ( Addr stack,
+                                 Addr retaddr,
+                                 void (*f)(Word),
+                                  Word arg1 );
 // %rdi == stack
 // %rsi == retaddr
 // %rdx == f
 // %rcx == arg1
 asm(
-"call_on_new_stack_0_1:\n"
+".globl vgModuleLocal_call_on_new_stack_0_1\n"
+vgModuleLocal_call_on_new_stack_0_1:\n"
 "   movq   %rdi, %rsp\n"   // set stack
 "   pushq  %rsi\n"         // retaddr to stack
 "   pushq  %rdx\n"         // f to stack
@@ -216,51 +97,6 @@ asm(
 "   ud2\n"                 // should never get here
 );
 
-
-/* Allocate a stack for the main thread, and run it all the way to the
-   end.  Although we already have a working VgStack
-   (VG_(interim_stack)) it's better to allocate a new one, so that
-   overflow detection works uniformly for all threads.
-*/
-void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
-{
-   Addr rsp;
-
-   VG_(debugLog)(1, "syswrap-amd64-linux", 
-                    "entering VG_(main_thread_wrapper_NORETURN)\n");
-
-   rsp = allocstack(tid);
-
-   /* If we can't even allocate the first thread's stack, we're hosed.
-      Give up. */
-   vg_assert2(rsp != 0, "Cannot allocate main thread's stack.");
-
-   /* 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*/
-      run_a_thread_NORETURN,  /* fn to call */
-      (Word)tid               /* arg to give it */
-   );
-
-   /*NOTREACHED*/
-   vg_assert(0);
-}
-
-
-static Long start_thread_NORETURN ( void* arg )
-{
-   ThreadState* tst = (ThreadState*)arg;
-   ThreadId     tid = tst->tid;
-
-   run_a_thread_NORETURN ( (Word)tid );
-   /*NOTREACHED*/
-   vg_assert(0);
-}
-
-
 /* ---------------------------------------------------------------------
    clone() handling
    ------------------------------------------------------------------ */
@@ -380,7 +216,7 @@ static SysRes do_clone ( ThreadId ptid,
    vg_assert(VG_(is_running_thread)(ptid));
    vg_assert(VG_(is_valid_tid)(ctid));
 
-   stack = (UWord*)allocstack(ctid);
+   stack = (UWord*)ML_(allocstack)(ctid);
    if (stack == NULL) {
       res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
       goto out;
@@ -445,7 +281,7 @@ static SysRes do_clone ( ThreadId ptid,
 
    /* Create the new thread */
    rax = do_syscall_clone_amd64_linux(
-            start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
+            ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
             child_tidptr, parent_tidptr, NULL
          );
    res = VG_(mk_SysRes_amd64_linux)( rax );
index 9ed5de6f4db3f8612667c56b9aa7fdfa44ba0d86..b036b82a2e1e84c6c95f654dc9d8f87b6a1ac9ac 100644 (file)
 #include "pub_core_scheduler.h"
 #include "pub_core_signals.h"
 #include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
 
 #include "priv_types_n_macros.h"
 #include "priv_syswrap-generic.h"
 #include "priv_syswrap-linux.h"
 
+#include "vki_unistd.h"              /* for the __NR_* constants */
+
 // Run a thread from beginning to end and return the thread's
 // scheduler-return-code.
 VgSchedReturnCode ML_(thread_wrapper)(Word /*ThreadId*/ tidW)
@@ -95,6 +98,194 @@ VgSchedReturnCode ML_(thread_wrapper)(Word /*ThreadId*/ tidW)
 }
 
 
+/* ---------------------------------------------------------------------
+   clone-related stuff
+   ------------------------------------------------------------------ */
+
+/* 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).  */
+void ML_(run_a_thread_NORETURN) ( Word tidW )
+{
+   ThreadId          tid = (ThreadId)tidW;
+   VgSchedReturnCode src;
+   Int               c;
+
+   VG_(debugLog)(1, "syswrap-generic", 
+                    "run_a_thread_NORETURN(tid=%lld): "
+                       "ML_(thread_wrapper) called\n",
+                       (ULong)tidW);
+
+   /* Run the thread all the way through. */
+   src = ML_(thread_wrapper)(tid);  
+
+   VG_(debugLog)(1, "syswrap-ppc32-linux", 
+                    "run_a_thread_NORETURN(tid=%lld): "
+                       "ML_(thread_wrapper) done\n",
+                       (ULong)tidW);
+
+   c = VG_(count_living_threads)();
+   vg_assert(c >= 1); /* stay sane */
+
+   if (c == 1) {
+
+      VG_(debugLog)(1, "syswrap-ppc32-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. 
+         Use the continuation pointer set at startup in m_main. */
+      ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
+
+   } else {
+
+      ThreadState *tst;
+
+      VG_(debugLog)(1, "syswrap-ppc32-linux", 
+                       "run_a_thread_NORETURN(tid=%lld): "
+                          "not last one standing\n",
+                          (ULong)tidW);
+
+      /* OK, thread is dead, but others still exist.  Just exit. */
+      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. */
+#if defined(VGP_x86_linux)
+      asm volatile (
+         "movl %1, %0\n"       /* set tst->status = VgTs_Empty */
+         "movl %2, %%eax\n"    /* set %eax = __NR_exit */
+         "movl %3, %%ebx\n"    /* set %ebx = tst->os_state.exitcode */
+         "int  $0x80\n"        /* exit(tst->os_state.exitcode) */
+         : "=m" (tst->status)
+         : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
+#elif defined(VGP_amd64_linux)
+      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));
+#elif defined(VGP_ppc32_linux)
+      { UInt vgts_empty = (UInt)VgTs_Empty;
+        asm volatile (
+          "stw %1,%0\n\t"          /* set tst->status = VgTs_Empty */
+          "li  0,%2\n\t"           /* set r0 = __NR_exit */
+          "lwz 3,%3\n\t"           /* set r3 = tst->os_state.exitcode */
+          "sc\n\t"                 /* exit(tst->os_state.exitcode) */
+          : "=m" (tst->status)
+          : "r" (vgts_empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
+      }
+#else
+# error Unknown platform
+#endif
+
+      VG_(core_panic)("Thread exit failed?\n");
+   }
+
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+Int ML_(start_thread_NORETURN) ( void* arg )
+{
+   ThreadState* tst = (ThreadState*)arg;
+   ThreadId     tid = tst->tid;
+
+   ML_(run_a_thread_NORETURN) ( (Word)tid );
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+/* Allocate a stack for this thread, if it doesn't already have one.
+   They're allocated lazily, and never freed.  Returns the initial stack
+   pointer value to use, or 0 if allocation failed. */
+Addr ML_(allocstack)(ThreadId tid)
+{
+   ThreadState* tst = VG_(get_ThreadState)(tid);
+   VgStack*     stack;
+   Addr         initial_SP;
+
+   /* Either the stack_base and stack_init_SP are both zero (in which
+      case a stack hasn't been allocated) or they are both non-zero,
+      in which case it has. */
+
+   if (tst->os_state.valgrind_stack_base == 0)
+      vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
+
+   if (tst->os_state.valgrind_stack_base != 0)
+      vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
+
+   /* If no stack is present, allocate one. */
+
+   if (tst->os_state.valgrind_stack_base == 0) {
+      stack = VG_(am_alloc_VgStack)( &initial_SP );
+      if (stack) {
+         tst->os_state.valgrind_stack_base    = (Addr)stack;
+         tst->os_state.valgrind_stack_init_SP = initial_SP;
+      }
+   }
+
+   if (0)
+      VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
+                   tid, 
+                   (void*)tst->os_state.valgrind_stack_base, 
+                   (void*)tst->os_state.valgrind_stack_init_SP );
+                  
+   return tst->os_state.valgrind_stack_init_SP;
+}
+
+/* Allocate a stack for the main thread, and run it all the way to the
+   end.  Although we already have a working VgStack
+   (VG_(interim_stack)) it's better to allocate a new one, so that
+   overflow detection works uniformly for all threads.
+*/
+void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
+{
+   Addr sp;
+   VG_(debugLog)(1, "syswrap-linux", 
+                    "entering VG_(main_thread_wrapper_NORETURN)\n");
+
+   sp = ML_(allocstack)(tid);
+
+#if defined(VGP_ppc32_linux)
+   /* make a stack frame */
+   sp -= 16;
+   sp &= ~0xF;
+   *(UWord *)sp = 0;
+#endif
+
+   /* If we can't even allocate the first thread's stack, we're hosed.
+      Give up. */
+   vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
+
+   /* shouldn't be any other threads around yet */
+   vg_assert( VG_(count_living_threads)() == 1 );
+
+   ML_(call_on_new_stack_0_1)( 
+      (Addr)sp,                    /* stack */
+      0,                           /* bogus return address */
+      ML_(run_a_thread_NORETURN),  /* fn to call */
+      (Word)tid                    /* arg to give it */
+   );
+
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+
 /* ---------------------------------------------------------------------
    PRE/POST wrappers for arch-generic, Linux-specific syscalls
    ------------------------------------------------------------------ */
index 6e5b49b4f45f9f8d394eed25f96f5217a6823b67..dc3ff04e756188447df48f78c5213def42192b02 100644 (file)
    Note.  Why is this stuff here?
    ------------------------------------------------------------------ */
 
-/* Allocate a stack for this thread.  They're allocated lazily, and
-   never freed. */
-
-/* Allocate a stack for this thread, if it doesn't already have one.
-   Returns the initial stack pointer value to use, or 0 if allocation
-   failed. */
-
-static Addr allocstack ( ThreadId tid )
-{
-   ThreadState* tst = VG_(get_ThreadState)(tid);
-   VgStack*     stack;
-   Addr         initial_SP;
-
-   /* Either the stack_base and stack_init_SP are both zero (in which
-      case a stack hasn't been allocated) or they are both non-zero,
-      in which case it has. */
-
-   if (tst->os_state.valgrind_stack_base == 0)
-      vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
-
-   if (tst->os_state.valgrind_stack_base != 0)
-      vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
-
-   /* If no stack is present, allocate one. */
-
-   if (tst->os_state.valgrind_stack_base == 0) {
-      stack = VG_(am_alloc_VgStack)( &initial_SP );
-      if (stack) {
-         tst->os_state.valgrind_stack_base    = (Addr)stack;
-         tst->os_state.valgrind_stack_init_SP = initial_SP;
-      }
-   }
-
-   if (0)
-      VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
-                   tid, 
-                   (void*)tst->os_state.valgrind_stack_base, 
-                   (void*)tst->os_state.valgrind_stack_init_SP );
-                  
-   return tst->os_state.valgrind_stack_init_SP;
-}
-
-
-/* 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 )
-{
-   Int               c;
-   VgSchedReturnCode src;
-   ThreadState*      tst;
-   ThreadId          tid = (ThreadId)tidW;
-
-   VG_(debugLog)(1, "syswrap-ppc32-linux", 
-                    "run_a_thread_NORETURN(tid=%lld): "
-                       "ML_(thread_wrapper) called\n",
-                       (ULong)tidW);
-
-   /* Run the thread all the way through. */
-   src = ML_(thread_wrapper)(tid);  
-
-   VG_(debugLog)(1, "syswrap-ppc32-linux", 
-                    "run_a_thread_NORETURN(tid=%lld): "
-                       "ML_(thread_wrapper) done\n",
-                       (ULong)tidW);
-
-   c = VG_(count_living_threads)();
-   vg_assert(c >= 1); /* stay sane */
-
-   if (c == 1) {
-
-      VG_(debugLog)(1, "syswrap-ppc32-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. 
-         Use the continuation pointer set at startup in m_main. */
-      ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
-
-   } else {
-
-      VG_(debugLog)(1, "syswrap-ppc32-linux", 
-                       "run_a_thread_NORETURN(tid=%lld): "
-                          "not last one standing\n",
-                          (ULong)tidW);
-
-      /* OK, thread is dead, but others still exist.  Just exit. */
-      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. */
-      { UInt vgts_empty = (UInt)VgTs_Empty;
-        asm volatile (
-          "stw %1,%0\n\t"          /* set tst->status = VgTs_Empty */
-          "li  0,%2\n\t"           /* set r0 = __NR_exit */
-          "lwz 3,%3\n\t"           /* set r3 = tst->os_state.exitcode */
-          "sc\n\t"                 /* exit(tst->os_state.exitcode) */
-          : "=m" (tst->status)
-          : "r" (vgts_empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
-      }
-
-      VG_(core_panic)("Thread exit failed?\n");
-   }
-
-  /*NOTREACHED*/
-  vg_assert(0);
-}
-
-
 /* Call f(arg1), but first switch stacks, using 'stack' as the new
-  stack, and use 'retaddr' as f's return-to address.  Also, clear all
+   stack, and use 'retaddr' as f's return-to address.  Also, clear all
    the integer registers before entering f.*/
 __attribute__((noreturn))
-void call_on_new_stack_0_1 ( Addr stack,
-                             Addr retaddr,
-                             void (*f)(Word),
-                             Word arg1 );
+void ML_(call_on_new_stack_0_1) ( Addr stack,
+                                  Addr retaddr,
+                                  void (*f)(Word),
+                                  Word arg1 );
 //    r3 = stack
 //    r4 = retaddr
 //    r5 = f
 //    r6 = arg1
 asm(
-"call_on_new_stack_0_1:\n"
+".globl vgModuleLocal_call_on_new_stack_0_1\n"
+"vgModuleLocal_call_on_new_stack_0_1:\n"
 "   mr    %r1,%r3\n\t"     // stack to %sp
 "   mtlr  %r4\n\t"         // retaddr to %lr
 "   mtctr %r5\n\t"         // f to count reg
@@ -233,53 +113,6 @@ asm(
 );
 
 
-/* Allocate a stack for the main thread, and run it all the way to the
-   end.  Although we already have a working VgStack
-   (VG_(interim_stack)) it's better to allocate a new one, so that
-   overflow detection works uniformly for all threads.
-*/
-void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
-{
-   Addr sp;
-   VG_(debugLog)(1, "syswrap-ppc32-linux", 
-                    "entering VG_(main_thread_wrapper_NORETURN)\n");
-
-   sp = allocstack(tid);
-
-   /* make a stack frame */
-   sp -= 16;
-   sp &= ~0xF;
-   *(UWord *)sp = 0;
-
-   /* If we can't even allocate the first thread's stack, we're hosed.
-      Give up. */
-   vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
-
-   /* shouldn't be any other threads around yet */
-   vg_assert( VG_(count_living_threads)() == 1 );
-
-   call_on_new_stack_0_1( 
-      (Addr)sp,             /* 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_NORETURN ( void* arg )
-{
-   ThreadState* tst = (ThreadState*)arg;
-   ThreadId     tid = tst->tid;
-
-   run_a_thread_NORETURN ( (Word)tid );
-   /*NOTREACHED*/
-   vg_assert(0);
-}
-
-
 /* ---------------------------------------------------------------------
    clone() handling
    ------------------------------------------------------------------ */
@@ -417,7 +250,7 @@ static SysRes do_clone ( ThreadId ptid,
    vg_assert(VG_(is_running_thread)(ptid));
    vg_assert(VG_(is_valid_tid)(ctid));
 
-   stack = (UWord*)allocstack(ctid);
+   stack = (UWord*)ML_(allocstack)(ctid);
    if (stack == NULL) {
       res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
       goto out;
@@ -495,7 +328,7 @@ static SysRes do_clone ( ThreadId ptid,
 
    /* Create the new thread */
    word64 = do_syscall_clone_ppc32_linux(
-               start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
+               ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
                child_tidptr, parent_tidptr, NULL
             );
    /* High half word64 is syscall return value.  Low half is
index 3e804bedbfdc4f963d647cffefa8a23bc0420aa2..6ea89dafda41d71e33c35cc5922b56bdcd50010f 100644 (file)
    Note.  Why is this stuff here?
    ------------------------------------------------------------------ */
 
-/* Allocate a stack for this thread.  They're allocated lazily, and
-   never freed. */
-
-/* Allocate a stack for this thread, if it doesn't already have one.
-   Returns the initial stack pointer value to use, or 0 if allocation
-   failed. */
-
-static Addr allocstack ( ThreadId tid )
-{
-   ThreadState* tst = VG_(get_ThreadState)(tid);
-   VgStack*     stack;
-   Addr         initial_SP;
-
-   /* Either the stack_base and stack_init_SP are both zero (in which
-      case a stack hasn't been allocated) or they are both non-zero,
-      in which case it has. */
-
-   if (tst->os_state.valgrind_stack_base == 0)
-      vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
-
-   if (tst->os_state.valgrind_stack_base != 0)
-      vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
-
-   /* If no stack is present, allocate one. */
-
-   if (tst->os_state.valgrind_stack_base == 0) {
-      stack = VG_(am_alloc_VgStack)( &initial_SP );
-      if (stack) {
-         tst->os_state.valgrind_stack_base    = (Addr)stack;
-         tst->os_state.valgrind_stack_init_SP = initial_SP;
-      }
-   }
-
-   if (0)
-      VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
-                   tid, 
-                   (void*)tst->os_state.valgrind_stack_base, 
-                   (void*)tst->os_state.valgrind_stack_init_SP );
-                  
-   return tst->os_state.valgrind_stack_init_SP;
-}
-
-
-/* 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;
-   VgSchedReturnCode src;
-   Int c;
-
-   VG_(debugLog)(1, "syswrap-x86-linux", 
-                    "run_a_thread_NORETURN(tid=%lld): "
-                       "ML_(thread_wrapper) called\n",
-                       (ULong)tidW);
-
-   /* Run the thread all the way through. */
-   src = ML_(thread_wrapper)(tid);  
-
-   VG_(debugLog)(1, "syswrap-x86-linux", 
-                    "run_a_thread_NORETURN(tid=%lld): "
-                       "ML_(thread_wrapper) done\n",
-                       (ULong)tidW);
-
-   c = VG_(count_living_threads)();
-   vg_assert(c >= 1); /* stay sane */
-
-   if (c == 1) {
-
-      VG_(debugLog)(1, "syswrap-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. 
-         Use the continuation pointer set at startup in m_main. */
-      ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
-
-   } else {
-
-      ThreadState *tst;
-
-      VG_(debugLog)(1, "syswrap-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. */
-      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 */
-         "movl %2, %%eax\n"    /* set %eax = __NR_exit */
-         "movl %3, %%ebx\n"    /* set %ebx = tst->os_state.exitcode */
-         "int  $0x80\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);
-}
-
-
 /* Call f(arg1), but first switch stacks, using 'stack' as the new
    stack, and use 'retaddr' as f's return-to address.  Also, clear all
    the integer registers before entering f.*/
 __attribute__((noreturn))
-void call_on_new_stack_0_1 ( Addr stack,
-                            Addr retaddr,
-                            void (*f)(Word),
-                             Word arg1 );
+void ML_(call_on_new_stack_0_1) ( Addr stack,
+                                 Addr retaddr,
+                                 void (*f)(Word),
+                                  Word arg1 );
 //  4(%esp) == stack
 //  8(%esp) == retaddr
 // 12(%esp) == f
 // 16(%esp) == arg1
 asm(
-"call_on_new_stack_0_1:\n"
+".globl vgModuleLocal_call_on_new_stack_0_1\n"
+"vgModuleLocal_call_on_new_stack_0_1:\n"
 "   movl %esp, %esi\n"     // remember old stack pointer
 "   movl 4(%esi), %esp\n"  // set stack
 "   pushl 16(%esi)\n"      // arg1 to stack
@@ -217,50 +98,6 @@ asm(
 );
 
 
-/* Allocate a stack for the main thread, and run it all the way to the
-   end.  Although we already have a working VgStack
-   (VG_(interim_stack)) it's better to allocate a new one, so that
-   overflow detection works uniformly for all threads.
-*/
-void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
-{
-   Addr esp;
-
-   VG_(debugLog)(1, "syswrap-x86-linux", 
-                    "entering VG_(main_thread_wrapper_NORETURN)\n");
-
-   esp = allocstack(tid);
-
-   /* If we can't even allocate the first thread's stack, we're hosed.
-      Give up. */
-   vg_assert2(esp != 0, "Cannot allocate main thread's stack.");
-
-   /* shouldn't be any other threads around yet */
-   vg_assert( VG_(count_living_threads)() == 1 );
-
-   call_on_new_stack_0_1( 
-      esp,                    /* 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_NORETURN ( void* arg )
-{
-   ThreadState* tst = (ThreadState*)arg;
-   ThreadId     tid = tst->tid;
-
-   run_a_thread_NORETURN ( (Word)tid );
-   /*NOTREACHED*/
-   vg_assert(0);
-}
-
-
 /* ---------------------------------------------------------------------
    clone() handling
    ------------------------------------------------------------------ */
@@ -388,7 +225,7 @@ static SysRes do_clone ( ThreadId ptid,
    vg_assert(VG_(is_running_thread)(ptid));
    vg_assert(VG_(is_valid_tid)(ctid));
 
-   stack = (UWord*)allocstack(ctid);
+   stack = (UWord*)ML_(allocstack)(ctid);
    if (stack == NULL) {
       res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
       goto out;
@@ -464,7 +301,7 @@ static SysRes do_clone ( ThreadId ptid,
 
    /* Create the new thread */
    eax = do_syscall_clone_x86_linux(
-            start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
+            ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
             child_tidptr, parent_tidptr, NULL
          );
    res = VG_(mk_SysRes_x86_linux)( eax );