예제 #1
0
        /// <summary>
        /// This method is used in a DFS exploration of nondet choice.
        /// It will pop off bool choices that are 1 until
        /// it reaches a 0 that will then be changed to a 1.
        /// The NextNondetChoiceIndex will be reset ready for replay.
        /// </summary>
        /// <param name="contract">IContract</param>
        /// <returns>false if there are no more nondet choices to explore</returns>
        public bool BacktrackNondetChoices(IContract contract)
        {
            if (NondetChoices == null)
            {
                return(false);
            }

            contract.Assert(NextNondetChoiceIndex == NondetChoices.Count);

            NextNondetChoiceIndex = 0;

            while (NondetChoices.Count > 0)
            {
                NonDetChoice choice = NondetChoices[NondetChoices.Count - 1];
                contract.Assert(choice.IsBoolChoice, "DFS DPOR only supports bool choices.");
                if (choice.Choice == 0)
                {
                    choice.Choice = 1;
                    NondetChoices[NondetChoices.Count - 1] = choice;
                    return(true);
                }
                contract.Assert(choice.Choice == 1, "Unexpected choice value.");
                NondetChoices.RemoveAt(NondetChoices.Count - 1);
            }

            return(false);
        }
예제 #2
0
        /// <summary>
        /// Get a nondet choice.
        /// This may replay a nondet choice or make (and record) a new nondet choice.
        /// </summary>
        /// <param name="isBoolChoice">If true, a boolean choice; otherwise, an int choice.</param>
        /// <param name="rand">Random</param>
        /// <param name="contract">IContract</param>
        public int MakeOrReplayNondetChoice(bool isBoolChoice, IRandomNumberGenerator rand, IContract contract)
        {
            contract.Assert(
                rand != null || isBoolChoice,
                "A DFS DPOR exploration of int nondeterminstic choices " +
                "is not currently supported because this won't scale.");

            if (NondetChoices == null)
            {
                NondetChoices = new List <NonDetChoice>();
            }


            if (NextNondetChoiceIndex < NondetChoices.Count)
            {
                // Replay:
                NonDetChoice choice = NondetChoices[NextNondetChoiceIndex];
                ++NextNondetChoiceIndex;
                contract.Assert(choice.IsBoolChoice == isBoolChoice);
                return(choice.Choice);
            }

            // Adding a choice.
            contract.Assert(NextNondetChoiceIndex == NondetChoices.Count);
            NonDetChoice ndc = new NonDetChoice
            {
                IsBoolChoice = isBoolChoice,
                Choice       = rand == null ? 0 : (isBoolChoice ? rand.Next(2) : rand.Next())
            };

            NondetChoices.Add(ndc);
            ++NextNondetChoiceIndex;
            return(ndc.Choice);
        }
예제 #3
0
        /// <summary>
        /// Push a list of tid entries onto the stack.
        /// If we are replaying, this will verify that
        /// the list is what we expected.
        /// </summary>
        /// <param name="machines"></param>
        /// <param name="prevThreadIndex"></param>
        /// <returns>true if a new element was added to the stack, otherwise the existing entry was verified</returns>
        public bool Push(List <ISchedulable> machines, int prevThreadIndex)
        {
            List <TidEntry> list = new List <TidEntry>();

            foreach (var machineInfo in machines)
            {
                list.Add(
                    new TidEntry(
                        (int)machineInfo.Id,
                        machineInfo.IsEnabled,
                        machineInfo.NextOperationType,
                        machineInfo.NextTargetType,
                        (int)machineInfo.NextTargetId,
                        (int)machineInfo.NextOperationMatchingSendIndex));
            }

            Contract.Assert(NextStackPos <= StackInternal.Count, "DFS strategy unexpected stack state.");

            bool added = NextStackPos == StackInternal.Count;

            if (added)
            {
                StackInternal.Add(new TidEntryList(list));
            }
            else
            {
                CheckMatches(list);
            }

            ++NextStackPos;

            return(added);
        }
예제 #4
0
        /// <summary>
        /// Gets the selected thread.
        /// Asserts that there is a selected thread.
        /// </summary>
        /// <param name="contract">IContract</param>
        public int GetSelected(IContract contract)
        {
            int res = TryGetSelected(contract);

            contract.Assert(res != -1, "DFS Strategy: No selected tid entry!");
            return(res);
        }
예제 #5
0
 /// <summary>
 /// Add all enabled threads to the backtrack set.
 /// </summary>
 /// <param name="contract">IContract</param>
 public void SetAllEnabledToBeBacktracked(IContract contract)
 {
     foreach (var tidEntry in List)
     {
         if (tidEntry.Enabled)
         {
             tidEntry.Backtrack = true;
             // TODO: Remove?
             contract.Assert(tidEntry.Enabled);
         }
     }
 }
예제 #6
0
        /// <summary>
        /// Gets all threads in backtrack that are not slept and not selected.
        /// </summary>
        /// <param name="contract">IContract</param>
        public List <int> GetAllBacktrackNotSleptNotSelected(IContract contract)
        {
            List <int> res = new List <int>();

            for (int i = 0; i < List.Count; ++i)
            {
                if (List[i].Backtrack &&
                    !List[i].Sleep &&
                    List[i].Id != SelectedEntry)
                {
                    contract.Assert(List[i].Enabled);
                    res.Add(i);
                }
            }

            return(res);
        }
예제 #7
0
        private void DoRandomRaceReverse(Stack stack, IRandomNumberGenerator rand)
        {
            int raceIndex = rand.Next(Races.Count);

            if (raceIndex == 0)
            {
                return;
            }
            Race race = Races[raceIndex];

            Contract.Assert(RaceReplaySuffix.Count == 0, "Tried to reverse race but replay suffix was not empty!");

            int threadIdOfA = GetSelectedTidEntry(stack, race.A).Id;

            // Add to RaceReplaySuffix: all steps between a and b that do not h.a. a.
            for (int i = race.A; i < race.B; ++i)
            {
                if (HB(threadIdOfA, race.A, i))
                {
                    // Skip it.
                    // But track the missing thread id if this is a create operation.
                    if (GetSelectedTidEntry(stack, i).OpType == OperationType.Create)
                    {
                        var missingThreadId = GetThreadsAt(stack, i).List.Count;
                        var index           = MissingThreadIds.BinarySearch(missingThreadId);
                        // We should not find it.
                        Contract.Assert(index < 0);
                        // Get the next largest index (see BinarySearch).
                        index = ~index;
                        // Insert before the next largest item.
                        MissingThreadIds.Insert(index, missingThreadId);
                    }
                }
                else
                {
                    // Add thread id to the RaceReplaySuffix, but adjust
                    // it for missing thread ids.
                    AddThreadIdToRaceReplaySuffix(GetThreadsAt(stack, i));
                }
            }

            AddThreadIdToRaceReplaySuffix(GetThreadsAt(stack, race.B));
            AddThreadIdToRaceReplaySuffix(GetThreadsAt(stack, race.A));

            // Remove steps from a onwards. Indexes start at one so we must subtract 1.
            stack.StackInternal.RemoveRange(race.A - 1, stack.StackInternal.Count - (race.A - 1));
        }
예제 #8
0
        /// <summary>
        /// Add the first enabled and not slept thread to the backtrack set.
        /// </summary>
        /// <param name="startingFrom">a thread id to start from</param>
        /// <param name="contract">IContract</param>
        public void AddFirstEnabledNotSleptToBacktrack(int startingFrom, IContract contract)
        {
            int size = List.Count;
            int i    = startingFrom;

            for (int count = 0; count < size; ++count)
            {
                if (List[i].Enabled &&
                    !List[i].Sleep)
                {
                    List[i].Backtrack = true;
                    // TODO: Remove?
                    contract.Assert(List[i].Enabled);
                    return;
                }
                ++i;
                if (i >= size)
                {
                    i = 0;
                }
            }
        }
예제 #9
0
 /// <summary>
 /// Sets the selected thread id.
 /// There must not already be a selected thread id.
 /// </summary>
 /// <param name="tid">thread id to be set to selected</param>
 /// <param name="contract">IContract</param>
 public void SetSelected(int tid, IContract contract)
 {
     contract.Assert(SelectedEntry < 0);
     contract.Assert(tid >= 0 && tid < List.Count);
     SelectedEntry = tid;
 }
예제 #10
0
 /// <summary>
 /// Add a thread to the backtrack set.
 /// </summary>
 /// <param name="tid">a thread id to add</param>
 /// <param name="contract">IContract</param>
 public void AddToBacktrack(int tid, IContract contract)
 {
     List[tid].Backtrack = true;
     contract.Assert(List[tid].Enabled);
 }
예제 #11
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);
        }