Пример #1
0
        /// <summary>
        /// Notify that a new task has been created for the given machine.
        /// </summary>
        /// <param name="id">TaskId</param>
        /// <param name="machine">Machine</param>
        internal virtual void NotifyNewTaskCreated(int id, AbstractMachine machine)
        {
            var machineInfo = new MachineInfo(id, machine);

            IO.Debug($"<ScheduleDebug> Created task '{machineInfo.Id}' for machine " +
                     $"'{machineInfo.Machine.Id}'.");

            if (this.TaskMap.Count == 0)
            {
                machineInfo.IsActive = true;
            }

            this.TaskMap.TryAdd(id, machineInfo);
        }
Пример #2
0
        /// <summary>
        /// Returns the prioritized machine.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>MachineInfo</returns>
        private MachineInfo GetPrioritizedMachine(List <MachineInfo> choices, MachineInfo current)
        {
            if (this.PrioritizedMachines.Count == 0)
            {
                this.PrioritizedMachines.Add(current.Machine.Id);
            }

            foreach (var mi in choices.Where(mi => !this.PrioritizedMachines.Contains(mi.Machine.Id)))
            {
                var mIndex = this.Random.Next(this.PrioritizedMachines.Count) + 1;
                this.PrioritizedMachines.Insert(mIndex, mi.Machine.Id);
                Debug.WriteLine($"<PCTLog> Detected new machine '{mi.Machine.Id}' at index '{mIndex}'.");
            }

            if (this.PriorityChangePoints.Contains(this.ExploredSteps))
            {
                if (choices.Count == 1)
                {
                    this.MovePriorityChangePointForward();
                }
                else
                {
                    var priority = this.GetHighestPriorityEnabledMachine(choices);
                    this.PrioritizedMachines.Remove(priority);
                    this.PrioritizedMachines.Add(priority);
                    Debug.WriteLine($"<PCTLog> Machine '{priority}' changes to lowest priority.");
                }
            }

            var prioritizedMachine = this.GetHighestPriorityEnabledMachine(choices);

            Debug.WriteLine($"<PCTLog> Prioritized machine '{prioritizedMachine}'.");
            Debug.Write("<PCTLog> Priority list: ");
            for (int idx = 0; idx < this.PrioritizedMachines.Count; idx++)
            {
                if (idx < this.PrioritizedMachines.Count - 1)
                {
                    Debug.Write($"'{this.PrioritizedMachines[idx]}', ");
                }
                else
                {
                    Debug.Write($"'{this.PrioritizedMachines[idx]}({1})'.\n");
                }
            }

            var prioritizedMachineInfo = choices.First(mi => mi.Machine.Id.Equals(prioritizedMachine));

            return(prioritizedMachineInfo);
        }
Пример #3
0
        /// <summary>
        /// Tries to register any new operations.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        private void TryRegisterNewOperations(IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            if (this.Operations.Count == 0)
            {
                this.Operations.Add(current.Machine.OperationId);
            }

            var operationIds = choices.Select(mi => mi.Machine.OperationId).Distinct();

            foreach (var id in operationIds.Where(id => !this.Operations.Contains(id)))
            {
                var opIndex = this.Random.Next(this.Operations.Count) + 1;
                this.Operations.Insert(opIndex, id);
                Debug.WriteLine("<OperationDebug> Detected new operation '{0}' at index '{1}'.", id, opIndex);
            }
        }
Пример #4
0
        /// <summary>
        /// Determines whether the specified System.Object is equal
        /// to the current System.Object.
        /// </summary>
        /// <param name="obj">Object</param>
        /// <returns>Boolean</returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }

            MachineInfo mid = obj as MachineInfo;

            if (mid == null)
            {
                return(false);
            }

            return(this.Id == mid.Id);
        }
Пример #5
0
        /// <summary>
        /// Notify that a new task has been created for the given machine.
        /// </summary>
        /// <param name="id">TaskId</param>
        /// <param name="machine">Machine</param>
        internal override void NotifyNewTaskCreated(int id, AbstractMachine machine)
        {
            var machineInfo = new MachineInfo(id, machine);

            IO.Debug($"<ScheduleDebug> Created task '{machineInfo.Id}' for machine " +
                     $"'{machineInfo.Machine.Id}'.");

            if (base.TaskMap.Count == 0)
            {
                machineInfo.IsActive = true;
            }

            base.TaskMap.TryAdd(id, machineInfo);

            if (machine is TaskMachine)
            {
                this.WrappedTaskMap.TryAdd((machine as TaskMachine).WrappedTask.Id, machineInfo);
            }
        }
Пример #6
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                mi => mi.IsEnabled && !mi.IsBlocked && !mi.IsWaitingToReceive).ToList();

            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return(false);
                }
            }

            next = this.GetPrioritizedMachine(availableMachines, current);
            this.ExploredSteps++;

            return(true);
        }
        /// <summary>
        /// Notify that a new task has been created for the given machine.
        /// </summary>
        /// <param name="id">TaskId</param>
        /// <param name="machine">Machine</param>
        internal override void NotifyNewTaskCreated(int id, AbstractMachine machine)
        {
            var machineInfo = new MachineInfo(id, machine);

            IO.Debug($"<ScheduleDebug> Created task '{machineInfo.Id}' for machine " +
                $"'{machineInfo.Machine.Id}'.");

            if (base.MachineInfos.Count == 0)
            {
                machineInfo.IsActive = true;
            }

            base.MachineInfos.Add(machineInfo);
            base.TaskMap.TryAdd(id, machineInfo);

            if (machine is TaskMachine)
            {
                this.WrappedTaskMap.TryAdd((machine as TaskMachine).WrappedTask.Id, machineInfo);
            }
        }
Пример #8
0
        /// <summary>
        /// Returns the next operation to schedule.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>OperationId</returns>
        protected override int GetNextOperation(List <MachineInfo> choices, MachineInfo current)
        {
            var operationIds = choices.Select(val => val.Machine.OperationId).Distinct();

            if (this.PriorityChangePoints.Contains(this.ExploredSteps))
            {
                if (operationIds.Count() == 1)
                {
                    this.MovePriorityChangePointForward();
                }
                else
                {
                    var priority = this.GetHighestPriorityEnabledOperationId(choices);
                    base.Operations.Remove(priority);
                    base.Operations.Add(priority);
                    Debug.WriteLine("<OperationLog> Operation '{0}' changes to lowest priority.", priority);
                }
            }

            return(this.GetHighestPriorityEnabledOperationId(choices));
        }
Пример #9
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public virtual bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            var machines = choices.OrderBy(mi => mi.Machine.Id.Value).ToList();

            var currentMachineIdx = machines.IndexOf(current);
            var orderedMachines   = machines.GetRange(currentMachineIdx, machines.Count - currentMachineIdx);

            if (currentMachineIdx != 0)
            {
                orderedMachines.AddRange(machines.GetRange(0, currentMachineIdx));
            }

            var availableMachines = orderedMachines.Where(
                mi => mi.IsEnabled && !mi.IsBlocked && !mi.IsWaitingToReceive).ToList();

            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return(false);
                }
            }

            int idx = 0;

            while (this.RemainingDelays.Count > 0 && this.ExploredSteps == this.RemainingDelays[0])
            {
                idx = (idx + 1) % availableMachines.Count;
                this.RemainingDelays.RemoveAt(0);
                IO.PrintLine("<DelayLog> Inserted delay, '{0}' remaining.", this.RemainingDelays.Count);
            }

            next = availableMachines[idx];

            this.ExploredSteps++;

            return(true);
        }
Пример #10
0
        /// <summary>
        /// Notify that the task has started.
        /// </summary>
        internal override void NotifyTaskStarted()
        {
            int?id = Task.CurrentId;

            if (id == null)
            {
                return;
            }

            MachineInfo machineInfo = null;

            if (!(base.TaskMap.TryGetValue((int)id, out machineInfo) ||
                  this.WrappedTaskMap.TryGetValue((int)id, out machineInfo)))
            {
                IO.Debug($"<ScheduleDebug> Unable to start task '{id}'.");
                base.Stop();
            }

            IO.Debug($"<ScheduleDebug> Started task '{machineInfo.Id}' of machine " +
                     $"'{machineInfo.Machine.Id}'.");

            lock (machineInfo)
            {
                machineInfo.HasStarted = true;
                System.Threading.Monitor.PulseAll(machineInfo);
                while (!machineInfo.IsActive)
                {
                    IO.Debug($"<ScheduleDebug> Sleep task '{machineInfo.Id}' of machine " +
                             $"'{machineInfo.Machine.Id}'.");
                    System.Threading.Monitor.Wait(machineInfo);
                    IO.Debug($"<ScheduleDebug> Wake up task '{machineInfo.Id}' of machine " +
                             $"'{machineInfo.Machine.Id}'.");
                }

                if (!machineInfo.IsEnabled)
                {
                    throw new OperationCanceledException();
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsWaitingToReceive).ToList();

            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return(false);
                }
            }

            if (this.ExploredSteps >= this.ScheduleTrace.Count)
            {
                Error.ReportAndExit("Trace is not reproducible: execution is longer than trace.");
            }

            ScheduleStep nextStep = this.ScheduleTrace[this.ExploredSteps];

            if (nextStep.Type != ScheduleStepType.SchedulingChoice)
            {
                Error.ReportAndExit("Trace is not reproducible: next step is not a scheduling choice.");
            }

            next = availableMachines.FirstOrDefault(m => m.Machine.Id.Type.Equals(
                                                        nextStep.ScheduledMachineId.Type) &&
                                                    m.Machine.Id.Value == nextStep.ScheduledMachineId.Value);
            if (next == null)
            {
                Error.ReportAndExit("Trace is not reproducible: cannot detect machine with type " +
                                    $"'{nextStep.ScheduledMachineId.Type}' and id '{nextStep.ScheduledMachineId.Value}'.");
            }

            this.ExploredSteps++;

            return(true);
        }
Пример #12
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();

            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return(false);
                }
            }

            int idx = this.Random.Next(availableMachines.Count);

            next = availableMachines[idx];

            this.ExploredSteps++;

            return(true);
        }
Пример #13
0
        /// <summary>
        /// Returns the prioritized machines.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        private List <MachineInfo> GetPrioritizedMachines(List <MachineInfo> choices, MachineInfo current)
        {
            choices = choices.OrderBy(mi => mi.Machine.Id.Value).ToList();
            choices = choices.OrderBy(mi => mi.Machine.OperationId).ToList();

            MachineInfo priorityMachine     = current;
            var         prioritizedMachines = new List <MachineInfo>();

            if (current.Machine.OperationId == this.PrioritizedOperationId)
            {
                var currentMachineIdx = choices.IndexOf(current);
                prioritizedMachines = choices.GetRange(currentMachineIdx, choices.Count - currentMachineIdx);
                if (currentMachineIdx != 0)
                {
                    prioritizedMachines.AddRange(choices.GetRange(0, currentMachineIdx));
                }
            }
            else
            {
                priorityMachine = choices.First(mi => mi.Machine.OperationId == this.PrioritizedOperationId);
                var priorityMachineIdx = choices.IndexOf(priorityMachine);
                prioritizedMachines = choices.GetRange(priorityMachineIdx, choices.Count - priorityMachineIdx);
                if (priorityMachineIdx != 0)
                {
                    prioritizedMachines.AddRange(choices.GetRange(0, priorityMachineIdx));
                }
            }

            prioritizedMachines = prioritizedMachines.Where(
                mi => mi.IsEnabled && !mi.IsWaitingToReceive).ToList();
            if (prioritizedMachines.Count == 0)
            {
                return(prioritizedMachines);
            }

            return(prioritizedMachines);
        }
Пример #14
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();

            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return(false);
                }
            }

            SChoice        nextChoice = null;
            List <SChoice> scs        = null;

            if (this.SchIndex < this.ScheduleStack.Count)
            {
                scs = this.ScheduleStack[this.SchIndex];
            }
            else
            {
                scs = new List <SChoice>();
                foreach (var task in availableMachines)
                {
                    scs.Add(new SChoice(task.Machine.Id.Value));
                }

                this.ScheduleStack.Add(scs);
            }

            nextChoice = scs.FirstOrDefault(val => !val.IsDone);
            if (nextChoice == null)
            {
                next = null;
                return(false);
            }

            if (this.SchIndex > 0)
            {
                var previousChoice = this.ScheduleStack[this.SchIndex - 1].Last(val => val.IsDone);
                previousChoice.IsDone = false;
            }

            next = availableMachines.Find(task => task.Machine.Id.Value == nextChoice.Id);
            nextChoice.IsDone = true;
            this.SchIndex++;

            if (next == null)
            {
                return(false);
            }

            this.ExploredSteps++;

            return(true);
        }
Пример #15
0
        /// <summary>
        /// Schedules the next machine to execute.
        /// </summary>
        internal override void Schedule()
        {
            int?id = Task.CurrentId;

            if (id == null || id == base.Runtime.RootTaskId)
            {
                return;
            }

            if (this.BugFound || !base.IsSchedulerRunning)
            {
                base.Stop();
            }

            // Checks if the scheduling steps bound has been reached.
            this.CheckIfSchedulingStepsBoundIsReached(true);

            foreach (var task in base.TaskMap.Values.Where(val => val.IsBlocked))
            {
                foreach (var userTask in this.UserTasks.Where(val => val.IsCompleted))
                {
                    if (task.BlockingUnwrappedTasks.Contains(userTask))
                    {
                        task.BlockingUnwrappedTasks.Remove(userTask);
                        if (!task.WaitAll)
                        {
                            task.BlockingWrappedTasks.Clear();
                            task.BlockingUnwrappedTasks.Clear();
                            task.IsBlocked = false;
                            break;
                        }
                    }
                }

                if (task.WaitAll && task.BlockingWrappedTasks.Count == 0 &&
                    task.BlockingUnwrappedTasks.Count == 0)
                {
                    task.WaitAll   = false;
                    task.IsBlocked = false;
                }

                if (!task.IsBlocked)
                {
                    IO.Debug($"<ScheduleDebug> Unblocked task '{task.Id}' of machine " +
                             $"'{task.Machine.Id}'.");
                }
            }

            MachineInfo machineInfo = null;

            if (!(base.TaskMap.TryGetValue((int)id, out machineInfo) ||
                  this.WrappedTaskMap.TryGetValue((int)id, out machineInfo)))
            {
                IO.Debug($"<ScheduleDebug> Unable to schedule task '{id}'.");
                base.Stop();
            }

            MachineInfo next = null;

            if (!this.Strategy.TryGetNext(out next, this.TaskMap.Values, machineInfo))
            {
                IO.Debug("<ScheduleDebug> Schedule explored.");
                this.HasFullyExploredSchedule = true;
                base.Stop();
            }

            base.Runtime.ScheduleTrace.AddSchedulingChoice(next.Machine.Id);

            // Checks the liveness monitors for potential liveness bugs.
            base.Runtime.LivenessChecker.CheckLivenessAtShedulingStep();
            if (base.Runtime.Configuration.CacheProgramState &&
                base.Runtime.Configuration.SafetyPrefixBound <= this.ExploredSteps)
            {
                base.Runtime.StateCache.CaptureState(base.Runtime.ScheduleTrace.Peek());
            }

            IO.Debug($"<ScheduleDebug> Schedule task '{next.Id}' of machine " +
                     $"'{next.Machine.Id}'.");

            if (next.IsWaitingToReceive)
            {
                string message = IO.Format("Livelock detected. Machine " +
                                           $"'{next.Machine.Id}' is waiting for an event, " +
                                           "but no other machine is enabled.");
                base.Runtime.BugFinder.NotifyAssertionFailure(message, true);
            }

            if (machineInfo != next)
            {
                machineInfo.IsActive = false;
                lock (next)
                {
                    next.IsActive = true;
                    System.Threading.Monitor.PulseAll(next);
                }

                lock (machineInfo)
                {
                    if (machineInfo.IsCompleted)
                    {
                        return;
                    }

                    while (!machineInfo.IsActive)
                    {
                        IO.Debug($"<ScheduleDebug> Sleep task '{machineInfo.Id}' of machine " +
                                 $"'{machineInfo.Machine.Id}'.");
                        System.Threading.Monitor.Wait(machineInfo);
                        IO.Debug($"<ScheduleDebug> Wake up task '{machineInfo.Id}' of machine " +
                                 $"'{machineInfo.Machine.Id}'.");
                    }

                    if (!machineInfo.IsEnabled)
                    {
                        throw new OperationCanceledException();
                    }
                }
            }
        }
        /// <summary>
        /// Returns the next operation to schedule.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>OperationId</returns>
        protected override int GetNextOperation(List<MachineInfo> choices, MachineInfo current)
        {
            int idx = this.Random.Next(choices.Count);
            var machineWithNextOperation = choices[idx];
            return machineWithNextOperation.Machine.OperationId;

            //var enabledOperations = base.Operations.Where(val => choices.Any(
            //    m => m.Machine.OperationId == val)).ToList();
            //int opIdx = base.Random.Next(enabledOperations.Count);
            //return enabledOperations[opIdx];
        }
Пример #17
0
        /// <summary>
        /// Schedules the next machine to execute.
        /// </summary>
        internal void Schedule()
        {
            int?taskId = Task.CurrentId;

            // If the caller is the root task, then return.
            if (taskId != null && taskId == this.Runtime.RootTaskId)
            {
                return;
            }

            if (!this.IsSchedulerRunning)
            {
                this.Stop();
            }

            // Checks if synchronisation not controlled by P# was used.
            this.CheckIfExternalSynchronizationIsUsed();

            // Checks if the scheduling steps bound has been reached.
            this.CheckIfSchedulingStepsBoundIsReached();

            MachineInfo machineInfo = this.TaskMap[(int)taskId];
            MachineInfo next        = null;

            var choices = this.TaskMap.Values.OrderBy(mi => mi.Machine.Id.Value);

            if (!this.Strategy.TryGetNext(out next, choices, machineInfo))
            {
                Debug.WriteLine("<ScheduleDebug> Schedule explored.");
                this.HasFullyExploredSchedule = true;
                this.Stop();
            }

            this.ScheduledMachine = next;

            this.Runtime.ScheduleTrace.AddSchedulingChoice(next.Machine.Id);
            next.Machine.ProgramCounter = 0;

            if (this.Runtime.Configuration.CacheProgramState &&
                this.Runtime.Configuration.SafetyPrefixBound <= this.ExploredSteps)
            {
                this.Runtime.StateCache.CaptureState(this.Runtime.ScheduleTrace.Peek());
            }

            // Checks the liveness monitors for potential liveness bugs.
            this.Runtime.LivenessChecker.CheckLivenessAtShedulingStep();

            Debug.WriteLine($"<ScheduleDebug> Schedule task '{next.Id}' of machine " +
                            $"'{next.Machine.Id}'.");

            if (next.IsWaitingToReceive)
            {
                string message = IO.Utilities.Format("Livelock detected. Machine " +
                                                     $"'{next.Machine.Id}' is waiting for an event, " +
                                                     "but no other machine is enabled.");
                this.Runtime.Scheduler.NotifyAssertionFailure(message, true);
            }

            if (machineInfo != next)
            {
                machineInfo.IsActive = false;
                lock (next)
                {
                    next.IsActive = true;
                    System.Threading.Monitor.PulseAll(next);
                }

                lock (machineInfo)
                {
                    if (machineInfo.IsCompleted)
                    {
                        return;
                    }

                    while (!machineInfo.IsActive)
                    {
                        Debug.WriteLine($"<ScheduleDebug> Sleep task '{machineInfo.Id}' of machine " +
                                        $"'{machineInfo.Machine.Id}'.");
                        System.Threading.Monitor.Wait(machineInfo);
                        Debug.WriteLine($"<ScheduleDebug> Wake up task '{machineInfo.Id}' of machine " +
                                        $"'{machineInfo.Machine.Id}'.");
                    }

                    if (!machineInfo.IsEnabled)
                    {
                        throw new ExecutionCanceledException();
                    }
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                mi => mi.IsEnabled && !mi.IsBlocked && !mi.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            next = this.GetPrioritizedMachine(availableMachines, current);
            this.ExploredSteps++;

            return true;
        }
Пример #19
0
 /// <summary>
 /// Returns the next operation to schedule.
 /// </summary>
 /// <param name="choices">Choices</param>
 /// <param name="current">Curent</param>
 /// <returns>OperationId</returns>
 protected abstract int GetNextOperation(List <MachineInfo> choices, MachineInfo current);
Пример #20
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            if (this.HasCurrentOperationCompleted(choices, current))
            {
                this.Operations.Remove(current.Machine.OperationId);
                Debug.WriteLine("<OperationDebug> Removes operation '{0}'.", current.Machine.OperationId);
            }

            var availableMachines = choices.Where(
                mi => mi.IsEnabled && !mi.IsWaitingToReceive).ToList();

            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return(false);
                }
            }

            this.TryRegisterNewOperations(availableMachines, current);

            var nextOperation = this.GetNextOperation(availableMachines, current);

            Debug.WriteLine("<OperationDebug> Chosen operation '{0}'.", nextOperation);
            Debug.Write("<OperationDebug> Operation list: ");
            for (int opIdx = 0; opIdx < this.Operations.Count; opIdx++)
            {
                if (opIdx < this.Operations.Count - 1)
                {
                    Debug.Write("'{0}', ", this.Operations[opIdx]);
                }
                else
                {
                    Debug.Write("'{0}'.\n", this.Operations[opIdx]);
                }
            }

            if (this.Configuration.DynamicEventQueuePrioritization)
            {
                var machineChoices = availableMachines.Where(mi => mi.Machine is Machine).
                                     Select(m => m.Machine as Machine);
                foreach (var choice in machineChoices)
                {
                    choice.SetQueueOperationPriority(nextOperation);
                }
            }

            next = this.GetNextMachineWithOperation(availableMachines, nextOperation);

            this.ExploredSteps++;

            return(true);
        }
Пример #21
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            if (this.HasCurrentOperationCompleted(choices, current))
            {
                this.Operations.Remove(current.Machine.OperationId);
                IO.Debug("<OperationDebug> Removes operation '{0}'.", current.Machine.OperationId);
            }

            var availableMachines = choices.Where(
                mi => mi.IsEnabled && !mi.IsBlocked && !mi.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            this.TryRegisterNewOperations(availableMachines, current);

            var nextOperation = this.GetNextOperation(availableMachines, current);

            IO.Debug("<OperationDebug> Chosen operation '{0}'.", nextOperation);
            if (IO.Debugging)
            {
                IO.Print("<OperationDebug> Operation list: ");
                for (int opIdx = 0; opIdx < this.Operations.Count; opIdx++)
                {
                    if (opIdx < this.Operations.Count - 1)
                    {
                        IO.Print("'{0}', ", this.Operations[opIdx]);
                    }
                    else
                    {
                        IO.Print("'{0}'.\n", this.Operations[opIdx]);
                    }
                }
            }

            if (this.Configuration.DynamicEventQueuePrioritization)
            {
                var machineChoices = availableMachines.Where(mi => mi.Machine is Machine).
                    Select(m => m.Machine as Machine);
                foreach (var choice in machineChoices)
                {
                    choice.SetQueueOperationPriority(nextOperation);
                }
            }

            next = this.GetNextMachineWithOperation(availableMachines, nextOperation);

            this.ExploredSteps++;

            return true;
        }
Пример #22
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public virtual bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            var machines = choices.OrderBy(mi => mi.Machine.Id.Value).ToList();

            var currentMachineIdx = machines.IndexOf(current);
            var orderedMachines = machines.GetRange(currentMachineIdx, machines.Count - currentMachineIdx);
            if (currentMachineIdx != 0)
            {
                orderedMachines.AddRange(machines.GetRange(0, currentMachineIdx));
            }

            var availableMachines = orderedMachines.Where(
                mi => mi.IsEnabled && !mi.IsBlocked && !mi.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            int idx = 0;
            while (this.RemainingDelays.Count > 0 && this.ExploredSteps == this.RemainingDelays[0])
            {
                idx = (idx + 1) % availableMachines.Count;
                this.RemainingDelays.RemoveAt(0);
                IO.PrintLine("<DelayLog> Inserted delay, '{0}' remaining.", this.RemainingDelays.Count);
            }

            next = availableMachines[idx];

            this.ExploredSteps++;

            return true;
        }
Пример #23
0
        /// <summary>
        /// Returns true if the current operation has completed.
        /// </summary>
        /// <param name="choices">List of machine infos</param>
        /// <param name="current">MachineInfo</param>
        /// <returns>Boolean</returns>
        private bool HasCurrentOperationCompleted(IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            foreach (var choice in choices.Where(mi => !mi.IsCompleted))
            {
                if (choice.Machine.OperationId == current.Machine.OperationId ||
                    choice.Machine.IsOperationPending(current.Machine.OperationId))
                {
                    return false;
                }
            }

            return true;
        }
Пример #24
0
 /// <summary>
 /// Returns the next operation to schedule.
 /// </summary>
 /// <param name="choices">Choices</param>
 /// <param name="current">Curent</param>
 /// <returns>OperationId</returns>
 protected abstract int GetNextOperation(List<MachineInfo> choices, MachineInfo current);
Пример #25
0
        /// <summary>
        /// Tries to register any new operations.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        private void TryRegisterNewOperations(IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            if (this.Operations.Count == 0)
            {
                this.Operations.Add(current.Machine.OperationId);
            }

            var operationIds = choices.Select(mi => mi.Machine.OperationId).Distinct();
            foreach (var id in operationIds.Where(id => !this.Operations.Contains(id)))
            {
                var opIndex = this.Random.Next(this.Operations.Count) + 1;
                this.Operations.Insert(opIndex, id);
                IO.Debug("<OperationDebug> Detected new operation '{0}' at index '{1}'.", id, opIndex);
            }
        }
        /// <summary>
        /// Returns the next operation to schedule.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>OperationId</returns>
        protected override int GetNextOperation(List<MachineInfo> choices, MachineInfo current)
        {
            var operationIds = choices.Select(val => val.Machine.OperationId).Distinct();
            if (this.PriorityChangePoints.Contains(this.ExploredSteps))
            {
                if (operationIds.Count() == 1)
                {
                    this.MovePriorityChangePointForward();
                }
                else
                {
                    var priority = this.GetHighestPriorityEnabledOperationId(choices);
                    base.Operations.Remove(priority);
                    base.Operations.Add(priority);
                    IO.PrintLine("<OperationLog> Operation '{0}' changes to lowest priority.",
                        priority);
                }
            }

            return this.GetHighestPriorityEnabledOperationId(choices);
        }
Пример #27
0
        /// <summary>
        /// Returns the prioritized machine.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>MachineInfo</returns>
        private MachineInfo GetPrioritizedMachine(List<MachineInfo> choices, MachineInfo current)
        {
            if (this.PrioritizedMachines.Count == 0)
            {
                this.PrioritizedMachines.Add(current.Machine.Id);
            }

            foreach (var mi in choices.Where(mi => !this.PrioritizedMachines.Contains(mi.Machine.Id)))
            {
                var mIndex = this.Random.Next(this.PrioritizedMachines.Count) + 1;
                this.PrioritizedMachines.Insert(mIndex, mi.Machine.Id);
                IO.Debug($"<PCTDebug> Detected new machine '{mi.Machine.Id}' at index '{mIndex}'.");
            }

            if (this.PriorityChangePoints.Contains(this.ExploredSteps))
            {
                if (choices.Count == 1)
                {
                    this.MovePriorityChangePointForward();
                }
                else
                {
                    var priority = this.GetHighestPriorityEnabledMachine(choices);
                    this.PrioritizedMachines.Remove(priority);
                    this.PrioritizedMachines.Add(priority);
                    IO.PrintLine($"<PCTLog> Machine '{priority}' changes to lowest priority.");
                }
            }

            var prioritizedMachine = this.GetHighestPriorityEnabledMachine(choices);
            IO.Debug($"<PCTDebug> Prioritized machine '{prioritizedMachine}'.");
            if (IO.Debugging)
            {
                IO.Print("<PCTDebug> Priority list: ");
                for (int idx = 0; idx < this.PrioritizedMachines.Count; idx++)
                {
                    if (idx < this.PrioritizedMachines.Count - 1)
                    {
                        IO.Print($"'{this.PrioritizedMachines[idx]}', ");
                    }
                    else
                    {
                        IO.Print($"'{this.PrioritizedMachines[idx]}({1})'.\n");
                    }
                }
            }

            var prioritizedMachineInfo = choices.First(mi => mi.Machine.Id.Equals(prioritizedMachine));
            return prioritizedMachineInfo;
        }
Пример #28
0
        /// <summary>
        /// Notify that a new task has been created for the given machine.
        /// </summary>
        /// <param name="id">TaskId</param>
        /// <param name="machine">Machine</param>
        internal virtual void NotifyNewTaskCreated(int id, AbstractMachine machine)
        {
            var machineInfo = new MachineInfo(id, machine);

            IO.Debug($"<ScheduleDebug> Created task '{machineInfo.Id}' for machine " +
                $"'{machineInfo.Machine.Id}'.");

            if (this.MachineInfos.Count == 0)
            {
                machineInfo.IsActive = true;
            }

            this.MachineInfos.Add(machineInfo);
            this.TaskMap.TryAdd(id, machineInfo);
        }
Пример #29
0
 /// <summary>
 /// Returns the next machine to schedule.
 /// </summary>
 /// <param name="next">Next</param>
 /// <param name="choices">Choices</param>
 /// <param name="current">Curent</param>
 /// <returns>Boolean</returns>
 public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
 {
     if (this.BoundedDFS.HasReachedMaxSchedulingSteps())
     {
         return this.Random.TryGetNext(out next, choices, current);
     }
     {
         return this.BoundedDFS.TryGetNext(out next, choices, current);
     }
 }
Пример #30
0
 /// <summary>
 /// Returns the next machine to schedule.
 /// </summary>
 /// <param name="next">Next</param>
 /// <param name="choices">Choices</param>
 /// <param name="current">Curent</param>
 /// <returns>Boolean</returns>
 public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
 {
     if (this.BoundedDFS.HasReachedMaxSchedulingSteps())
     {
         return(this.Random.TryGetNext(out next, choices, current));
     }
     {
         return(this.BoundedDFS.TryGetNext(out next, choices, current));
     }
 }
Пример #31
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            if (this.ExploredSteps >= this.ScheduleTrace.Count)
            {
                IO.Error.ReportAndExit("Trace is not reproducible: execution is longer than trace.");
            }

            ScheduleStep nextStep = this.ScheduleTrace[this.ExploredSteps];
            if (nextStep.Type != ScheduleStepType.SchedulingChoice)
            {
                IO.Error.ReportAndExit("Trace is not reproducible: next step is not a scheduling choice.");
            }

            next = availableMachines.FirstOrDefault(m => m.Machine.Id.Type.Equals(
                nextStep.ScheduledMachineType) &&
                m.Machine.Id.Value == nextStep.ScheduledMachineId);
            if (next == null)
            {
                IO.Error.ReportAndExit("Trace is not reproducible: cannot detect machine with type " +
                    $"'{nextStep.ScheduledMachineType}' and id '{nextStep.ScheduledMachineId}'.");
            }

            this.ExploredSteps++;

            return true;
        }
Пример #32
0
        /// <summary>
        /// Returns the prioritized machines.
        /// </summary>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        private List<MachineInfo> GetPrioritizedMachines(List<MachineInfo> choices, MachineInfo current)
        {
            choices = choices.OrderBy(mi => mi.Machine.Id.Value).ToList();
            choices = choices.OrderBy(mi => mi.Machine.OperationId).ToList();

            MachineInfo priorityMachine = current;
            var prioritizedMachines = new List<MachineInfo>();
            if (current.Machine.OperationId == this.PrioritizedOperationId)
            {
                var currentMachineIdx = choices.IndexOf(current);
                prioritizedMachines = choices.GetRange(currentMachineIdx, choices.Count - currentMachineIdx);
                if (currentMachineIdx != 0)
                {
                    prioritizedMachines.AddRange(choices.GetRange(0, currentMachineIdx));
                }
            }
            else
            {
                priorityMachine = choices.First(mi => mi.Machine.OperationId == this.PrioritizedOperationId);
                var priorityMachineIdx = choices.IndexOf(priorityMachine);
                prioritizedMachines = choices.GetRange(priorityMachineIdx, choices.Count - priorityMachineIdx);
                if (priorityMachineIdx != 0)
                {
                    prioritizedMachines.AddRange(choices.GetRange(0, priorityMachineIdx));
                }
            }

            prioritizedMachines = prioritizedMachines.Where(
                mi => mi.IsEnabled && !mi.IsBlocked && !mi.IsWaitingToReceive).ToList();
            if (prioritizedMachines.Count == 0)
            {
                return prioritizedMachines;
            }

            return prioritizedMachines;
        }
Пример #33
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            SChoice nextChoice = null;
            List<SChoice> scs = null;

            if (this.SchIndex < this.ScheduleStack.Count)
            {
                scs = this.ScheduleStack[this.SchIndex];
            }
            else
            {
                scs = new List<SChoice>();
                foreach (var task in availableMachines)
                {
                    scs.Add(new SChoice(task.Machine.Id.Value));
                }

                this.ScheduleStack.Add(scs);
            }

            nextChoice = scs.FirstOrDefault(val => !val.IsDone);
            if (nextChoice == null)
            {
                next = null;
                return false;
            }

            if (this.SchIndex > 0)
            {
                var previousChoice = this.ScheduleStack[this.SchIndex - 1].Last(val => val.IsDone);
                previousChoice.IsDone = false;
            }

            next = availableMachines.Find(task => task.Machine.Id.Value == nextChoice.Id);
            nextChoice.IsDone = true;
            this.SchIndex++;

            if (next == null)
            {
                return false;
            }

            this.ExploredSteps++;

            return true;
        }
Пример #34
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            next = null;

            List<MachineInfo> availableMachines;
            if (this.Configuration.BoundOperations)
            {
                availableMachines = this.GetPrioritizedMachines(choices.ToList(), current);
            }
            else
            {
                choices = choices.OrderBy(machine => machine.Machine.Id.Value).ToList();
                availableMachines = choices.Where(
                    m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();
            }

            if (availableMachines.Count == 0)
            {
                IO.PrintLine(">> No available machines to schedule ...");
                return false;
            }

            this.ExploredSteps++;

            var parsed = false;
            while (!parsed)
            {
                if (this.InputCache.Count >= this.ExploredSteps)
                {
                    var step = this.InputCache[this.ExploredSteps - 1];
                    int idx = 0;
                    if (step.Length > 0)
                    {
                        idx = Convert.ToInt32(step);
                    }
                    else
                    {
                        this.InputCache[this.ExploredSteps - 1] = "0";
                    }

                    next = availableMachines[idx];
                    parsed = true;
                    break;
                }

                IO.PrintLine(">> Available machines to schedule ...");
                for (int idx = 0; idx < availableMachines.Count; idx++)
                {
                    var m = availableMachines[idx];
                    if (this.Configuration.BoundOperations)
                    {
                        IO.PrintLine($">> [{idx}] '{m.Machine.Id}' with " +
                            $"operation id '{m.Machine.OperationId}'");
                    }
                    else
                    {
                        IO.PrintLine($">> [{idx}] '{m.Machine.Id}'");
                    }
                }

                IO.PrintLine($">> Choose machine to schedule [step '{this.ExploredSteps}']");

                var input = IO.GetLine();
                if (input.Equals("replay"))
                {
                    if (!this.Replay())
                    {
                        continue;
                    }

                    this.Configuration.SchedulingIterations++;
                    this.ConfigureNextIteration();
                    return false;
                }
                else if (input.Equals("jump"))
                {
                    this.Jump();
                    continue;
                }
                else if (input.Equals("reset"))
                {
                    this.Configuration.SchedulingIterations++;
                    this.Reset();
                    return false;
                }
                else if (input.Length > 0)
                {
                    try
                    {
                        var idx = Convert.ToInt32(input);
                        if (idx < 0)
                        {
                            IO.PrintLine(">> Expected positive integer, please retry ...");
                            continue;
                        }

                        next = availableMachines[idx];
                        if (next == null)
                        {
                            IO.PrintLine(">> Unexpected id, please retry ...");
                            continue;
                        }

                        if (this.Configuration.BoundOperations)
                        {
                            this.PrioritizedOperationId = next.Machine.OperationId;
                        }
                    }
                    catch (FormatException)
                    {
                        IO.PrintLine(">> Wrong format, please retry ...");
                        continue;
                    }
                }
                else
                {
                    next = availableMachines[0];
                }

                this.InputCache.Add(input);
                parsed = true;
            }

            return true;
        }
Пример #35
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        bool ISchedulingStrategy.TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices,
            MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            if (this.Runtime.Configuration.EnableCycleReplayingStrategy)
            {
                ScheduleStep nextStep = this.PotentialCycle[this.CurrentCycleIndex].Item1;
                if (nextStep.Type != ScheduleStepType.SchedulingChoice)
                {
                    IO.Debug("<LivenessDebug> Trace is not reproducible: next step is not a scheduling choice.");
                    this.EscapeCycle();
                    return this.BugFindingSchedulingStrategy.TryGetNext(out next, choices, current);
                }

                IO.Debug($"<LivenessDebug> Replaying '{nextStep.Index}' '{nextStep.ScheduledMachine.Id}'.");

                next = availableMachines.FirstOrDefault(m => m.Machine.Id.Type.Equals(
                    nextStep.ScheduledMachineType) &&
                    m.Machine.Id.Value == nextStep.ScheduledMachineId);
                if (next == null)
                {
                    IO.Debug("<LivenessDebug> Trace is not reproducible: cannot detect machine with type " +
                        $"'{nextStep.ScheduledMachineType}' and id '{nextStep.ScheduledMachineId}'.");
                    this.EscapeCycle();
                    return this.BugFindingSchedulingStrategy.TryGetNext(out next, choices, current);
                }

                this.CurrentCycleIndex++;
                if (this.CurrentCycleIndex == this.PotentialCycle.Count)
                {
                    this.CurrentCycleIndex = 0;
                }
            }
            else
            {
                int idx = this.Random.Next(availableMachines.Count);
                next = availableMachines[idx];
            }

            return true;
        }
Пример #36
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable<MachineInfo> choices, MachineInfo current)
        {
            var availableMachines = choices.Where(
                m => m.IsEnabled && !m.IsBlocked && !m.IsWaitingToReceive).ToList();
            if (availableMachines.Count == 0)
            {
                availableMachines = choices.Where(m => m.IsWaitingToReceive).ToList();
                if (availableMachines.Count == 0)
                {
                    next = null;
                    return false;
                }
            }

            int idx = this.Random.Next(availableMachines.Count);
            next = availableMachines[idx];

            this.ExploredSteps++;

            return true;
        }
Пример #37
0
 /// <summary>
 /// Returns the next machine to schedule.
 /// </summary>
 /// <param name="next">Next</param>
 /// <param name="choices">Choices</param>
 /// <param name="current">Curent</param>
 /// <returns>Boolean</returns>
 public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
 {
     if (this.PrefixStrategy.GetExploredSteps() > this.SafetyPrefixDepth)
     {
         return(this.SuffixStrategy.TryGetNext(out next, choices, current));
     }
     else
     {
         return(this.PrefixStrategy.TryGetNext(out next, choices, current));
     }
 }
Пример #38
0
        /// <summary>
        /// Returns the next machine to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        /// <returns>Boolean</returns>
        public bool TryGetNext(out MachineInfo next, IEnumerable <MachineInfo> choices, MachineInfo current)
        {
            next = null;

            List <MachineInfo> availableMachines;

            if (this.Configuration.BoundOperations)
            {
                availableMachines = this.GetPrioritizedMachines(choices.ToList(), current);
            }
            else
            {
                choices           = choices.OrderBy(machine => machine.Machine.Id.Value).ToList();
                availableMachines = choices.Where(
                    m => m.IsEnabled && !m.IsWaitingToReceive).ToList();
            }

            if (availableMachines.Count == 0)
            {
                this.Logger.WriteLine(">> No available machines to schedule ...");
                return(false);
            }

            this.ExploredSteps++;

            var parsed = false;

            while (!parsed)
            {
                if (this.InputCache.Count >= this.ExploredSteps)
                {
                    var step = this.InputCache[this.ExploredSteps - 1];
                    int idx  = 0;
                    if (step.Length > 0)
                    {
                        idx = Convert.ToInt32(step);
                    }
                    else
                    {
                        this.InputCache[this.ExploredSteps - 1] = "0";
                    }

                    next   = availableMachines[idx];
                    parsed = true;
                    break;
                }

                this.Logger.WriteLine(">> Available machines to schedule ...");
                for (int idx = 0; idx < availableMachines.Count; idx++)
                {
                    var m = availableMachines[idx];
                    if (this.Configuration.BoundOperations)
                    {
                        this.Logger.WriteLine($">> [{idx}] '{m.Machine.Id}' with " +
                                              $"operation id '{m.Machine.OperationId}'");
                    }
                    else
                    {
                        this.Logger.WriteLine($">> [{idx}] '{m.Machine.Id}'");
                    }
                }

                this.Logger.WriteLine($">> Choose machine to schedule [step '{this.ExploredSteps}']");

                var input = Console.ReadLine();
                if (input.Equals("replay"))
                {
                    if (!this.Replay())
                    {
                        continue;
                    }

                    this.Configuration.SchedulingIterations++;
                    this.ConfigureNextIteration();
                    return(false);
                }
                else if (input.Equals("jump"))
                {
                    this.Jump();
                    continue;
                }
                else if (input.Equals("reset"))
                {
                    this.Configuration.SchedulingIterations++;
                    this.Reset();
                    return(false);
                }
                else if (input.Length > 0)
                {
                    try
                    {
                        var idx = Convert.ToInt32(input);
                        if (idx < 0)
                        {
                            this.Logger.WriteLine(">> Expected positive integer, please retry ...");
                            continue;
                        }

                        next = availableMachines[idx];
                        if (next == null)
                        {
                            this.Logger.WriteLine(">> Unexpected id, please retry ...");
                            continue;
                        }

                        if (this.Configuration.BoundOperations)
                        {
                            this.PrioritizedOperationId = next.Machine.OperationId;
                        }
                    }
                    catch (FormatException)
                    {
                        this.Logger.WriteLine(">> Wrong format, please retry ...");
                        continue;
                    }
                }
                else
                {
                    next = availableMachines[0];
                }

                this.InputCache.Add(input);
                parsed = true;
            }

            return(true);
        }
Пример #39
0
        /// <summary>
        /// Schedules the next machine to execute.
        /// </summary>
        internal virtual void Schedule()
        {
            int?id = Task.CurrentId;

            if (id == null || id == this.Runtime.RootTaskId)
            {
                return;
            }

            if (this.BugFound || !this.IsSchedulerRunning)
            {
                this.Stop();
            }

            // Checks if the scheduling steps bound has been reached.
            this.CheckIfSchedulingStepsBoundIsReached(false);

            MachineInfo machineInfo = null;

            if (!this.TaskMap.TryGetValue((int)id, out machineInfo))
            {
                IO.Debug($"<ScheduleDebug> Unable to schedule task '{id}'.");
                this.Stop();
            }

            MachineInfo next = null;

            if (!this.Strategy.TryGetNext(out next, this.TaskMap.Values, machineInfo))
            {
                IO.Debug("<ScheduleDebug> Schedule explored.");
                this.HasFullyExploredSchedule = true;
                this.Stop();
            }

            this.Runtime.ScheduleTrace.AddSchedulingChoice(next.Machine.Id);

            if (this.Runtime.Configuration.CacheProgramState &&
                this.Runtime.Configuration.SafetyPrefixBound <= this.ExploredSteps)
            {
                this.Runtime.StateCache.CaptureState(this.Runtime.ScheduleTrace.Peek());
            }

            // Checks the liveness monitors for potential liveness bugs.
            this.Runtime.LivenessChecker.CheckLivenessAtShedulingStep();

            IO.Debug($"<ScheduleDebug> Schedule task '{next.Id}' of machine " +
                     $"'{next.Machine.Id}'.");

            if (next.IsWaitingToReceive)
            {
                string message = IO.Format("Livelock detected. Machine " +
                                           $"'{next.Machine.Id}' is waiting for an event, " +
                                           "but no other machine is enabled.");
                this.Runtime.BugFinder.NotifyAssertionFailure(message, true);
            }

            if (machineInfo != next)
            {
                machineInfo.IsActive = false;
                lock (next)
                {
                    next.IsActive = true;
                    System.Threading.Monitor.PulseAll(next);
                }

                lock (machineInfo)
                {
                    if (machineInfo.IsCompleted)
                    {
                        return;
                    }

                    while (!machineInfo.IsActive)
                    {
                        IO.Debug($"<ScheduleDebug> Sleep task '{machineInfo.Id}' of machine " +
                                 $"'{machineInfo.Machine.Id}'.");
                        System.Threading.Monitor.Wait(machineInfo);
                        IO.Debug($"<ScheduleDebug> Wake up task '{machineInfo.Id}' of machine " +
                                 $"'{machineInfo.Machine.Id}'.");
                    }

                    if (!machineInfo.IsEnabled)
                    {
                        throw new OperationCanceledException();
                    }
                }
            }
        }