https://git.reactos.org/?p=reactos.git;a=commitdiff;h=85f42a25d5bcda5ce1720e247b5907d372f0c042

commit 85f42a25d5bcda5ce1720e247b5907d372f0c042
Author:     Timo Kreuzer <timo.kreu...@reactos.org>
AuthorDate: Fri Dec 13 12:59:28 2024 +0200
Commit:     Timo Kreuzer <timo.kreu...@reactos.org>
CommitDate: Wed Jan 22 14:04:18 2025 +0200

    [NTOS:KE/x64] Improve freeze code
    
    - Set ACTIVE flag on freeze owner like on Windows
    - Add a nice state graph
    - Change license to MIT
---
 ntoskrnl/ke/amd64/freeze.c | 41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/ntoskrnl/ke/amd64/freeze.c b/ntoskrnl/ke/amd64/freeze.c
index 5cf53f3f27f..5e655d32939 100644
--- a/ntoskrnl/ke/amd64/freeze.c
+++ b/ntoskrnl/ke/amd64/freeze.c
@@ -1,8 +1,30 @@
 /*
  * PROJECT:     ReactOS Kernel
- * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
  * PURPOSE:     Processor freeze support for x64
- * COPYRIGHT:   Copyright 2023 Timo Kreuzer <timo.kreu...@reactos.org>
+ * COPYRIGHT:   Copyright 2023-2024 Timo Kreuzer <timo.kreu...@reactos.org>
+ */
+
+/*
+
+ IpiFrozen state graph (based on Windows behavior):
+
+    +-----------------+     Freeze request      +-----------------+
+    | RUNNING         |------------------------>| TARGET_FREEZE   |
+    +-----------------+<---------               +-----------------+
+            |^                  | Resume                |
+     Freeze || Thaw        +-----------+ Thaw request   | Freeze IPI
+            v|             | THAW      |<-----------\   v
+    +-----------------+    +-----------+        +-----------------+
+    | OWNER + ACTIVE  |         ^               | FROZEN          |
+    +-----------------+         |               +-----------------+
+            ^                   |                       ^
+            | Kd proc switch    |                       | Kd proc switch
+            v                   |                       v
+    +-----------------+         |               +-----------------+
+    | OWNER           |---------+               | FROZEN + ACTIVE |
+    +-----------------+ Thaw request            +-----------------+
+
  */
 
 /* INCLUDES 
*******************************************************************/
@@ -98,8 +120,8 @@ KxFreezeExecution(
         }
     }
 
-    /* We are the owner now */
-    CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
+    /* We are the owner now and active */
+    CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER | IPI_FROZEN_FLAG_ACTIVE;
 
     /* Loop all processors */
     for (ULONG i = 0; i < KeNumberProcessors; i++)
@@ -107,7 +129,7 @@ KxFreezeExecution(
         PKPRCB TargetPrcb = KiProcessorBlock[i];
         if (TargetPrcb != CurrentPrcb)
         {
-            /* Nobody else is allowed to change IpiFrozen, except the freeze 
owner */
+            /* Only the active processor is allowed to change IpiFrozen */
             ASSERT(TargetPrcb->IpiFrozen == IPI_FROZEN_STATE_RUNNING);
 
             /* Request target to freeze */
@@ -142,6 +164,7 @@ KxThawExecution(
     VOID)
 {
     PKPRCB CurrentPrcb = KeGetCurrentPrcb();
+    ASSERT(CurrentPrcb->IpiFrozen & IPI_FROZEN_FLAG_ACTIVE);
 
     /* Loop all processors */
     for (ULONG i = 0; i < KeNumberProcessors; i++)
@@ -190,6 +213,10 @@ KxSwitchKdProcessor(
     /* Make sure that the processor index is valid */
     ASSERT(ProcessorIndex < KeNumberProcessors);
 
+    /* We are no longer active */
+    ASSERT(CurrentPrcb->IpiFrozen & IPI_FROZEN_FLAG_ACTIVE);
+    CurrentPrcb->IpiFrozen &= ~IPI_FROZEN_FLAG_ACTIVE;
+
     /* Inform the target processor that it's his turn now */
     TargetPrcb = KiProcessorBlock[ProcessorIndex];
     TargetPrcb->IpiFrozen |= IPI_FROZEN_FLAG_ACTIVE;
@@ -212,12 +239,12 @@ KxSwitchKdProcessor(
     {
         /* Another CPU has completed, we can leave the debugger now */
         KdpDprintf("[%u] KxSwitchKdProcessor: ContinueSuccess\n", 
KeGetCurrentProcessorNumber());
-        CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
+        CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER | 
IPI_FROZEN_FLAG_ACTIVE;
         return ContinueSuccess;
     }
 
     /* We have been reselected, return to Kd to continue in the debugger */
-    CurrentPrcb->IpiFrozen = IPI_FROZEN_STATE_OWNER;
+    ASSERT(CurrentPrcb->IpiFrozen == (IPI_FROZEN_STATE_OWNER | 
IPI_FROZEN_FLAG_ACTIVE));
 
     return ContinueProcessorReselected;
 }

Reply via email to