From: Julian Seward Date: Fri, 9 Nov 2007 23:13:22 +0000 (+0000) Subject: Merge (from branches/THRCHECK) r6804: X-Git-Tag: svn/VALGRIND_3_3_0~168 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30238ecdb25f56a1fd210771148f14594eba4cce;p=thirdparty%2Fvalgrind.git Merge (from branches/THRCHECK) r6804: 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 --- diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 2b5929449b..ca9dc4b98d 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -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 ); } //-------------------------------------------------------------- diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 1978adc827..f63d89bc9a 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -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) { diff --git a/coregrind/pub_core_scheduler.h b/coregrind/pub_core_scheduler.h index 848ec0b4fc..866e252056 100644 --- a/coregrind/pub_core_scheduler.h +++ b/coregrind/pub_core_scheduler.h @@ -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 );