/// <summary> /// Transform to next state by choice in the order of /// .Execute the current instruction /// .Complete one of the pending actions /// </summary> /// <param name="choice">Indicate the index of the transition to execute</param> public void Forward(int choice) { if((syncState == SyncState.RUNNING) && (pc != null) && (pc.CanExecute(this))) { if(choice == 0) { if(CheckerConfiguration.DoPrintExecution) Console.WriteLine("Thread {0} executing {1}", currentMethod.ToString(), pc.ToString()); pc = pc.Execute(this); GreedyPORExecution(); return; } else { choice--; } } // we didn't have to execute the pc // instead now we have to execute one of the pending actions for(int i = 0; i < pendingActions.Count; i++) if(IsDelayedActionLocal(i) == false) if(CanCompleteAction(i)) { if(pendingActions[i] is DelayedPulse) { DelayedPulse dp = (DelayedPulse)pendingActions[i]; if(dp.isPulseAll) choice--; else { int ctwo = systemState.CountThreadWaitingOn(dp.obj); if(ctwo == 0) ctwo = 1; choice -= ctwo; } } else choice--; if(choice < 0) { DelayedAction da = (DelayedAction)pendingActions[i]; if(da is DelayedWait) { DelayedWait dw = (DelayedWait)da; DelayedLock dl = new DelayedLock(dw.obj, dw.SourceInstruction, dw.lockCount); pendingActions[i] = dl; } else if(da is DelayedPulse) { DelayedPulse dp = (DelayedPulse)da; if(dp.isPulseAll == true) { foreach(ThreadState ts in systemState.threads) if((ts.syncState == ThreadState.SyncState.WAITING) && (ts.waitingOn == dp.obj)) { ts.syncState = ThreadState.SyncState.RUNNING; ts.waitingOn = -1; } } else { // only if there is at least one thread waiting we resume it // else we don't do anything in completing this pulse // in another word, the pulse signal is lost int ctwo = systemState.CountThreadWaitingOn(dp.obj); if(ctwo > 0) { for(int j = 0; j < systemState.threads.Count; j++) { ThreadState ts = (ThreadState)systemState.threads[j]; if((ts.syncState == SyncState.WAITING) && (ts.waitingOn == dp.obj)) { choice++; if(choice == 0) { ts.syncState = SyncState.RUNNING; ts.waitingOn = -1; break; } } } } } pendingActions.RemoveAt(i); } else { pendingActions.RemoveAt(i); da.Complete(this); } GreedyPORExecution(); break; } } }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { VMValue_double v, vnew, vpower, vbase; VMValue_int32 vint; if(CanExecute(threadState) == false) throw new Exception("Something's wrong, executing assertion when value is not ready"); if(theMethod.ParentClass.Name == "[mscorlib]System.Object") { if(theMethod.Name == ".ctor") return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.ParentClass.Name == "MMC") { // this is the checker's assertion class if(theMethod.Name == "Report") { vint = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); threadState.SystemState.Report(vint.Value); } return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Thread") { // just go pass this instruction because the CanExecute() has made sure // that there is incomplete bytecodes if(theMethod.Name == "MemoryBarrier") return threadState.CurrentMethod.GetNextInstruction(this); else throw new Exception("Not supported function " + theMethod.ParentClass.Name + "::" + theMethod.Name); } else if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Monitor") { if(theMethod.Name == "Enter") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedLock dl = new DelayedLock(obj.ValueGUID, this); threadState.AddPendingAction(dl); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Exit") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedUnlock du = new DelayedUnlock(obj.ValueGUID, this); threadState.AddPendingAction(du); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Wait") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedWait du = new DelayedWait(obj.ValueGUID, this, 0); threadState.AddPendingAction(du); // set this thread to waiting threadState.syncState = ThreadState.SyncState.WAITING; threadState.waitingOn = obj.ValueGUID; // release the lock VMValue_objectinst objinst = (VMValue_objectinst)threadState.GetValue(obj.ValueGUID); du.lockCount = objinst.HoldingLockCount; objinst.HoldingLockCount = 0; objinst.HoldingLockThreadID = -1; // TODO: Now wait always return 1, change to reflect the result of the call VMValue_int32 theConstant = (VMValue_int32)threadState.SystemState.Values.MakeValue(new CILVar_int32("")); theConstant.Value = 1; theConstant.IsThreadLocal = true; theConstant.IsConcrete = true; threadState.ThreadStack.Push(theConstant.GUID); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Pulse") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedPulse du = new DelayedPulse(obj.ValueGUID, this, false); threadState.AddPendingAction(du); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "PulseAll") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedPulse du = new DelayedPulse(obj.ValueGUID, this, true); threadState.AddPendingAction(du); return threadState.CurrentMethod.GetNextInstruction(this); }else throw new Exception("Function " + theMethod.Name + " of class Monitor is not supported"); } else if(theMethod.ParentClass.Name == "[mscorlib]System.Math") { // arithmetic instructions, just do the mathematics associated with each switch(theMethod.Name) { case "Abs": v = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(v); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Abs(v.Value); threadState.ThreadStack.Push(vnew.GUID); break; case "Sin": v = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(v); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Sin(v.Value); threadState.ThreadStack.Push(vnew.GUID); break; case "Cos": v = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(v); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Cos(v.Value); threadState.ThreadStack.Push(vnew.GUID); break; case "Pow": vpower = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vbase = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(vpower); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Pow(vbase.Value, vpower.Value); threadState.ThreadStack.Push(vnew.GUID); break; default: throw new Exception("Not supported function of [mscorlib]System.Math"); } return threadState.CurrentMethod.GetNextInstruction(this); } return threadState.CallFunction(theMethod); }