]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge (from branches/THRCHECK) r6804:
authorJulian Seward <jseward@acm.org>
Fri, 9 Nov 2007 23:13:22 +0000 (23:13 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 9 Nov 2007 23:13:22 +0000 (23:13 +0000)
Split the scheduler initialisation into two phases, for reasons I
can't exactly remember.  But I think it was so that the tool can be
told of the initial thread's TID before it is notified of any initial
address range permissions.  Or something like that.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7121

coregrind/m_main.c
coregrind/m_scheduler/scheduler.c
coregrind/pub_core_scheduler.h

index 2b5929449b6f80b0bd71433853fc24b08a5b757d..ca9dc4b98df1b46dae877f9fbd7f4cbc78eff4f1 100644 (file)
@@ -1174,6 +1174,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    HChar*  toolname           = "memcheck";    // default to Memcheck
    Int     need_help          = 0; // 0 = no, 1 = --help, 2 = --help-debug
    UInt*   client_auxv        = NULL;
+   ThreadId tid_main          = VG_INVALID_THREADID;
    Int     loglevel, i;
    Bool    logging_to_fd;
    struct vki_rlimit zero = { 0, 0 };
@@ -1765,6 +1766,17 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
      vg_assert(change_ownership_v_c_OK);
    }
 
+   //--------------------------------------------------------------
+   // Initialise the scheduler (phase 1) [generates tid_main]
+   //   p: none, afaics
+   //--------------------------------------------------------------
+   VG_(debugLog)(1, "main", "Initialise scheduler (phase 1)\n");
+   tid_main = VG_(scheduler_init_phase1)();
+   vg_assert(tid_main >= 0 && tid_main < VG_N_THREADS
+             && tid_main != VG_INVALID_THREADID);
+   /* Tell the tool about tid_main */
+   VG_TRACK( pre_thread_ll_create, VG_INVALID_THREADID, tid_main );
+   
    //--------------------------------------------------------------
    // Tell the tool about the initial client memory permissions
    //   p: aspacem
@@ -1837,18 +1849,20 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    }
 
    //--------------------------------------------------------------
-   // Initialise the scheduler
+   // Initialise the scheduler (phase 2)
+   //   p: Initialise the scheduler (phase 1) [for tid_main]
    //   p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
    //   p: setup_client_stack
    //--------------------------------------------------------------
-   VG_(debugLog)(1, "main", "Initialise scheduler\n");
+   VG_(debugLog)(1, "main", "Initialise scheduler (phase 2)\n");
    { NSegment const* seg 
         = VG_(am_find_nsegment)( the_iifii.initial_client_SP );
      vg_assert(seg);
      vg_assert(seg->kind == SkAnonC);
      vg_assert(the_iifii.initial_client_SP >= seg->start);
      vg_assert(the_iifii.initial_client_SP <= seg->end);
-     VG_(scheduler_init)( seg->end, the_iifii.clstack_max_size );
+     VG_(scheduler_init_phase2)( tid_main, 
+                                 seg->end, the_iifii.clstack_max_size );
    }
 
    //--------------------------------------------------------------
index 1978adc827d3df71e55a385abc136914337c309f..f63d89bc9ad2a8b3227c7203596905ad4c1c46d6 100644 (file)
@@ -437,21 +437,16 @@ static void sched_fork_cleanup(ThreadId me)
 }
 
 
-/* Initialise the scheduler.  Create a single "main" thread ready to
-   run, with special ThreadId of one.  This is called at startup.  The
-   caller subsequently initialises the guest state components of this
-   main thread, thread 1.  
+/* First phase of initialisation of the scheduler.  Initialise the
+   bigLock, zeroise the VG_(threads) structure and decide on the
+   ThreadId of the root thread.
 */
-void VG_(scheduler_init) ( Addr clstack_end, SizeT clstack_size )
+ThreadId VG_(scheduler_init_phase1) ( void )
 {
    Int i;
    ThreadId tid_main;
 
-   VG_(debugLog)(1,"sched","sched_init: cls_end=0x%lx, cls_sz=%ld\n",
-                   clstack_end, clstack_size);
-
-   vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
-   vg_assert(VG_IS_PAGE_ALIGNED(clstack_size));
+   VG_(debugLog)(1,"sched","sched_init_phase1\n");
 
    ML_(sema_init)(&the_BigLock);
 
@@ -470,7 +465,27 @@ void VG_(scheduler_init) ( Addr clstack_end, SizeT clstack_size )
    }
 
    tid_main = VG_(alloc_ThreadState)();
-   vg_assert(tid_main == 1);
+
+   return tid_main;
+}
+
+
+/* Second phase of initialisation of the scheduler.  Given the root
+   ThreadId computed by first phase of initialisation, fill in stack
+   details and acquire bigLock.  Initialise the scheduler.  This is
+   called at startup.  The caller subsequently initialises the guest
+   state components of this main thread.
+*/
+void VG_(scheduler_init_phase2) ( ThreadId tid_main,
+                                  Addr     clstack_end, 
+                                  SizeT    clstack_size )
+{
+   VG_(debugLog)(1,"sched","sched_init_phase2: tid_main=%d, "
+                   "cls_end=0x%lx, cls_sz=%ld\n",
+                   tid_main, clstack_end, clstack_size);
+
+   vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
+   vg_assert(VG_IS_PAGE_ALIGNED(clstack_size));
 
    VG_(threads)[tid_main].client_stack_highest_word 
       = clstack_end + 1 - sizeof(UWord);
@@ -625,6 +640,7 @@ static UInt run_thread_for_a_while ( ThreadId tid )
                                       VG_(clo_profile_flags) > 0 ? 1 : 0 )
    );
 
+   vg_assert(VG_(in_generated_code) == True);
    VG_(in_generated_code) = False;
 
    if (jumped) {
index 848ec0b4fc6c48673f46491b96616cf8cc5e1866..866e2520566f198f278b05263d54989338c8ed9e 100644 (file)
@@ -75,8 +75,15 @@ extern void VG_(vg_yield)(void);
 // The scheduler.
 extern VgSchedReturnCode VG_(scheduler) ( ThreadId tid );
 
-// Initialise.  Is passed the extent of the root thread's client stack.
-extern void VG_(scheduler_init) ( Addr clstack_end, SizeT clstack_size );
+// Initialise, phase 1.  Zero out VG_(threads), decide on the root
+// ThreadId and initialise the bigLock.
+extern ThreadId VG_(scheduler_init_phase1) ( void );
+
+// Initialise, phase 2.  Is passed the extent of the root thread's
+// client stack and the root ThreadId decided on by phase 1.
+extern void VG_(scheduler_init_phase2) ( ThreadId main_tid, 
+                                         Addr     clstack_end, 
+                                         SizeT    clstack_size );
 
 /* Stats ... */
 extern void VG_(print_scheduler_stats) ( void );