KCONTINUE_STATUS KeSwitchFrozenProcessor ( IN ULONG ProcessorNumber ) { #if !defined(NT_UP) PKPRCB TargetPrcb, CurrentPrcb; // // If Processor number is out of range, reselect current processor // if (ProcessorNumber >= (ULONG) KeNumberProcessors) { return ContinueProcessorReselected; } TargetPrcb = KiProcessorBlock[ProcessorNumber]; CurrentPrcb = KeGetCurrentPrcb(); // // Move active flag to correct processor. // CurrentPrcb->IpiFrozen &= ~FREEZE_ACTIVE; TargetPrcb->IpiFrozen |= FREEZE_ACTIVE; // // If this processor is frozen in KiFreezeTargetExecution, return to it // if (FrozenState(CurrentPrcb->IpiFrozen) == TARGET_FROZEN) { return ContinueNextProcessor; } // // This processor must be FREEZE_OWNER, wait to be reselected as the // active processor // if (FrozenState(CurrentPrcb->IpiFrozen) != FREEZE_OWNER) { return ContinueError; } while (!(CurrentPrcb->IpiFrozen & FREEZE_ACTIVE)) { KeYieldProcessor(); } #endif // !defined(NT_UP) // // Reselect this processor // return ContinueProcessorReselected; }
void CAltStatesController::onTick(unsigned int msecs) { for (int i = 0; i < _vecAltStates.size(); ++i) { if (_vecAltStates.at(i).name == "Poison") PoisonState(_vecAltStates.at(i), msecs); else if (_vecAltStates.at(i).name == "Canibal") CanibalState(_vecAltStates.at(i), msecs); else if (_vecAltStates.at(i).name == "Slowdown") SlowdownState(_vecAltStates.at(i), msecs); else if (_vecAltStates.at(i).name == "Frozen") FrozenState(_vecAltStates.at(i), msecs); } }
BOOLEAN KeFreezeExecution ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function freezes the execution of all other processors in the host configuration and then returns to the caller. Arguments: TrapFrame - Supplies a pointer to a trap frame that describes the trap. ExceptionFrame - Supplies a pointer to an exception frame that describes the trap. Return Value: Previous interrupt enable. --*/ { BOOLEAN Enable; #if !defined(NT_UP) BOOLEAN Flag; PKPRCB Prcb; ULONG TargetSet; ULONG BitNumber; KIRQL OldIrql; #if IDBG ULONG Count = 30000; #endif #endif // // Disable interrupts. // Enable = KiDisableInterrupts(); KiFreezeFlag = FREEZE_FROZEN; #if !defined(NT_UP) // // Raise IRQL to HIGH_LEVEL. // KeRaiseIrql(HIGH_LEVEL, &OldIrql); if (FrozenState(KeGetCurrentPrcb()->IpiFrozen) == FREEZE_OWNER) { // // This processor already owns the freeze lock. // Return without trying to re-acquire lock or without // trying to IPI the other processors again // return Enable; } // // Try to acquire the KiFreezeExecutionLock before sending the request. // To prevent deadlock from occurring, we need to accept and process // incoming FreexeExecution requests while we are waiting to acquire // the FreezeExecutionFlag. // while (KiTryToAcquireSpinLock (&KiFreezeExecutionLock) == FALSE) { // // FreezeExecutionLock is busy. Another processor may be trying // to IPI us - go service any IPI. // KiRestoreInterrupts(Enable); Flag = KiIpiServiceRoutine((PVOID)TrapFrame, (PVOID)ExceptionFrame); KiDisableInterrupts(); #if IDBG if (Flag != FALSE) { Count = 30000; continue; } KeStallExecutionProcessor (100); if (!Count--) { Count = 30000; if (KiTryToAcquireSpinLock (&KiFreezeLockBackup) == TRUE) { KiFreezeFlag |= FREEZE_BACKUP; break; } } #endif } // // After acquiring the lock flag, we send Freeze request to each processor // in the system (other than us) and wait for it to become frozen. // Prcb = KeGetCurrentPrcb(); // Do this after spinlock is acquired. TargetSet = KeActiveProcessors & ~(1 << Prcb->Number); if (TargetSet) { #if IDBG Count = 400; #endif KiFreezeOwner = Prcb; Prcb->IpiFrozen = FREEZE_OWNER | FREEZE_ACTIVE; Prcb->SkipTick = TRUE; KiIpiSend((KAFFINITY) TargetSet, IPI_FREEZE); while (TargetSet != 0) { BitNumber = KeFindFirstSetRightMember(TargetSet); ClearMember(BitNumber, TargetSet); Prcb = KiProcessorBlock[BitNumber]; #if IDBG while (Prcb->IpiFrozen != TARGET_FROZEN) { if (Count == 0) { KiFreezeFlag |= FREEZE_SKIPPED_PROCESSOR; break; } KeStallExecutionProcessor (10000); Count--; } #else while (Prcb->IpiFrozen != TARGET_FROZEN) { KeYieldProcessor(); } #endif } } // // Save the old IRQL and return whether interrupts were previous enabled. // KiOldIrql = OldIrql; #endif // !defined(NT_UP) return Enable; }
VOID KeThawExecution ( IN BOOLEAN Enable ) /*++ Routine Description: This function thaws the execution of all other processors in the host configuration and then returns to the caller. It is intended for use by the kernel debugger. Arguments: Enable - Supplies the previous interrupt enable that is to be restored after having thawed the execution of all other processors. Return Value: None. --*/ { #if !defined(NT_UP) KIRQL OldIrql; ULONG TargetSet; ULONG BitNumber; ULONG Flag; PKPRCB Prcb; // // Before releasing FreezeExecutionLock clear any all targets IpiFrozen // flag. // KeGetCurrentPrcb()->IpiFrozen = RUNNING; TargetSet = KeActiveProcessors & ~(1 << KeGetCurrentPrcb()->Number); while (TargetSet != 0) { BitNumber = KeFindFirstSetRightMember(TargetSet); ClearMember(BitNumber, TargetSet); Prcb = KiProcessorBlock[BitNumber]; #if IDBG // // If the target processor was not forzen, then don't wait // for target to unfreeze. // if (FrozenState(Prcb->IpiFrozen) != TARGET_FROZEN) { Prcb->IpiFrozen = RUNNING; continue; } #endif Prcb->IpiFrozen = TARGET_THAW; while (Prcb->IpiFrozen == TARGET_THAW) { KeYieldProcessor(); } } // // Capture the previous IRQL before releasing the freeze lock. // OldIrql = KiOldIrql; #if IDBG Flag = KiFreezeFlag; KiFreezeFlag = 0; if ((Flag & FREEZE_BACKUP) != 0) { KiReleaseSpinLock(&KiFreezeLockBackup); } else { KiReleaseSpinLock(&KiFreezeExecutionLock); } #else KiFreezeFlag = 0; KiReleaseSpinLock(&KiFreezeExecutionLock); #endif #endif // !defined (NT_UP) // // Flush the current TB, instruction cache, and data cache. // KeFlushCurrentTb(); KeSweepCurrentIcache(); KeSweepCurrentDcache(); // // Lower IRQL and restore interrupt enable // #if !defined(NT_UP) KeLowerIrql(OldIrql); #endif KiRestoreInterrupts(Enable); return; }
VOID KiFreezeTargetExecution ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function freezes the execution of the current running processor. If a trapframe is supplied to current state is saved into the prcb for the debugger. Arguments: TrapFrame - Supplies a pointer to the trap frame that describes the trap. ExceptionFrame - Supplies a pointer to the exception frame that describes the trap. Return Value: None. --*/ { #if !defined(NT_UP) KIRQL OldIrql; PKPRCB Prcb; BOOLEAN Enable; KCONTINUE_STATUS Status; EXCEPTION_RECORD ExceptionRecord; Enable = KiDisableInterrupts(); KeRaiseIrql(HIGH_LEVEL, &OldIrql); Prcb = KeGetCurrentPrcb(); Prcb->IpiFrozen = TARGET_FROZEN; Prcb->SkipTick = TRUE; if (TrapFrame != NULL) { KiSaveProcessorState(TrapFrame, ExceptionFrame); } // // Sweep the data cache in case this is a system crash and the bug // check code is attempting to write a crash dump file. // KeSweepCurrentDcache(); // // Wait for person requesting us to freeze to // clear our frozen flag // while (FrozenState(Prcb->IpiFrozen) == TARGET_FROZEN) { if (Prcb->IpiFrozen & FREEZE_ACTIVE) { // // This processor has been made the active processor // if (TrapFrame) { RtlZeroMemory (&ExceptionRecord, sizeof ExceptionRecord); ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER; ExceptionRecord.ExceptionRecord = &ExceptionRecord; ExceptionRecord.ExceptionAddress = (PVOID)CONTEXT_TO_PROGRAM_COUNTER (&Prcb->ProcessorState.ContextFrame); Status = (KiDebugSwitchRoutine) ( &ExceptionRecord, &Prcb->ProcessorState.ContextFrame, FALSE ); } else { Status = ContinueError; } // // If status is anything other then, continue with next // processor then reselect master // if (Status != ContinueNextProcessor) { Prcb->IpiFrozen &= ~FREEZE_ACTIVE; KiFreezeOwner->IpiFrozen |= FREEZE_ACTIVE; } } KeYieldProcessor(); } if (TrapFrame != NULL) { KiRestoreProcessorState(TrapFrame, ExceptionFrame); } Prcb->IpiFrozen = RUNNING; KeFlushCurrentTb(); KeSweepCurrentIcache(); KeLowerIrql(OldIrql); KiRestoreInterrupts(Enable); #endif // !define(NT_UP) return; }