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 };
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
}
//--------------------------------------------------------------
- // 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 );
}
//--------------------------------------------------------------
}
-/* 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);
}
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);
VG_(clo_profile_flags) > 0 ? 1 : 0 )
);
+ vg_assert(VG_(in_generated_code) == True);
VG_(in_generated_code) = False;
if (jumped) {
// 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 );