singrdk/base/Imported/Bartok/runtime/shared/GCs/Transitions.cs

907 lines
34 KiB
C#
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
2008-03-05 09:52:00 -05:00
/*******************************************************************/
/* WARNING */
/* This file should be identical in the Bartok and Singularity */
/* depots. Master copy resides in Bartok Depot. Changes should be */
/* made to Bartok Depot and propagated to Singularity Depot. */
/*******************************************************************/
namespace System.GCs
{
using System.Runtime.CompilerServices;
using System.Threading;
#if SINGULARITY
using Microsoft.Singularity;
#endif
#if SINGULARITY_KERNEL
using Microsoft.Singularity.Scheduling;
#endif
2008-11-17 18:29:00 -05:00
[AccessedByRuntime("Referenced in halforgc.asm")]
2008-03-05 09:52:00 -05:00
internal class Transitions
{
// Synchronization among threads for GC:
//
// We keep an integer for each thread.
// The possible values are:
#if SINGULARITY_KERNEL
// Thread is dormant or in unmanaged code and a GC would be ok
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int DormantState = 0x1;
// Thread is running in managed code and not ready for GC
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int MutatorState = 0x2;
// GC work is desired
private const int GCRequest = 0x4;
// Thread is under GC control
private const int GCControl = 0x8;
// Thread is dormant in the application space
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int OtherDormantState = 0x10;
// Thread is running in the application space
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int OtherMutatorState = 0x20;
// GC work is desired in the application space
private const int OtherGCRequest = 0x40;
// Application thread is under GC control
private const int OtherGCControl = 0x80;
#else
// Thread is dormant or in unmanaged code and a GC would be ok
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int DormantState = 0x10;
// Thread is running in managed code and not ready for GC
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int MutatorState = 0x20;
// GC work is desired. Must be a power of 2.
private const int GCRequest = 0x40;
// Thread is under GC control. Must be a power of 2.
private const int GCControl = 0x80;
// Thread is dormant in the kernel space
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int OtherDormantState = 0x1;
// Thread is running in the kernel space
[AccessedByRuntime("Referenced in halforgc.asm")]
private const int OtherMutatorState = 0x2;
#endif // SINGULARITY_KERNEL
internal static bool fInitializedRuntime;
internal static void RuntimeInitialized() {
fInitializedRuntime = true;
}
#if SINGULARITY_KERNEL
[Inline]
internal static unsafe
void InitializeStatusWord(ref ThreadContext threadContext)
{
int oldValue, newValue;
do {
oldValue = threadContext.gcStates;
newValue = ((oldValue|DormantState|OtherDormantState)&
~(MutatorState|GCRequest|GCControl|
OtherMutatorState|OtherGCRequest|OtherGCControl));
} while (!CompareAndSwap(ref threadContext.gcStates,
newValue, oldValue));
}
#endif
// Code outside of the GC will move threads between
// MutatorState and DormantState. This should be done with
// the TakeMutatorControl and TakeDormantControl methods. The
// garbage collectors can request that they be notified when
// threads go dormant. They do this by calling the
// MakeGCRequests method. The TakeMutatorControl and
// TakeDormantControl methods are then supposed to do the
// right thing.
[Inline]
private static bool CompareAndSwap(ref int word,
int newValue,
int oldValue)
{
return (Interlocked.CompareExchange(ref word, newValue, oldValue)
== oldValue);
}
#region Transition Methods (Methods corresponding to macro transitions)
// To be called when a thread is created
internal static void NewThreadNotification(int newThreadIndex,
bool initial)
{
#if SINGULARITY_PROCESS
if (initial) {
VTable.Assert(InMutatorState(newThreadIndex));
return;
}
#endif
VTable.Assert(InDormantState(newThreadIndex));
}
// To be called when a thread is terminated/terminating
internal static void DeadThreadNotification(int deadThreadIndex)
{
VTable.Assert(Thread.threadTable[deadThreadIndex] == null);
VTable.Assert(InDormantState(deadThreadIndex));
if (Transitions.HasGCRequest(deadThreadIndex)) {
GC.ThreadDormantGCNotification(deadThreadIndex);
}
}
#if SINGULARITY
#if SINGULARITY_KERNEL
// To be called at the beginning of a thread
internal static unsafe void ThreadStart() {
ThreadContext *currentThreadContext =
Processor.GetCurrentThreadContext();
2008-11-17 18:29:00 -05:00
TakeInitialMutatorControl(currentThreadContext);
2008-03-05 09:52:00 -05:00
}
#else
// To be called at the beginning of a thread
internal static unsafe void ThreadStart() {
ThreadContext *currentThreadContext =
Processor.GetCurrentThreadContext();
// The thread has been started in the kernel. We need
// to ensure that the transition to application space
// is completed properly.
EnsureMutatorControlNoGC(currentThreadContext);
}
#endif
#else // SINGULARITY
// To be called at the beginning of a thread
internal static void ThreadStart(int currentThreadIndex) {
VTable.Assert(InDormantState(currentThreadIndex));
2008-11-17 18:29:00 -05:00
TakeInitialMutatorControl(currentThreadIndex);
2008-03-05 09:52:00 -05:00
}
#endif // SINGULARITY
// To be called at the end of a thread
internal static void ThreadEnd(int currentThreadIndex) {
VTable.Assert(InMutatorState(currentThreadIndex));
TakeDormantControl(currentThreadIndex);
}
#if SINGULARITY
[AccessedByRuntime("called from halforgc.asm")]
2008-11-17 18:29:00 -05:00
[NoStackLinkCheckTrans] // This is called from __pushStackMark, which cannot tolerate an
// ABI call to allocate a new stack
2008-03-05 09:52:00 -05:00
internal static unsafe
void LeaveManagedSpace(ThreadContext *currentThreadContext)
{
TransferMutatorControl(currentThreadContext);
}
// To be used for returning from calls to outside managed space
[AccessedByRuntime("called from halforgc.asm")]
2008-11-17 18:29:00 -05:00
[NoStackLinkCheckTrans] // This is called from __popStackMark, which cannot tolerate an
// ABI call to allocate a new stack
2008-03-05 09:52:00 -05:00
[Inline]
internal static unsafe
void ReturnToManagedSpace(ThreadContext *currentThreadContext)
{
EnsureMutatorControl(currentThreadContext);
}
#if SINGULARITY_KERNEL
[AccessedByRuntime("called from halforgc.asm")]
internal static unsafe
void SuspendThread(ThreadContext *currentThreadContext)
{
TakeDormantControl(currentThreadContext);
}
[AccessedByRuntime("called from halforgc.asm")]
internal static unsafe
void ReviveThread(ThreadContext *currentThreadContext)
{
TakeMutatorControl(currentThreadContext);
}
#endif // SINGULARITY_KERNEL
#else // SINGULARITY
// To be used for calls to outside managed space
[AccessedByRuntime("called from halforgc.asm")]
[Inline]
[ManualRefCounts]
internal static void LeaveManagedSpace(Thread currentThread) {
TakeDormantControl(currentThread.threadIndex);
}
// To be used for returning from calls to outside managed space
[AccessedByRuntime("called from halforgc.asm")]
[Inline]
internal static Thread ReturnToManagedSpace(int currentThreadIndex) {
TakeMutatorControl(currentThreadIndex);
return Thread.threadTable[currentThreadIndex];
}
#endif // SINGULARITY
// For the LoadFunction stub for PInvoke methods
[RequiredByBartok]
internal static void EnterLoadFunctionStub() {
TakeMutatorControl(Thread.GetCurrentThreadIndex());
}
// For the LoadFunction stub for PInvoke methods
[RequiredByBartok]
internal static void LeaveLoadFunctionStub() {
TakeDormantControl(Thread.GetCurrentThreadIndex());
}
#endregion
internal static void MakeGCRequests(int excludedThreadIndex) {
int limit = Thread.threadTable.Length;
for (int i = 0; i < limit; i++) {
if (Thread.threadTable[i] != null &&
i != excludedThreadIndex) {
MakeGCRequest(i);
}
}
}
#region Helper Functions (Independent of where statusWord is)
[Inline]
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
2008-03-05 09:52:00 -05:00
private static bool fInDormantState(int statusWord) {
return ((statusWord & DormantState) != 0);
}
[Inline]
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
2008-03-05 09:52:00 -05:00
private static bool fInMutatorState(int statusWord) {
return ((statusWord & MutatorState) != 0);
}
[Inline]
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
2008-03-05 09:52:00 -05:00
private static bool fHasGCRequest(int statusWord) {
return ((statusWord & GCRequest) != 0);
}
[Inline]
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
2008-03-05 09:52:00 -05:00
private static bool fUnderGCControl(int statusWord) {
return ((statusWord & GCControl) != 0);
}
[Inline]
private static void TakeDormantControl(ref int statusWord,
int threadIndex)
{
VTable.Assert(fInMutatorState(statusWord));
VTable.Deny(fInDormantState(statusWord));
int oldValue, newValue;
do {
oldValue = statusWord;
newValue = (oldValue|DormantState) & ~MutatorState;
} while (!CompareAndSwap(ref statusWord, newValue, oldValue));
if (fHasGCRequest(newValue)) {
GC.ThreadDormantGCNotification(threadIndex);
}
}
[Inline]
private static void TakeDormantControlNoGC(ref int statusWord) {
VTable.Assert(fInMutatorState(statusWord));
VTable.Deny(fInDormantState(statusWord));
int oldValue, newValue;
do {
oldValue = statusWord;
newValue = (oldValue|DormantState) & ~MutatorState;
} while (!CompareAndSwap(ref statusWord, newValue, oldValue));
}
[Inline]
private static void TransferMutatorControl(ref int statusWord,
int threadIndex)
{
if (!CompareAndSwap(ref statusWord,
DormantState|OtherMutatorState,
MutatorState|OtherDormantState)) {
TakeDormantControl(ref statusWord, threadIndex);
}
}
[Inline]
private static void EnsureMutatorControl(ref int statusWord,
int currentThreadIndex)
{
if (!fInMutatorState(statusWord)) {
TakeMutatorControl(ref statusWord, currentThreadIndex);
}
VTable.Deny(fInDormantState(statusWord));
VTable.Deny(fUnderGCControl(statusWord));
}
[Inline]
private static void EnsureMutatorControlNoGC(ref int statusWord,
int currentThreadIndex)
{
if (!fInMutatorState(statusWord)) {
TakeMutatorControlNoGC(ref statusWord, currentThreadIndex);
}
VTable.Deny(fInDormantState(statusWord));
VTable.Deny(fUnderGCControl(statusWord));
}
#if SINGULARITY
[AccessedByRuntime("referenced from halasm.asm")]
2008-11-17 18:29:00 -05:00
[NoStackLinkCheckTrans]
2008-03-05 09:52:00 -05:00
internal static unsafe void RestoreMutatorControlIfNeeded()
{
ThreadContext *currentThreadContext =
Processor.GetCurrentThreadContext();
if (!Transitions.InMutatorState(currentThreadContext)) {
// NOTE: There is a window where OtherMutatorControl may be
// set simultaneously with OtherGCRequest. When clearing
// OtherMutatorControl and setting OtherDormantControl, the
// normal thing to do is to check for a GC request, but in
// this case it doesn't matter as this code is only run
// when an kernel exception is supposed to pass over an
// application stack segment.
int oldValue, newValue;
2008-11-17 18:29:00 -05:00
bool consumedSignal = false;
int threadIndex = currentThreadContext->threadIndex;
2008-03-05 09:52:00 -05:00
do {
oldValue = currentThreadContext->gcStates;
if (fUnderGCControl(oldValue)) {
2008-11-17 18:29:00 -05:00
Thread.WaitForGCEvent(threadIndex);
consumedSignal = true;
2008-03-05 09:52:00 -05:00
}
newValue = ((oldValue|MutatorState|OtherDormantState) &
~(DormantState|OtherMutatorState));
} while (!CompareAndSwap(ref currentThreadContext->gcStates,
newValue, oldValue));
2008-11-17 18:29:00 -05:00
if (consumedSignal) {
Thread.SignalGCEvent(threadIndex);
}
2008-03-05 09:52:00 -05:00
}
}
#endif
[Inline]
private static void TakeMutatorControl(ref int statusWord,
int currentThreadIndex)
{
if (!SwitchToMutatorState(ref statusWord)) {
TakeMutatorControlSlow(ref statusWord, currentThreadIndex);
}
VTable.Assert(fInMutatorState(statusWord));
VTable.Deny(fInDormantState(statusWord));
VTable.Deny(fUnderGCControl(statusWord));
}
[Inline]
private static void TakeMutatorControlNoGC(ref int statusWord,
int currentThreadIndex)
{
if (!SwitchToMutatorState(ref statusWord)) {
TakeMutatorControlSlowNoGC(ref statusWord, currentThreadIndex);
}
VTable.Assert(fInMutatorState(statusWord));
VTable.Deny(fInDormantState(statusWord));
VTable.Deny(fUnderGCControl(statusWord));
}
2008-11-17 18:29:00 -05:00
private static void TakeInitialMutatorControl(ref int statusWord,
int currentThreadIndex)
{
if (!SwitchToMutatorState(ref statusWord)) {
TakeInitialMutatorControlSlow(ref statusWord,
currentThreadIndex);
}
VTable.Assert(fInMutatorState(statusWord));
VTable.Deny(fInDormantState(statusWord));
VTable.Deny(fUnderGCControl(statusWord));
}
2008-03-05 09:52:00 -05:00
[NoInline]
2008-11-17 18:29:00 -05:00
// [StackLinkCheck] Removed due to call from ReturnToManagedSpace
2008-03-05 09:52:00 -05:00
private static void TakeMutatorControlSlow(ref int statusWord,
int currentThreadIndex)
{
2008-11-17 18:29:00 -05:00
TakeMutatorControlSlow(ref statusWord, currentThreadIndex,
true, true);
2008-03-05 09:52:00 -05:00
}
[NoInline]
2008-11-17 18:29:00 -05:00
// [StackLinkCheck] Removed due to call from LeaveManagedSpace
2008-03-05 09:52:00 -05:00
private static void TakeMutatorControlSlowNoGC(ref int statusWord,
int currentThreadIndex)
{
2008-11-17 18:29:00 -05:00
TakeMutatorControlSlow(ref statusWord, currentThreadIndex,
false, true);
}
private static
void TakeInitialMutatorControlSlow(ref int statusWord,
int currentThreadIndex)
{
TakeMutatorControlSlow(ref statusWord, currentThreadIndex,
false, false);
}
private static void TakeMutatorControlSlow(ref int statusWord,
int currentThreadIndex,
bool allowGC,
bool preserveSignals)
{
bool consumedSignal = false;
2008-03-05 09:52:00 -05:00
while (true) {
if (SwitchToMutatorState(ref statusWord)) {
break;
}
if (SwitchToMutatorStateWithGCRequest(ref statusWord)) {
2008-11-17 18:29:00 -05:00
if (allowGC) {
Thread currentThread =
Thread.threadTable[currentThreadIndex];
if (currentThread != null) {
GC.InvokeCollection(currentThread);
}
}
2008-03-05 09:52:00 -05:00
break;
}
if (fUnderGCControl(statusWord)) {
Thread.WaitForGCEvent(currentThreadIndex);
2008-11-17 18:29:00 -05:00
consumedSignal = true;
2008-03-05 09:52:00 -05:00
}
}
2008-11-17 18:29:00 -05:00
if (consumedSignal && preserveSignals) {
Thread.SignalGCEvent(currentThreadIndex);
}
2008-03-05 09:52:00 -05:00
}
[Inline]
private static bool SwitchToMutatorState(ref int statusWord) {
VTable.Deny(fInMutatorState(statusWord),
"Thread is already under mutator control");
VTable.Assert(fInDormantState(statusWord));
int oldValue = statusWord & ~(GCRequest|GCControl);
int newValue = (oldValue|MutatorState) & ~DormantState;
return CompareAndSwap(ref statusWord, newValue, oldValue);
}
[Inline]
private static
bool SwitchToMutatorStateWithGCRequest(ref int statusWord)
{
int oldValue = ((statusWord|DormantState|GCRequest) & ~GCControl);
int newValue = (oldValue|MutatorState) & ~DormantState;
return CompareAndSwap(ref statusWord, newValue, oldValue);
}
[Inline]
private static bool TakeGCControl(ref int statusWord) {
int oldValue, newValue;
do {
oldValue = statusWord;
if (!fInDormantState(oldValue) ||
!fHasGCRequest(oldValue) ||
fUnderGCControl(oldValue)) {
return false;
}
newValue = oldValue|GCControl;
} while (!CompareAndSwap(ref statusWord, newValue, oldValue));
return true;
}
[Inline]
private static void ReleaseGCControl(ref int statusWord,
int threadIndex)
{
// There is only one possible transition out of this state.
int oldValue, newValue;
do {
oldValue = statusWord;
2008-11-17 18:29:00 -05:00
VTable.Assert(fInDormantState(oldValue));
VTable.Assert(fHasGCRequest(oldValue));
VTable.Assert(fUnderGCControl(oldValue));
newValue = (oldValue& ~(GCRequest|GCControl));
2008-03-05 09:52:00 -05:00
} while (!CompareAndSwap(ref statusWord, newValue, oldValue));
Thread.SignalGCEvent(threadIndex);
}
private static void MakeGCRequest(ref int statusWord,
int threadIndex)
{
#if SINGULARITY_KERNEL
if (Scheduler.IsIdleThread(threadIndex)) {
return;
}
#endif
int oldStatus, newStatus;
do {
oldStatus = statusWord;
newStatus = oldStatus|GCRequest;
} while (!CompareAndSwap(ref statusWord, newStatus, oldStatus));
}
private static void ClearGCRequest(ref int statusWord,
int threadIndex)
{
VTable.Assert(fHasGCRequest(statusWord));
VTable.Assert(fInMutatorState(statusWord));
int oldStatus, newStatus;
do {
oldStatus = statusWord;
newStatus = (oldStatus & ~GCRequest);
} while (!CompareAndSwap(ref statusWord, newStatus, oldStatus));
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
#endregion
#if SINGULARITY
[Inline]
private static unsafe
ThreadContext *GetCurrentThreadContext(int currentThreadIndex) {
VTable.Assert(GetThreadContext(currentThreadIndex) ==
Processor.GetCurrentThreadContext());
return Processor.GetCurrentThreadContext();
}
[Inline]
private static unsafe
ThreadContext *GetThreadContext(int threadIndex) {
Thread thread = Thread.threadTable[threadIndex];
if (thread == null) {
return null;
} else {
#if SINGULARITY_KERNEL
fixed (ThreadContext *result = &thread.context) {
return result;
}
#else
return thread.context;
#endif
}
}
#endif
#region Dependent (Methods depending on location of the status word)
#if SINGULARITY
2008-11-17 18:29:00 -05:00
[NoBarriers]
2008-03-05 09:52:00 -05:00
[PreInitRefCounts]
internal static void Initialize()
{
}
// To be used for callbacks into managed space
[RequiredByBartok]
[Inline]
internal static unsafe void EntryIntoManagedSpace() {
ThreadContext *currentThreadContext =
Processor.GetCurrentThreadContext();
EnsureMutatorControl(currentThreadContext);
}
// To be used for returning from a callback into managed space
[RequiredByBartok]
[Inline]
internal static unsafe void ReturnFromManagedSpace() {
ThreadContext *currentThreadContext =
Processor.GetCurrentThreadContext();
2008-11-17 18:29:00 -05:00
#if SINGULARITY_KERNEL
// In Singularity kernel this function is the exit point of a kernel ABI.
// If the thread is requested to be aborted, we stop it right here
currentThreadContext->thread.ProcessAbortIfRequested(AbortRequestSource.ABIExit);
#endif
2008-03-05 09:52:00 -05:00
TransferMutatorControl(currentThreadContext);
}
// To be used for returning from a callback into managed space
// from another managed space that doesn't want the automatic
// transition back to its mutator state.
[RequiredByBartok]
[Inline]
internal static unsafe void ReturnFromManagedSpaceNoCallerTransition()
{
ThreadContext *currentThreadContext =
Processor.GetCurrentThreadContext();
2008-11-17 18:29:00 -05:00
#if SINGULARITY_KERNEL
// In Singularity kernel this function is the exit point of a kernel ABI.
// If the thread is requested to be aborted, we stop it right here
currentThreadContext->thread.ProcessAbortIfRequested(AbortRequestSource.ABINoGCExit);
#endif
2008-03-05 09:52:00 -05:00
TakeDormantControl(currentThreadContext);
}
[Inline]
internal static unsafe bool InDormantState(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
return (threadContext == null ||
fInDormantState(threadContext->gcStates));
}
[Inline]
internal static unsafe bool InMutatorState(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
return InMutatorState(threadContext);
}
[Inline]
2008-11-17 18:29:00 -05:00
[NoHeapAllocation]
2008-03-05 09:52:00 -05:00
internal static unsafe bool InMutatorState(ThreadContext *threadContext)
{
return (threadContext != null &&
fInMutatorState(threadContext->gcStates));
}
[Inline]
internal static unsafe bool HasGCRequest(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
return (threadContext != null &&
fHasGCRequest(threadContext->gcStates));
}
[Inline]
internal static unsafe bool UnderGCControl(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
return (threadContext != null &&
fUnderGCControl(threadContext->gcStates));
}
[Inline]
internal static unsafe void TakeDormantControl(int threadIndex)
{
ThreadContext *threadContext = GetThreadContext(threadIndex);
TakeDormantControl(ref threadContext->gcStates, threadIndex);
}
[Inline]
internal static unsafe
void TakeDormantControl(ThreadContext *threadContext)
{
TakeDormantControl(ref threadContext->gcStates,
threadContext->threadIndex);
}
[Inline]
internal static unsafe
void TakeDormantControlNoGC(int currentThreadIndex)
{
ThreadContext *threadContext =
GetCurrentThreadContext(currentThreadIndex);
TakeDormantControlNoGC(ref threadContext->gcStates);
}
[Inline]
internal static unsafe
void TakeMutatorControl(int currentThreadIndex)
{
ThreadContext *threadContext =
GetCurrentThreadContext(currentThreadIndex);
TakeMutatorControl(threadContext);
}
[Inline]
internal static unsafe
void TakeMutatorControlNoGC(int currentThreadIndex)
{
ThreadContext *threadContext =
GetCurrentThreadContext(currentThreadIndex);
TakeMutatorControlNoGC(threadContext);
}
[Inline]
internal static unsafe
void TakeMutatorControl(ThreadContext *threadContext)
{
TakeMutatorControl(ref threadContext->gcStates,
threadContext->threadIndex);
}
[Inline]
internal static unsafe
void TakeMutatorControlNoGC(ThreadContext *threadContext)
{
TakeMutatorControlNoGC(ref threadContext->gcStates,
threadContext->threadIndex);
}
2008-11-17 18:29:00 -05:00
internal static unsafe
void TakeInitialMutatorControl(ThreadContext *threadContext)
{
TakeInitialMutatorControl(ref threadContext->gcStates,
threadContext->threadIndex);
}
2008-03-05 09:52:00 -05:00
[Inline]
internal static unsafe
void TransferMutatorControl(ThreadContext *currentThreadContext)
{
TransferMutatorControl(ref currentThreadContext->gcStates,
currentThreadContext->threadIndex);
}
[Inline]
internal static unsafe
void EnsureMutatorControl(ThreadContext *currentThreadContext)
{
EnsureMutatorControl(ref currentThreadContext->gcStates,
currentThreadContext->threadIndex);
}
[Inline]
internal static unsafe
void EnsureMutatorControlNoGC(ThreadContext *currentThreadContext)
{
EnsureMutatorControlNoGC(ref currentThreadContext->gcStates,
currentThreadContext->threadIndex);
}
[Inline]
internal static unsafe
void EnsureDormantControl(int currentThreadIndex) {
ThreadContext *threadContext =
GetCurrentThreadContext(currentThreadIndex);
if (!fInDormantState(threadContext->gcStates)) {
TakeDormantControlNoGC(ref threadContext->gcStates);
}
}
[Inline]
internal static unsafe bool TakeGCControl(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
return (threadContext != null &&
TakeGCControl(ref threadContext->gcStates));
}
[Inline]
internal static unsafe void ReleaseGCControl(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
2008-11-17 18:29:00 -05:00
if (threadContext != null) {
ReleaseGCControl(ref threadContext->gcStates, threadIndex);
}
2008-03-05 09:52:00 -05:00
}
[Inline]
internal static unsafe void MakeGCRequest(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
if (threadContext != null) {
MakeGCRequest(ref threadContext->gcStates, threadIndex);
}
}
[Inline]
internal static unsafe void ClearGCRequest(int threadIndex) {
ThreadContext *threadContext = GetThreadContext(threadIndex);
if (threadContext != null) {
ClearGCRequest(ref threadContext->gcStates, threadIndex);
}
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
#else
private static int[] gcReadyTable;
2008-11-17 18:29:00 -05:00
[NoBarriers]
2008-03-05 09:52:00 -05:00
[PreInitRefCounts]
internal static void Initialize()
{
// gcReadyTable = new int[Thread.maxThreads];
gcReadyTable = (int[])
GCs.BootstrapMemory.Allocate(typeof(int[]), Thread.maxThreads);
for (int i = 0; i < gcReadyTable.Length; i++) {
gcReadyTable[i] = DormantState;
}
}
// To be used for callbacks into managed space
[RequiredByBartok]
[Inline]
internal static void EntryIntoManagedSpace() {
int currentThreadIndex = Thread.GetCurrentThreadIndex();
TakeMutatorControl(currentThreadIndex);
}
// To be used for returning from a callback into managed space
[RequiredByBartok]
[Inline]
internal static void ReturnFromManagedSpace() {
TakeDormantControl(Thread.GetCurrentThreadIndex());
}
[RequiredByBartok]
[Inline]
internal static void ReturnFromManagedSpaceNoCallerTransition() {
TakeDormantControl(Thread.GetCurrentThreadIndex());
}
[Inline]
internal static bool InDormantState(int threadIndex) {
return fInDormantState(gcReadyTable[threadIndex]);
}
[Inline]
internal static bool InMutatorState(int threadIndex) {
return fInMutatorState(gcReadyTable[threadIndex]);
}
[Inline]
internal static bool HasGCRequest(int threadIndex) {
return fHasGCRequest(gcReadyTable[threadIndex]);
}
[Inline]
internal static bool UnderGCControl(int threadIndex) {
return fUnderGCControl(gcReadyTable[threadIndex]);
}
[Inline]
internal static void TakeDormantControl(int currentThreadIndex) {
TakeDormantControl(ref gcReadyTable[currentThreadIndex],
currentThreadIndex);
}
[Inline]
internal static void TakeDormantControlNoGC(int currentThreadIndex) {
TakeDormantControlNoGC(ref gcReadyTable[currentThreadIndex]);
}
[Inline]
internal static void TakeMutatorControl(int currentThreadIndex) {
TakeMutatorControl(ref gcReadyTable[currentThreadIndex],
currentThreadIndex);
}
[Inline]
internal static void TakeMutatorControlNoGC(int currentThreadIndex) {
TakeMutatorControlNoGC(ref gcReadyTable[currentThreadIndex],
currentThreadIndex);
}
2008-11-17 18:29:00 -05:00
internal static void TakeInitialMutatorControl(int currentThreadIndex)
{
TakeInitialMutatorControl(ref gcReadyTable[currentThreadIndex],
currentThreadIndex);
}
2008-03-05 09:52:00 -05:00
[Inline]
internal static bool TakeGCControl(int threadIndex) {
return TakeGCControl(ref gcReadyTable[threadIndex]);
}
[Inline]
internal static void ReleaseGCControl(int threadIndex) {
ReleaseGCControl(ref gcReadyTable[threadIndex], threadIndex);
}
[Inline]
internal static void MakeGCRequest(int threadIndex) {
MakeGCRequest(ref gcReadyTable[threadIndex], threadIndex);
}
[Inline]
internal static void ClearGCRequest(int threadIndex) {
ClearGCRequest(ref gcReadyTable[threadIndex], threadIndex);
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
#endif
#endregion
}
}