- Add ASSERT_APC definition.
authorAlex Ionescu <aionescu@gmail.com>
Mon, 11 Sep 2006 01:45:11 +0000 (01:45 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 11 Sep 2006 01:45:11 +0000 (01:45 +0000)
- Fix KeRemoveQueueApc comment header and clean up function.
- Acquire dispatcher lock at DPC level during ApcListEntry read/write.

svn path=/trunk/; revision=24053

reactos/include/ddk/winddk.h
reactos/ntoskrnl/ke/apc.c

index e9695a6..3e43a60 100644 (file)
@@ -1085,9 +1085,12 @@ typedef struct _KLOCK_QUEUE_HANDLE {
 #define DPC_NORMAL 0
 #define DPC_THREADED 1
 
-#define ASSERT_DPC(Object)                                                   \
-    ASSERT(((Object)->Type == 0) ||                                          \
-           ((Object)->Type == DpcObject) ||                                  \
+#define ASSERT_APC(Object) \
+    ASSERT((Object)->Type == ApcObject)
+
+#define ASSERT_DPC(Object) \
+    ASSERT(((Object)->Type == 0) || \
+           ((Object)->Type == DpcObject) || \
            ((Object)->Type == ThreadedDpcObject))
 
 typedef struct _KDPC
index 86419bd..bd48f21 100644 (file)
@@ -774,59 +774,69 @@ KeFlushQueueApc(IN PKTHREAD Thread,
 }
 
 /*++
- * KeRemoveQueueApc
+ * @name KeRemoveQueueApc
+ * @implemented NT4
  *
  *     The KeRemoveQueueApc routine removes a given APC object from the system
  *     APC queue.
  *
- * Params:
- *     APC - Pointer to an initialized APC object that was queued by calling
- *           KeInsertQueueApc.
+ * @params Apc
+ *         Pointer to an initialized APC object that was queued by calling
+ *         KeInsertQueueApc.
  *
- * Returns:
- *     TRUE if the APC Object is in the APC Queue. If it isn't, no operation is
- *     performed and FALSE is returned.
+ * @return TRUE if the APC Object is in the APC Queue. Otherwise, no operation
+ *         is performed and FALSE is returned.
  *
- * Remarks:
- *     If the given APC Object is currently queued, it is removed from the queue
- *     and any calls to the registered routines are cancelled.
+ * @remarks If the given APC Object is currently queued, it is removed from the
+ *          queue and any calls to the registered routines are cancelled.
  *
- *     Callers of KeLeaveCriticalRegion can be running at any IRQL.
+ *          Callers of this routine must be running at IRQL <= DISPATCH_LEVEL.
  *
  *--*/
 BOOLEAN
-STDCALL
-KeRemoveQueueApc(PKAPC Apc)
+NTAPI
+KeRemoveQueueApc(IN PKAPC Apc)
 {
     PKTHREAD Thread = Apc->Thread;
     PKAPC_STATE ApcState;
     BOOLEAN Inserted;
     KLOCK_QUEUE_HANDLE ApcLock;
+    ASSERT_APC(Apc);
+    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
 
     /* Get the APC lock */
     KiAcquireApcLock(Thread, &ApcLock);
 
     /* Check if it's inserted */
-    if ((Inserted = Apc->Inserted))
+    Inserted = Apc->Inserted;
+    if (Inserted)
     {
-        /* Remove it from the Queue*/
+        /* Set it as non-inserted and get the APC state */
         Apc->Inserted = FALSE;
-        ApcState = Thread->ApcStatePointer[(int)Apc->ApcStateIndex];
+        ApcState = Thread->ApcStatePointer[(SCHAR)Apc->ApcStateIndex];
+
+        /* Acquire the dispatcher lock and remove it from the list */
+        KiAcquireDispatcherLockAtDpcLevel();
         RemoveEntryList(&Apc->ApcListEntry);
 
         /* If the Queue is completely empty, then no more APCs are pending */
-        if (IsListEmpty(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode]))
+        if (IsListEmpty(&ApcState->ApcListHead[Apc->ApcMode]))
         {
-            /* Set the correct State based on the Apc Mode */
+            /* Set the correct state based on the APC Mode */
             if (Apc->ApcMode == KernelMode)
             {
+                /* No more pending kernel APCs */
                 ApcState->KernelApcPending = FALSE;
             }
             else
             {
+                /* No more pending user APCs */
                 ApcState->UserApcPending = FALSE;
             }
         }
+
+        /* Release dispatcher lock */
+        KiReleaseDispatcherLockFromDpcLevel();
     }
 
     /* Release the lock and return */