// . Check for optimal number of barriers needed for a program // by trying to put at every possible configurations starting // from the configuration with 1, 2, 3, ... barriers. // . We could not do this checking directly on the flow graph // because it is not possible to check whether a configuration // is disabled by a particular barrier (suppose there is a branch // and the barrier comes before it, the transition is a reordering // between an instruction after the branch and the one before the // branch. The barriers may even change the branch condition // . So for every configuration we need to run the reachablity // analysis again. public static void CheckOptimality(State st0) { int i; stateSet.AddState(st0); FindGoodState(st0); Console.Write("Good end values:"); for(i = 0; i < goodReportedValues.Count; i++) Console.Write(" {0}", goodReportedValues[i]); Console.WriteLine(); stateSet = new StateSet(); stateSet.AddState(st0); badState = -1; possibleLocations = new Hashtable(); FindBadState(st0); int nLocations = 0; IDictionaryEnumerator iter = possibleLocations.GetEnumerator(); while(iter.MoveNext()) if(((CILInstruction)iter.Value).ParentMethod.Name.Equals(".ctor") == false) nLocations++; marker = new int[nLocations]; for(i = 0; i < marker.Length; i++) marker[i] = 0; ins = new CILInstruction[marker.Length]; iter = possibleLocations.GetEnumerator(); i = 0; while(iter.MoveNext()) if(((CILInstruction)iter.Value).ParentMethod.Name.Equals(".ctor") == false) ins[i++] = (CILInstruction)iter.Value; found = false; int nBarriers = 1; initialState = st0; while(found == false) { Console.WriteLine("progress: nBarriers = {0}", nBarriers); last = -1; GenerateCases(nBarriers); nBarriers++; } for(i = 0; i < marker.Length; i++) if(marker[i] == 1) Console.WriteLine(ins[i].ParentMethod.Name + ":" + ins[i]); }
static void GenerateCases(int depth) { for(int i = last + 1; i < marker.Length;i++) { if(marker[i] == 0) { marker[i] = 1; int oldLast = last; last = i; if(depth >= 4) Console.WriteLine("progress: {0}: {1} of {2}", depth, i, marker.Length); CILInstruction barrier = new CIL_call("xxxx", program.GetClass("[mscorlib]System.Threading.Thread").GetMethod("MemoryBarrier", "()")); if(ins[i].ParentMethod.InsertInstruction(ins[i].ID, barrier) == false) throw new Exception("Exception at insert instruction"); if(depth == 1) { badState = -1; stateSet = new StateSet(); stateSet.AddState(initialState); FindFirstBadState(initialState); if(badState == -1) { found = true; return; } } else { GenerateCases(depth - 1); if(found) return; } if(ins[i].ParentMethod.RemoveInstruction(barrier.ID) == false) throw new Exception("Exception at remove instruction"); last = oldLast; marker[i] = 0; } } }