singrdk/base/Kernel/Singularity/X86/ThreadContext.cs

285 lines
11 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: ThreadContext.cs
//
// Note:
//
namespace Microsoft.Singularity.X86
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Singularity.V1.Threads;
using Microsoft.Singularity.X86;
[NoCCtor]
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
internal struct ThreadContext
{
[AccessedByRuntime("referenced from c++")]
internal ushort num;
[AccessedByRuntime("referenced from c++")]
internal ushort regs;
[AccessedByRuntime("referenced from c++")]
internal unsafe ThreadContext * prev;
[AccessedByRuntime("referenced from c++")]
internal unsafe ThreadContext * next;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr cr2;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr cr3;
[AccessedByRuntime("referenced from c++")]
internal unsafe ThreadContext * prevInKern;
[AccessedByRuntime("referenced from c++")]
internal unsafe ThreadContext * nextInKern;
[AccessedByRuntime("referenced from c++")]
internal unsafe ThreadContext * prevInProc;
[AccessedByRuntime("referenced from c++")]
internal unsafe ThreadContext * nextInProc;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr err;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr eip;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr cs0;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr efl;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr eax;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr ebx;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr ecx;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr edx;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr esp;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr ebp;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr esi;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr edi;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr stackBegin;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr stackLimit;
[AccessedByRuntime("referenced from c++")]
internal ushort processId;
[AccessedByRuntime("referenced from c++")]
internal bool uncaughtFlag; // true means "uncaught exception from process, so throw exception in kernel"
[AccessedByRuntime("referenced from halforgc.asm")]
internal bool suspendAlert; // true means "check whether thread should suspend"
// Note: These two forks must be exactly the same size, but their
// fields alias differently for kernel or process code.
#if SINGULARITY_KERNEL
[AccessedByRuntime("referenced from c++")]
internal unsafe Thread *_thread;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr processThread;
[AccessedByRuntime("referenced from c++")]
internal unsafe System.GCs.CallStack.TransitionRecord * stackMarkers;
[AccessedByRuntime("referenced from c++")]
internal unsafe System.GCs.CallStack.TransitionRecord * processMarkers;
[AccessedByRuntime("referenced from c++")]
internal ushort threadIndex;
[AccessedByRuntime("referenced from c++")]
internal ushort processThreadIndex;
#elif SINGULARITY_PROCESS
[AccessedByRuntime("referenced from c++")]
internal UIntPtr kernelThread;
[AccessedByRuntime("referenced from c++")]
internal unsafe Thread *_thread;
[AccessedByRuntime("referenced from c++")]
internal unsafe System.GCs.CallStack.TransitionRecord * kernelMarkers;
[AccessedByRuntime("referenced from c++")]
internal unsafe System.GCs.CallStack.TransitionRecord * stackMarkers;
[AccessedByRuntime("referenced from c++")]
internal ushort kernelThreadIndex;
[AccessedByRuntime("referenced from c++")]
internal ushort threadIndex;
#endif
[AccessedByRuntime("referenced from halforgc.asm")]
internal unsafe int gcStates;
// See ThreadContext.IsInKernelMode
private unsafe System.GCs.CallStack.TransitionRecord * modeMarker;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr dr0;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr dr1;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr dr2;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr dr3;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr dr6;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr dr7;
[AccessedByRuntime("referenced from c++")]
internal MmxContext mmx;
#if PAGING
[AccessedByRuntime("referenced from c++")]
internal UIntPtr abiStackHead;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr abiStackBegin;
[AccessedByRuntime("referenced from c++")]
internal UIntPtr abiStackLimit;
#endif
#if THREAD_TIME_ACCOUNTING
[AccessedByRuntime("referenced from c++")]
internal ulong lastExecutionTimeUpdate;
[AccessedByRuntime("referenced from c++")]
internal ulong executionTime;
#endif
//////////////////////////////////////////////// Methods & Properties.
//
internal Thread thread {
[NoHeapAllocation]
get { return GetThread(); }
}
[NoHeapAllocation]
internal unsafe bool IsFirst()
{
return (((UIntPtr)prev) == UIntPtr.Zero);
}
internal bool WasInterrupted {
[NoHeapAllocation]
get { return (efl & EFlags.IF) != 0; }
}
[AccessedByRuntime("referenced from c++")]
// Return true if the thread is in kernel mode, false if the
// thread is in process mode.
// Note that by the time this method returns, the thread might
// have already switched to a different mode; in other words,
// don't rely on this result of this method being up-to-date unless
// the thread is suspended or blocked.
[NoHeapAllocation]
internal unsafe bool IsInKernelMode()
{
// When a thread enters process mode, RuntimeEntryPoint
// sets modeMarker=processMarkers. Thus, in process mode:
//
// modeMarker == processMarkers
//
// When a thread in process mode calls the kernel, pushStackMark
// pushes a child process marker onto the stack, so that
// modeMarker is left pointing to the new processMarker's
// parent (the old processMarker). Thus, in kernel mode:
//
// modeMarker == parent(processMarkers)
//
// This keeps the mode in sync with the process stack markers,
// which is convenient though not essential. This assumes that
// the only reason a process pushes a stack marker is to enter
// kernel mode.
//
// Since processMarkers may be null, ThreadContext.ParentModeMarker
// defines a special definition for parent(null).
#if SINGULARITY_PROCESS
System.GCs.CallStack.TransitionRecord * processMarkers =
stackMarkers;
#endif // SINGULARITY_PROCESS
if (modeMarker == processMarkers) {
return false;
}
else {
VTable.Assert(modeMarker == ParentModeMarker(processMarkers));
return true;
}
}
[AccessedByRuntime("referenced from c++")]
[NoHeapAllocation]
internal unsafe void SetKernelMode()
{
#if SINGULARITY_PROCESS
System.GCs.CallStack.TransitionRecord * processMarkers =
stackMarkers;
#endif // SINGULARITY_PROCESS
modeMarker = ParentModeMarker(processMarkers);
}
[AccessedByRuntime("referenced from c++")]
[NoHeapAllocation]
internal unsafe void SetProcessMode()
{
#if SINGULARITY_PROCESS
System.GCs.CallStack.TransitionRecord * processMarkers =
stackMarkers;
#endif // SINGULARITY_PROCESS
modeMarker = processMarkers;
}
[NoHeapAllocation]
static private unsafe System.GCs.CallStack.TransitionRecord *
ParentModeMarker(System.GCs.CallStack.TransitionRecord * child)
{
System.GCs.CallStack.TransitionRecord * bottom =
(System.GCs.CallStack.TransitionRecord *) (-1);
VTable.Assert(child != bottom);
if (child == null) {
return bottom;
}
else {
return child->oldTransitionRecord;
}
}
//////////////////////////////////////////////////// External Methods.
//
[AccessedByRuntime("output to header: defined in c++")]
[MethodImpl(MethodImplOptions.InternalCall)]
[StackBound(32)]
[NoHeapAllocation]
private extern Thread GetThread();
[AccessedByRuntime("output to header: defined in c++")]
[MethodImpl(MethodImplOptions.InternalCall)]
[StackBound(32)]
[NoHeapAllocation]
internal extern void UpdateAfterGC(Thread thread);
[AccessedByRuntime("output to header: defined in c++")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(32)]
[NoHeapAllocation]
internal extern void Initialize(int threadIndex, UIntPtr stackBegin, uint cr3);
#if SINGULARITY_KERNEL
[AccessedByRuntime("output to header: defined in c++")]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(32)]
[NoHeapAllocation]
internal extern void InitializeIdle(int threadIndex, UIntPtr stackBegin, uint cr3);
#endif
}
}