2008-03-05 09:52:00 -05:00
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
|
|
|
|
|
|
|
// 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))]
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
namespace MarmotBugs
|
|
|
|
{
|
2008-03-05 09:52:00 -05:00
|
|
|
[ConsoleCategory(HelpMessage="Show attributes associated with a file", DefaultAction=true)]
|
|
|
|
internal class Parameters {
|
|
|
|
|
|
|
|
[InputEndpoint("data")]
|
|
|
|
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
|
|
|
|
|
|
|
|
[OutputEndpoint("data")]
|
|
|
|
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
|
|
|
|
|
|
|
|
[LongParameter( "t", Default=1, HelpMessage="threads")]
|
|
|
|
internal long threads;
|
|
|
|
|
|
|
|
reflective internal Parameters();
|
|
|
|
|
|
|
|
internal int AppMain() {
|
|
|
|
Bug00013.AppMain(this);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
class DebugPrintSpin
|
|
|
|
{
|
2008-03-05 09:52:00 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
class Bug00013
|
|
|
|
{ //: Runnable {
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
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) {
|
2008-11-17 18:29:00 -05:00
|
|
|
if (!b) {
|
2008-03-05 09:52:00 -05:00
|
|
|
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();
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
//
|
|
|
|
//new WatchDog().start();
|
|
|
|
//try {
|
|
|
|
// Thread.sleep(1000);
|
|
|
|
//}
|
|
|
|
//catch (InterruptedException e) {
|
|
|
|
//}
|
|
|
|
///*
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
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();
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
//
|
|
|
|
//public override String ToString() {
|
|
|
|
// if (nodename != null) return(nodename);
|
|
|
|
// return(base.ToString());
|
|
|
|
//}
|
|
|
|
//
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
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();
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
conflict = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!conflict) {
|
|
|
|
traversalLimit = nodeTraverse;
|
|
|
|
Bug00013 last = this;
|
|
|
|
Bug00013 next = this;
|
|
|
|
Bug00013 node = new Bug00013();
|
|
|
|
anchor.addLink(this, node);
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < newThreads; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
traversalLimit = nodeTraverse;
|
|
|
|
int strides = 0;
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int j = 0; j < newNodes; j++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
recordUndead();
|
|
|
|
node = new Bug00013();
|
|
|
|
if (wasteSpace) {
|
|
|
|
while (newNodes
|
|
|
|
< newRejects*random.NextDouble()) {
|
|
|
|
Object ooo = new int[1057];
|
|
|
|
node = new Bug00013();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
strides = 100 + (int)(1000*random.NextDouble());
|
|
|
|
last = traverse(last, strides);
|
|
|
|
while (!addLink(last, node)) {
|
|
|
|
strides = 100 + (int)(1000*random.NextDouble());
|
|
|
|
last = traverse(last, strides);
|
|
|
|
}
|
|
|
|
strides = 100 + (int)(1000*random.NextDouble());
|
|
|
|
next = traverse(next, strides);
|
|
|
|
while (!addLink(next, node)) {
|
|
|
|
strides = 100 + (int)(1000*random.NextDouble());
|
|
|
|
next = traverse(next, strides);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.Write("n");
|
|
|
|
Console.Write(threadid);
|
|
|
|
DebugPrintSpin.Unlock();
|
|
|
|
traversalLimit = linkTraverse;
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int j = 4*newNodes; j < newLinks; j += 2) {
|
2008-03-05 09:52:00 -05:00
|
|
|
last = traverse(last, strides);
|
|
|
|
next = traverse(next, strides);
|
|
|
|
while (!addLink(last, next)) {
|
|
|
|
strides = 100 + (int)(1000*random.NextDouble());
|
|
|
|
last = traverse(last, strides);
|
|
|
|
strides = 100 + (int)(1000*random.NextDouble());
|
|
|
|
next = traverse(next, strides);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.Write("l");
|
|
|
|
Console.Write(threadid);
|
|
|
|
DebugPrintSpin.Unlock();
|
|
|
|
|
|
|
|
Thread newThread = new Thread(new ThreadStart(last.run));
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.Write("t");
|
|
|
|
Console.Write(threadid);
|
|
|
|
DebugPrintSpin.Unlock();
|
|
|
|
newThread.Start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lock (Lock) {
|
|
|
|
recordUndead();
|
|
|
|
Assert(numThreadsAlive > 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();
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < numStrides; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Assert(traversalsLeft >= 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;
|
|
|
|
}
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2008-03-05 09:52:00 -05:00
|
|
|
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;
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < last.numLinks; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (last.links[i] == next) {
|
|
|
|
lastLinked = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lastLinked) {
|
|
|
|
last.links[last.numLinks++] = next;
|
|
|
|
lastLinks = last.numLinks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
checkConsistency();
|
|
|
|
}
|
|
|
|
if (!lastLinked) {
|
|
|
|
// last can't take another link
|
|
|
|
// or these two nodes are already linked
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
lock (next) {
|
|
|
|
checkConsistency();
|
|
|
|
if (next.numLinks < maxLinks) {
|
|
|
|
nextLinked = true;
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < next.numLinks; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Assert(next.links[i] != last,
|
|
|
|
"addlink() should not already be linked to last");
|
|
|
|
}
|
|
|
|
next.links[next.numLinks++] = last;
|
|
|
|
nextLinks = next.numLinks;
|
|
|
|
}
|
|
|
|
checkConsistency();
|
|
|
|
}
|
|
|
|
if (nextLinked) {
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
lock (last) {
|
|
|
|
checkConsistency();
|
|
|
|
Assert(last.numLinks>0, "addlink() last.numLinks should be > 0");
|
|
|
|
last.numLinks--;
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < last.numLinks; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (last.links[i] == next) {
|
|
|
|
last.links[i] = last.links[last.numLinks];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
last.links[last.numLinks] = null;
|
|
|
|
checkConsistency();
|
|
|
|
}
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void notifyPending() {
|
|
|
|
lock (Lock) {
|
|
|
|
Bug00013 firstPending = pendingQueue;
|
|
|
|
if ((firstPending != null) && (numThreadsActive < maxActive)) {
|
|
|
|
pendingQueue = firstPending.nextPending;
|
|
|
|
firstPending.nextPending = null;
|
|
|
|
lock (firstPending) {
|
|
|
|
firstPending.isPending = false;
|
|
|
|
Monitor.PulseAll(firstPending);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void recordUndead() {
|
|
|
|
if (threadid == 0) DebugBreak();
|
|
|
|
deadman = System.DateTime.Now;
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < numUndeadThreadids; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (undeadThreadids[i] == threadid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (undeadThreadids[i] > threadid) {
|
|
|
|
if (numUndeadThreadids == undeadThreadids.Length) {
|
|
|
|
numUndeadThreadids--;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int j = numUndeadThreadids; j > i; j--) {
|
2008-03-05 09:52:00 -05:00
|
|
|
undeadThreadids[j] = undeadThreadids[j-1];
|
|
|
|
}
|
|
|
|
undeadThreadids[i] = threadid;
|
|
|
|
numUndeadThreadids++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (numUndeadThreadids == undeadThreadids.Length) return;
|
|
|
|
undeadThreadids[numUndeadThreadids++] = threadid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DebugPrintUndead() {
|
|
|
|
char sep = ':';
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < numUndeadThreadids; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
Console.Write(sep);
|
|
|
|
Console.Write(undeadThreadids[i]);
|
|
|
|
sep = ',';
|
|
|
|
}
|
|
|
|
numUndeadThreadids = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkConsistency() {
|
|
|
|
bool locked = false;
|
|
|
|
if (this.GetType() != bug13Type) {
|
|
|
|
if (!locked) {
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.WriteLine();
|
|
|
|
Console.Write("Bug00013 ");
|
|
|
|
Console.Write(this);
|
|
|
|
Console.WriteLine(":");
|
|
|
|
locked = true;
|
|
|
|
}
|
|
|
|
Console.Write(" vtable ");
|
|
|
|
Console.Write(this.GetType());
|
|
|
|
Console.Write(" s/b ");
|
|
|
|
Console.Write(bug13Type);
|
|
|
|
Console.WriteLine();
|
|
|
|
}
|
|
|
|
if (links.GetType() != linksType) {
|
|
|
|
if (!locked) {
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.WriteLine();
|
|
|
|
Console.Write("Bug00013 ");
|
|
|
|
Console.Write(this);
|
|
|
|
Console.WriteLine(":");
|
|
|
|
locked = true;
|
|
|
|
}
|
|
|
|
Console.Write(" links.vtable ");
|
|
|
|
Console.Write(links.GetType());
|
|
|
|
Console.Write(" s/b ");
|
|
|
|
Console.Write(linksType);
|
|
|
|
Console.WriteLine();
|
|
|
|
}
|
|
|
|
if (links.Length != maxLinks) {
|
|
|
|
if (!locked) {
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.WriteLine();
|
|
|
|
Console.Write("Bug00013 ");
|
|
|
|
Console.Write(this);
|
|
|
|
Console.WriteLine(":");
|
|
|
|
locked = true;
|
|
|
|
}
|
|
|
|
Console.Write(" links.Length ");
|
|
|
|
Console.Write(links.Length);
|
|
|
|
Console.Write(" s/b ");
|
|
|
|
Console.Write(maxLinks);
|
|
|
|
Console.WriteLine();
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < links.Length; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
if (links[i] == null) continue;
|
|
|
|
if (links[i].GetType() != bug13Type) {
|
|
|
|
if (!locked) {
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.WriteLine();
|
|
|
|
Console.Write("Bug00013 ");
|
|
|
|
Console.Write(this);
|
|
|
|
Console.WriteLine(":");
|
|
|
|
locked = true;
|
|
|
|
}
|
|
|
|
Console.Write(" links[");
|
|
|
|
Console.Write(i);
|
|
|
|
Console.Write("].vtable ");
|
|
|
|
Console.Write(this.GetType());
|
|
|
|
Console.Write(" s/b ");
|
|
|
|
Console.Write(bug13Type);
|
|
|
|
Console.WriteLine();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (locked) {
|
|
|
|
DebugBreak();
|
|
|
|
DebugPrintSpin.Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// node fields
|
|
|
|
|
|
|
|
int nodeid;
|
|
|
|
String nodename;
|
|
|
|
int numLinks;
|
|
|
|
Bug00013[] links;
|
|
|
|
|
|
|
|
// thread/runnable fields
|
|
|
|
|
|
|
|
int threadid;
|
|
|
|
Random random;
|
|
|
|
int traversalLimit;
|
|
|
|
int traversalsLeft;
|
|
|
|
bool isPending;
|
|
|
|
Bug00013 nextPending;
|
|
|
|
|
|
|
|
// global/statics
|
|
|
|
|
|
|
|
static Bug00013 anchor;
|
|
|
|
|
|
|
|
static Object Lock;
|
|
|
|
static int nodeidGenerator;
|
|
|
|
static int threadidGenerator;
|
|
|
|
static int numThreadsAlive;
|
|
|
|
static int numThreadsActive;
|
|
|
|
static DateTime deadman;
|
|
|
|
static Type ClassBug00013;
|
|
|
|
static Bug00013 pendingQueue;
|
|
|
|
static int numUndeadThreadids;
|
|
|
|
static int[] undeadThreadids;
|
|
|
|
|
|
|
|
static Type bug13Type;
|
|
|
|
static Type linksType;
|
|
|
|
}
|
|
|
|
|
2008-11-17 18:29:00 -05:00
|
|
|
class WatchDog
|
|
|
|
{ // : Thread {
|
2008-03-05 09:52:00 -05:00
|
|
|
WatchDog() {} //: base("WatchDog") {}
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.WriteLine("WatchDog sleeping");
|
|
|
|
DebugPrintSpin.Unlock();
|
|
|
|
//try {
|
|
|
|
Thread.Sleep(200000);
|
|
|
|
//} catch(ThreadInterruptedException) {
|
|
|
|
//DebugPrintSpin.Lock();
|
|
|
|
//Console.WriteLine("!");
|
|
|
|
//DebugPrintSpin.Unlock();
|
|
|
|
//}
|
|
|
|
DebugPrintSpin.Lock();
|
|
|
|
Console.WriteLine("WatchDog awake");
|
|
|
|
Bug00013.DebugDumpThreadAnchorTable(4);
|
2008-11-17 18:29:00 -05:00
|
|
|
Console.WriteLine("WatchDog exitting");
|
2008-03-05 09:52:00 -05:00
|
|
|
DebugPrintSpin.Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|