internal static UIntPtr GetSipStackSegment(UIntPtr size) { UIntPtr stack; // @TODO: Historically we have disabled interrupts around stack growth. // Actually I think it is unnecessary; however to be conservative for // now we will disable interrupts while we use the interrupt stack. bool en = Processor.DisableInterrupts(); try { unsafe { // Sanity check: we allocate from the current stack segment, and // will set the thread context to point to a new stack segment VTable.Assert(Isa.GetStackPointer() <= Processor.GetCurrentThreadContext()->stackBegin); VTable.Assert(Isa.GetStackPointer() >= Processor.GetCurrentThreadContext()->stackLimit); } stack = Isa.CallbackOnInterruptStack(getSipStackCallback, size); } finally { Processor.RestoreInterrupts(en); } return(stack); }
internal static UIntPtr GetKernelStackSegment(UIntPtr size) { UIntPtr stack; // @TODO: see note about disabling interrupts above. bool en = Processor.DisableInterrupts(); try { unsafe { // Sanity check: we allocate from the current stack segment, and // will set the thread context to point to a new stack segment VTable.Assert(Isa.GetStackPointer() <= Processor.GetCurrentThreadContext()->stackBegin); VTable.Assert(Isa.GetStackPointer() >= Processor.GetCurrentThreadContext()->stackLimit); } stack = Isa.CallbackOnInterruptStack(getKernelStackCallback, size); } finally { Processor.RestoreInterrupts(en); } return(stack); }
internal static void ReturnKernelStackSegment() { // @TODO: see note about disabling interrupts above. bool en = Processor.DisableInterrupts(); try { Isa.CallbackOnInterruptStack(returnKernelStackCallback, 0); unsafe { // Sanity check: we freed from the previous segment, and // should have set the thread context to point to this segment now. VTable.Assert(Isa.GetStackPointer() <= Processor.GetCurrentThreadContext()->stackBegin); VTable.Assert(Isa.GetStackPointer() >= Processor.GetCurrentThreadContext()->stackLimit); } } finally { Processor.RestoreInterrupts(en); } }
internal static unsafe void SwitchToThreadContextNoGC(ref ThreadContext newContext) { // Interrupts should be disabled at this point VTable.Assert(Processor.InterruptsDisabled()); // Save appears to returns twice: once with true on this thread after // the save, and once with false when the context is restored. if (GetCurrentThreadContext()->threadRecord.spill.Save()) { // Initial return from save; time to swap in the new context. // Must do this on the interrupt stack, since once we release the // dispatch lock the saved context is free to run (and we would // be on the same stack.) fixed(ThreadContext *c = &newContext) { // Note that this does not return. Isa.CallbackOnInterruptStack(resumeThreadCallback, (UIntPtr)c); } } // Saved context will resume here }