Example #1
0
        private static unsafe void ThreadStub(int threadIndex)
        {
            Transitions.ThreadStart();
            GC.ThreadStartNotification(threadIndex);
            Thread currentThread = threadTable[threadIndex];

            if (AddThread(threadIndex))
            {
                // Log Thread Start.
                Tracing.Log(Tracing.Audit, "ThreadStub(atid={0}) Entered",
                            (UIntPtr) unchecked ((uint)threadIndex));

                ThreadStart startFun = currentThread.threadStart;

                try {
                    startFun();
                }
                catch (Exception uncaughtException) {
                    // Save Uncaught Exception in Thread instance.
                    currentThread.lastUncaughtException = uncaughtException;

                    // Dump (possibly nested) Exceptions to the Debugger.
                    //  Note: The first line identifies the outer exception,
                    //  later lines identify the inner exceptions nesting level.
                    string    formatString;
                    uint      nestingLevel     = 0;
                    Exception currentException = uncaughtException;
                    formatString = "Thread{0,3}   Outer" +
                                   " Exception: Type '{2}', Message '{3}'.";
                    while (currentException != null)
                    {
                        DebugStub.WriteLine(
                            formatString,
                            __arglist(threadIndex,
                                      nestingLevel,
                                      currentException.GetType().ToString(),
                                      currentException.Message));
                        currentException = currentException.InnerException;
                        formatString     = "Thread{0,3} Inner{1,2}" +
                                           " Exception: Type '{2}', Message '{3}'.";
                        if (++nestingLevel > 16)
                        {
                            break;
                        }
                    }

                    // Assert (always asserts as exception is never null here).
                    string message = uncaughtException.Message;
                    if (message == null)
                    {
                        message = String.Empty;
                    }

                    VTable.Assert(uncaughtException == null,
                                  "Thread " + threadIndex +
                                  " failed with Exception Type '" +
                                  uncaughtException.GetType().ToString() +
                                  "', Message '" + message + "'.");
                }

                // Log Thread Exit.
                Tracing.Log(Tracing.Audit, "ThreadStub(atid={0}) Exiting",
                            (UIntPtr) unchecked ((uint)threadIndex));
            }

            currentThread.joinEvent.Set();
            RemoveThread(threadIndex);
            GC.DeadThreadNotification(currentThread);

            bool disabled = Processor.DisableLocalPreemption();

            // REVIEW: this is a dangerous locking strategy as the transition code
            // may decide it needs to wake up another thread.
            Thread.threadTableLock.Acquire(currentThread);
            try {
                Transitions.ThreadEnd(threadIndex);
                // You may not do any calls out of proc after this point!
                threadTable[threadIndex] = null;
                Transitions.DeadThreadNotification(threadIndex);
            }
            finally {
                Thread.threadTableLock.Release(currentThread);
                Processor.RestoreLocalPreemption(disabled);
            }
        }