示例#1
0
        /// <summary>
        /// Update the sleep sets for the top operation on the stack.
        /// This will look at the second from top element in the stack
        /// and copy forward the sleep set, excluding threads that are dependent
        /// with the executed operation.
        /// </summary>
        /// <param name="stack">Stack</param>
        /// <param name="contract">IContract</param>
        public static void UpdateSleepSets(Stack stack, IContract contract)
        {
            if (stack.GetNumSteps() <= 1)
            {
                return;
            }

            TidEntryList prevTop      = stack.GetSecondFromTop();
            TidEntry     prevSelected = prevTop.List[prevTop.GetSelected(contract)];

            TidEntryList currTop = stack.GetTop();

            // For each thread on the top of stack (except previously selected thread and new threads):
            //   if thread was slept previously
            //   and thread's op was independent with selected op then:
            //     the thread is still slept.
            //   else: not slept.

            for (int i = 0; i < prevTop.List.Count; i++)
            {
                if (i == prevSelected.Id)
                {
                    continue;
                }
                if (prevTop.List[i].Sleep && !IsDependent(prevTop.List[i], prevSelected))
                {
                    currTop.List[i].Sleep = true;
                }
            }
        }
示例#2
0
        /// <summary>
        /// Returns or forces the next choice to schedule.
        /// </summary>
        /// <param name="next">Next</param>
        /// <param name="choices">Choices</param>
        /// <param name="current">Curent</param>
        private bool GetNextHelper(
            ref ISchedulable next,
            List <ISchedulable> choices,
            ISchedulable current)
        {
            int currentSchedulableId = (int)current.Id;

            // "Yield" and "Waiting for quiescence" hack.
            if (choices.TrueForAll(info => !info.IsEnabled))
            {
                if (choices.Exists(info => info.NextOperationType == OperationType.Yield))
                {
                    foreach (var actorInfo in choices)
                    {
                        if (actorInfo.NextOperationType == OperationType.Yield)
                        {
                            actorInfo.IsEnabled = true;
                        }
                    }
                }
                else if (choices.Exists(
                             info => info.NextOperationType == OperationType.WaitForQuiescence))
                {
                    foreach (var actorInfo in choices)
                    {
                        if (actorInfo.NextOperationType == OperationType.WaitForQuiescence)
                        {
                            actorInfo.IsEnabled = true;
                        }
                    }
                }
            }

            // Forced choice.
            if (next != null)
            {
                AbdandonReplay(false);
            }

            bool         added = Stack.Push(choices, currentSchedulableId);
            TidEntryList top   = Stack.GetTop();

            Contract.Assert(next == null || added, "DPOR: Forced choice implies we should have added to stack.");

            if (added)
            {
                if (UseSleepSets)
                {
                    SleepSets.UpdateSleepSets(Stack, Contract);
                }

                if (Dpor == null)
                {
                    top.SetAllEnabledToBeBacktracked(Contract);
                }
                else if (Dpor.RaceReplaySuffix.Count > 0 && Dpor.ReplayRaceIndex < Dpor.RaceReplaySuffix.Count)
                {
                    // Replaying a race:
                    var tidReplay = Dpor.RaceReplaySuffix[Dpor.ReplayRaceIndex];
                    // Restore the nondet choices on the top of stack.
                    top.NondetChoices = tidReplay.NondetChoices;
                    // Add the replay tid to the backtrack set.
                    top.List[tidReplay.Id].Backtrack = true;
                    Contract.Assert(
                        top.List[tidReplay.Id].Enabled ||
                        top.List[tidReplay.Id].OpType == OperationType.Yield);
                    ++Dpor.ReplayRaceIndex;
                }
                else
                {
                    // TODO: Here is where we can combine with another scheduler:
                    // For now, we just do round-robin when doing DPOR and random when doing random DPOR.

                    // If our choice is forced by parent scheduler:
                    if (next != null)
                    {
                        top.AddToBacktrack((int)next.Id, Contract);
                    }
                    else if (Rand == null)
                    {
                        top.AddFirstEnabledNotSleptToBacktrack(currentSchedulableId, Contract);
                    }
                    else
                    {
                        top.AddRandomEnabledNotSleptToBacktrack(Rand);
                    }
                }
            }
            else if (Rand != null)
            {
                // When doing random DPOR: we are replaying a schedule prefix so rewind the nondet choices now.
                top.RewindNondetChoicesForReplay();
            }

            int nextTid = Stack.GetSelectedOrFirstBacktrackNotSlept(currentSchedulableId);

            if (nextTid < 0)
            {
                next = null;
                // TODO: if nextTidIndex == DPORAlgorithm.SLEEP_SET_BLOCKED then let caller know that this is the case.
                // I.e. this is not deadlock.
                return(false);
            }

            if (top.TryGetSelected(Contract) != nextTid)
            {
                top.SetSelected(nextTid, Contract);
            }

            Contract.Assert(nextTid < choices.Count);
            next = choices[nextTid];

            // TODO: Part of yield hack.
            if (!next.IsEnabled &&
                next.NextOperationType == OperationType.Yield)
            {
                //                // Uncomment to avoid waking a yielding thread.
                //                next = null;
                //                // TODO: let caller know that this is not deadlock.
                //                return false;
                next.IsEnabled = true;
            }

            Contract.Assert(next.IsEnabled);
            return(true);
        }