Пример #1
0
        /// <summary>
        /// Notify that the event handler has completed.
        /// </summary>
        /// <param name="info">SchedulableInfo</param>
        internal void NotifyEventHandlerCompleted(SchedulableInfo info)
        {
            Debug.WriteLine($"<ScheduleDebug> Completed event handler of '{info.Name}' with task id '{info.TaskId}'.");

            info.IsEnabled   = false;
            info.IsCompleted = true;

            this.Schedule();

            Debug.WriteLine($"<ScheduleDebug> Exit event handler of '{info.Name}' with task id '{info.TaskId}'.");
        }
Пример #2
0
        /// <summary>
        /// Notify that an event handler has been created.
        /// </summary>
        /// <param name="info">SchedulableInfo</param>
        internal void NotifyEventHandlerCreated(SchedulableInfo info)
        {
            if (!this.SchedulableInfoMap.ContainsKey(info.Id))
            {
                if (this.SchedulableInfoMap.Count == 0)
                {
                    this.ScheduledMachine = info;
                }

                this.SchedulableInfoMap.Add(info.Id, info);
            }

            Debug.WriteLine($"<ScheduleDebug> Created event handler of '{info.Name}' with task id '{info.TaskId}'.");
        }
Пример #3
0
 /// <summary>
 /// Waits for the event handler to start.
 /// </summary>
 /// <param name="info">SchedulableInfo</param>
 internal void WaitForEventHandlerToStart(SchedulableInfo info)
 {
     lock (info)
     {
         if (this.SchedulableInfoMap.Count == 1)
         {
             info.IsActive = true;
             System.Threading.Monitor.PulseAll(info);
         }
         else
         {
             while (!info.IsEventHandlerRunning)
             {
                 System.Threading.Monitor.Wait(info);
             }
         }
     }
 }
Пример #4
0
        /// <summary>
        /// Notify that the event handler has started.
        /// </summary>
        /// <param name="info">SchedulableInfo</param>
        internal void NotifyEventHandlerStarted(SchedulableInfo info)
        {
            Debug.WriteLine($"<ScheduleDebug> Started event handler of '{info.Name}' with task id '{info.TaskId}'.");

            lock (info)
            {
                info.IsEventHandlerRunning = true;
                System.Threading.Monitor.PulseAll(info);
                while (!info.IsActive)
                {
                    Debug.WriteLine($"<ScheduleDebug> Sleep '{info.Name}' with task id '{info.TaskId}'.");
                    System.Threading.Monitor.Wait(info);
                    Debug.WriteLine($"<ScheduleDebug> Wake up '{info.Name}' with task id '{info.TaskId}'.");
                }

                if (!info.IsEnabled)
                {
                    throw new ExecutionCanceledException();
                }
            }
        }
Пример #5
0
 /// <summary>
 /// Notify that a monitor was registered.
 /// </summary>
 /// <param name="info">SchedulableInfo</param>
 internal void NotifyMonitorRegistered(SchedulableInfo info)
 {
     SchedulableInfoMap.Add(info.Id, info);
     Debug.WriteLine($"<ScheduleDebug> Created monitor of '{info.Name}'.");
 }
Пример #6
0
        /// <summary>
        /// Schedules the next <see cref="ISchedulable"/> operation to execute.
        /// </summary>
        /// <param name="operationType">Type of the operation.</param>
        /// <param name="targetType">Type of the target of the operation.</param>
        /// <param name="targetId">Id of the target.</param>
        internal void Schedule(OperationType operationType, OperationTargetType targetType, ulong targetId)
        {
            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();

            SchedulableInfo current = this.ScheduledMachine;

            current.SetNextOperation(operationType, targetType, targetId);

            // Get and order the schedulable choices by their id.
            var choices = this.SchedulableInfoMap.Values.OrderBy(choice => choice.Id).Select(choice => choice as ISchedulable).ToList();

            ISchedulable next = null;

            if (!this.Strategy.GetNext(out next, choices, current))
            {
                // Checks if the program has livelocked.
                this.CheckIfProgramHasLivelocked(choices.Select(choice => choice as SchedulableInfo));

                Debug.WriteLine("<ScheduleDebug> Schedule explored.");
                this.HasFullyExploredSchedule = true;
                this.Stop();
            }

            this.ScheduledMachine = next as SchedulableInfo;

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

            Debug.WriteLine($"<ScheduleDebug> Schedule '{next.Name}' with task id '{this.ScheduledMachine.TaskId}'.");

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

                lock (current)
                {
                    if (!current.IsEventHandlerRunning)
                    {
                        return;
                    }

                    while (!current.IsActive)
                    {
                        Debug.WriteLine($"<ScheduleDebug> Sleep '{current.Name}' with task id '{current.TaskId}'.");
                        System.Threading.Monitor.Wait(current);
                        Debug.WriteLine($"<ScheduleDebug> Wake up '{current.Name}' with task id '{current.TaskId}'.");
                    }

                    if (!current.IsEnabled)
                    {
                        throw new ExecutionCanceledException();
                    }
                }
            }
        }
Пример #7
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();

            SchedulableInfo current = this.ScheduledMachine;
            ISchedulable    next    = null;

            var choices = this.Infos.Values.OrderBy(choice => choice.Id).Select(choice => choice as ISchedulable).ToList();

            if (!this.Strategy.TryGetNext(out next, choices, current))
            {
                // Checks if the program has livelocked.
                this.CheckIfProgramHasLivelocked(choices.Select(choice => choice as SchedulableInfo));

                Debug.WriteLine("<ScheduleDebug> Schedule explored.");
                this.HasFullyExploredSchedule = true;
                this.Stop();
            }

            this.ScheduledMachine = next as SchedulableInfo;

            this.Runtime.ScheduleTrace.AddSchedulingChoice(next.Id);
            this.ScheduledMachine.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 '{next.Name}' with task id '{this.ScheduledMachine.TaskId}'.");

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

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

                    while (!current.IsActive)
                    {
                        Debug.WriteLine($"<ScheduleDebug> Sleep '{current.Name}' with task id '{current.TaskId}'.");
                        System.Threading.Monitor.Wait(current);
                        Debug.WriteLine($"<ScheduleDebug> Wake up '{current.Name}' with task id '{current.TaskId}'.");
                    }

                    if (!current.IsEnabled)
                    {
                        throw new ExecutionCanceledException();
                    }
                }
            }
        }