// // Copyright (c) Microsoft Corporation. All rights reserved. // // Some sort of threads/locking test. // See usage for parameter. // DebubPrintSpinLock was in the Marmot runtime. using System; using System.Threading; using Microsoft.Contracts; using Microsoft.SingSharp.Reflection; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Applications; using Microsoft.Singularity.Io; using Microsoft.Singularity.Configuration; [assembly: Transform(typeof(ApplicationResourceTransform))] namespace MarmotBugs { [ConsoleCategory(HelpMessage="Show attributes associated with a file", DefaultAction=true)] internal class Parameters { [InputEndpoint("data")] public readonly TRef Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [LongParameter( "t", Default=1, HelpMessage="threads")] internal long threads; reflective internal Parameters(); internal int AppMain() { Bug00013.AppMain(this); return 0; } } class DebugPrintSpin { private static Object locker = new Object(); public static void Lock() { // Class_java_lang_Thread *currentThread = CurrentThread(); // currentThread->f_isAwaitingDebugPrintSpinLock = true; System.Threading.Monitor.Enter(locker); // DebugPrintCriticalSectionHolder = currentThread; // currentThread->f_isAwaitingDebugPrintSpinLock = false; } public static void Unlock() { // DebugPrintCriticalSectionHolder = NULL; System.Threading.Monitor.Exit(locker); } } class Bug00013 { //: Runnable { static int totalThreads = Int32.MaxValue; const bool wasteSpace = true; const bool showPended = false; const int maxLinks = 10; const int maxThreads = 10; const int maxActive = 4; const int nodeTraverse= 50; const int linkTraverse= 500; const int newThreads = 2; //10; const int newNodes = 100; const int newLinks = 700; const int newRejects = 1000; // conversion filler public static void DebugDumpThreadAnchorTable(int i) {} private static void DebugBreak() { Assert(false, "DebugBreak"); } private static void Assert(bool b) { Assert(b, "Assertion failed"); } private static void Assert(bool b, String s) { if(!b) { DebugPrintSpin.Lock(); Console.WriteLine(s); Console.WriteLine("Failed Bug00013"); DebugPrintSpin.Unlock(); Environment.Exit(1); } } // end conversion void nonsyncv() { lock (this) { DebugPrintSpin.Lock(); Console.WriteLine("within nonsyncv()"); DebugDumpThreadAnchorTable(4); DebugPrintSpin.Unlock(); } } [System.Runtime.CompilerServices.MethodImpl (System.Runtime.CompilerServices.MethodImplOptions.Synchronized)] void syncv() { DebugPrintSpin.Lock(); Console.WriteLine("within syncv()"); DebugDumpThreadAnchorTable(4); DebugPrintSpin.Unlock(); } static void nonsyncs() { lock (ClassBug00013) { DebugPrintSpin.Lock(); Console.WriteLine("within nonsyncs()"); DebugDumpThreadAnchorTable(4); DebugPrintSpin.Unlock(); } } [System.Runtime.CompilerServices.MethodImpl (System.Runtime.CompilerServices.MethodImplOptions.Synchronized)] static void syncs() { DebugPrintSpin.Lock(); Console.WriteLine("within syncs()"); DebugDumpThreadAnchorTable(4); DebugPrintSpin.Unlock(); } static void usage() { Console.WriteLine("usage: Bug00013 [total_threads]"); Environment.Exit(1); } internal static void AppMain(Parameters! config) { totalThreads = (int)config.threads; undeadThreadids = new int[2*maxThreads]; DebugPrintSpin.Lock(); Console.WriteLine("Bug00013.Main()"); DebugDumpThreadAnchorTable(4); DebugPrintSpin.Unlock(); Object Lock = new Object(); Bug00013.Lock = Lock; DebugPrintSpin.Lock(); Console.Write("Bug00013.Lock = "); Console.WriteLine(Lock.GetHashCode()); DebugPrintSpin.Unlock(); anchor = new Bug00013(); DebugPrintSpin.Lock(); Console.Write("Bug00013.Type = "); Console.WriteLine(anchor.GetType()); DebugPrintSpin.Unlock(); ClassBug00013 = anchor.GetType(); DebugPrintSpin.Lock(); Console.Write("Bug00013.class = "); Console.WriteLine(ClassBug00013.GetHashCode()); DebugPrintSpin.Unlock(); bug13Type = anchor.GetType(); linksType = anchor.links.GetType(); //================================================================== DebugPrintSpin.Lock(); Console.WriteLine(); Console.WriteLine("//======================================" + "======================================="); Console.WriteLine(); Console.WriteLine("before nonsyncv()"); DebugPrintSpin.Unlock(); anchor.nonsyncv(); DebugPrintSpin.Lock(); Console.WriteLine("after nonsyncv()"); DebugPrintSpin.Unlock(); //================================================================== DebugPrintSpin.Lock(); Console.WriteLine(); Console.WriteLine("//======================================" + "======================================="); Console.WriteLine(); Console.WriteLine("before syncv()"); DebugPrintSpin.Unlock(); anchor.syncv(); DebugPrintSpin.Lock(); Console.WriteLine("after syncv()"); DebugPrintSpin.Unlock(); //================================================================== DebugPrintSpin.Lock(); Console.WriteLine(); Console.WriteLine("//======================================" + "======================================="); Console.WriteLine(); Console.WriteLine("before nonsyncs()"); DebugPrintSpin.Unlock(); nonsyncs(); DebugPrintSpin.Lock(); Console.WriteLine("after nonsyncs()"); DebugPrintSpin.Unlock(); //================================================================== DebugPrintSpin.Lock(); Console.WriteLine(); Console.WriteLine("//======================================" + "======================================="); Console.WriteLine(); Console.WriteLine("before syncs()"); DebugPrintSpin.Unlock(); syncs(); DebugPrintSpin.Lock(); Console.WriteLine("after syncs()"); DebugPrintSpin.Unlock(); //================================================================== Thread newThread = new Thread(new ThreadStart(anchor.run)); DebugPrintSpin.Lock(); Console.WriteLine(); Console.WriteLine("//======================================" + "======================================="); Console.WriteLine(); Console.Write("newThread = "); Console.WriteLine(newThread.GetHashCode()); DebugPrintSpin.Unlock(); /* new WatchDog().start(); try { Thread.sleep(1000); } catch(InterruptedException e) { } /**/ newThread.Start(); deadman = System.DateTime.Now; for (;;) { //try { Thread.Sleep(25000); //} catch(ThreadInterruptedException) { //DebugPrintSpin.Lock(); //Console.WriteLine("!"); //DebugPrintSpin.Unlock(); // } lock (Lock) { DebugPrintSpin.Lock(); long deadms = (System.DateTime.Now - deadman).Milliseconds; if (deadms > 100000) { Console.WriteLine(); Console.WriteLine("Bug00013.Main()" + " deadman expired"); DebugDumpThreadAnchorTable(4); DebugBreak(); } else { Console.WriteLine(); Console.Write(" ?<0,"); Console.Write(numThreadsAlive); Console.Write(","); Console.Write(numThreadsActive); DebugPrintUndead(); Console.Write("> "); } DebugPrintSpin.Unlock(); if (numThreadsAlive == 0) break; } } Console.WriteLine("Passed Bug00013"); } Bug00013() { lock (Lock) { nodeid = nodeidGenerator++; } nodename = ("Node" + nodeid); links = new Bug00013[maxLinks]; } /* public override String ToString() { if (nodename != null) return(nodename); return(base.ToString()); } */ public void run() { int myNumThreadsAlive; int myNumThreadsActive; lock (Lock) { Assert(numThreadsAlive >= 0, "run() numThreadsAlive should be >= 0"); Assert(numThreadsActive >= 0, "run() numThreadsActive should be >= 0"); numThreadsAlive++; myNumThreadsAlive = numThreadsAlive; numThreadsActive++; myNumThreadsActive = numThreadsActive; threadid = ++threadidGenerator; recordUndead(); } DebugPrintSpin.Lock(); Console.WriteLine(); Console.Write("T+<"); Console.Write(threadid); Console.Write(","); Console.Write(myNumThreadsAlive); Console.Write(","); Console.Write(myNumThreadsActive); Console.Write("> "); DebugPrintSpin.Unlock(); if ((myNumThreadsAlive <= maxThreads) && (threadid < totalThreads)) { bool conflict = false; lock (this) { if (random == null) { random = new Random(); } else { conflict = true; } } if (!conflict) { traversalLimit = nodeTraverse; Bug00013 last = this; Bug00013 next = this; Bug00013 node = new Bug00013(); anchor.addLink(this, node); for (int i=0; i 0, "run() numThreadsAlive should be > 0"); Assert(numThreadsActive > 0, "run() numThreadsActive should be > 0"); numThreadsAlive--; myNumThreadsAlive = numThreadsAlive; numThreadsActive--; myNumThreadsActive = numThreadsActive; } DebugPrintSpin.Lock(); Console.WriteLine(); Console.Write("T-<"); Console.Write(threadid); Console.Write(","); Console.Write(myNumThreadsAlive); Console.Write(","); Console.Write(myNumThreadsActive); Console.Write("> "); DebugPrintSpin.Unlock(); notifyPending(); } Bug00013 traverse(Bug00013 node, int numStrides) { lock (Lock) { recordUndead(); } for (int i=0; i= 0); if (traversalsLeft > traversalLimit) { traversalsLeft = traversalLimit; } if (traversalsLeft == 0) { bool pended = false; int myNumThreadsAlive; int myNumThreadsActive; lock (Lock) { Assert(numThreadsActive > 0); Assert(nextPending == null); if ((numThreadsActive > maxActive) || (pendingQueue != null)) { pended = showPended; isPending = true; if (pendingQueue != null) { Bug00013 pend = pendingQueue; for (;;) { Bug00013 curr = pend; pend = curr.nextPending; if (pend == null) { curr.nextPending = this; break; } } } else { pendingQueue = this; } } numThreadsActive--; myNumThreadsAlive = numThreadsAlive; myNumThreadsActive = numThreadsActive; } if (pended) { DebugPrintSpin.Lock(); Console.WriteLine(); Console.Write("T_<"); Console.Write(threadid); Console.Write(","); Console.Write(myNumThreadsAlive); Console.Write(","); Console.Write(myNumThreadsActive); Console.Write("> "); DebugPrintSpin.Unlock(); } notifyPending(); lock (this) { while (isPending) { //try { Monitor.Wait(this); //} catch(ThreadInterruptedException) {} } Assert(nextPending == null); } lock (Lock) { Assert(numThreadsAlive > 0, "run() numThreadsAlive should be > 0"); Assert(numThreadsActive >= 0, "run() numThreadsActive should be >= 0"); myNumThreadsAlive = numThreadsAlive; numThreadsActive++; myNumThreadsActive = numThreadsActive; recordUndead(); } if (pended) { DebugPrintSpin.Lock(); Console.WriteLine(); Console.Write("T=<"); Console.Write(threadid); Console.Write(","); Console.Write(myNumThreadsAlive); Console.Write(","); Console.Write(myNumThreadsActive); Console.Write("< "); DebugPrintSpin.Unlock(); } traversalsLeft = traversalLimit; } traversalsLeft--; lock (node) { if (node.numLinks > 0) { int link = (int)(node.numLinks*random.NextDouble()); Assert(link >= 0, "traverse() selected link should be nonnegative"); Assert(link < node.numLinks, "traverse() selected link should be < numLinks"); if (node.links[link] == null) { DebugPrintSpin.Lock(); Console.WriteLine("BUG at link "+link); for (int ii = 0; ii < node.numLinks; ii++) { Console.WriteLine("link["+ii+"] is " +node.links[ii]); } Console.WriteLine("link["+link+"] is " +node.links[link]); DebugPrintSpin.Unlock(); } Assert(node.links[link] != null, "traverse() selected link should not be null"); node = node.links[link]; } } } return(node); } bool addLink(Bug00013 last, Bug00013 next) { Assert(last != null, "addlink() last should not be null"); Assert(next != null, "addlink() next should not be null"); if (last == next) return(false); bool lastLinked = false; int lastLinks; bool nextLinked = false; int nextLinks; lock (last) { checkConsistency(); if (last.numLinks < maxLinks) { lastLinked = true; for (int i=0; i0, "addlink() last.numLinks should be > 0"); last.numLinks--; for (int i=0; i threadid) { if (numUndeadThreadids == undeadThreadids.Length) { numUndeadThreadids--; } for (int j=numUndeadThreadids; j>i; j--) { undeadThreadids[j] = undeadThreadids[j-1]; } undeadThreadids[i] = threadid; numUndeadThreadids++; return; } } if (numUndeadThreadids == undeadThreadids.Length) return; undeadThreadids[numUndeadThreadids++] = threadid; } static void DebugPrintUndead() { char sep = ':'; for (int i=0; i