Esempio n. 1
0
        /// <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;
                        }
                    }
        }
Esempio n. 2
0
        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);
        }