- Add ASSERT_APC definition.

- Fix KeRemoveQueueApc comment header and clean up function.
- Acquire dispatcher lock at DPC level during ApcListEntry read/write.

svn path=/trunk/; revision=24053
This commit is contained in:
Alex Ionescu 2006-09-11 01:45:11 +00:00
parent 4b35027c0f
commit 43a412db60
2 changed files with 34 additions and 21 deletions

View file

@ -1085,9 +1085,12 @@ typedef struct _KLOCK_QUEUE_HANDLE {
#define DPC_NORMAL 0 #define DPC_NORMAL 0
#define DPC_THREADED 1 #define DPC_THREADED 1
#define ASSERT_DPC(Object) \ #define ASSERT_APC(Object) \
ASSERT(((Object)->Type == 0) || \ ASSERT((Object)->Type == ApcObject)
((Object)->Type == DpcObject) || \
#define ASSERT_DPC(Object) \
ASSERT(((Object)->Type == 0) || \
((Object)->Type == DpcObject) || \
((Object)->Type == ThreadedDpcObject)) ((Object)->Type == ThreadedDpcObject))
typedef struct _KDPC typedef struct _KDPC

View 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 * The KeRemoveQueueApc routine removes a given APC object from the system
* APC queue. * APC queue.
* *
* Params: * @params Apc
* APC - Pointer to an initialized APC object that was queued by calling * Pointer to an initialized APC object that was queued by calling
* KeInsertQueueApc. * KeInsertQueueApc.
* *
* Returns: * @return TRUE if the APC Object is in the APC Queue. Otherwise, no operation
* TRUE if the APC Object is in the APC Queue. If it isn't, no operation is * is performed and FALSE is returned.
* performed and FALSE is returned.
* *
* Remarks: * @remarks If the given APC Object is currently queued, it is removed from the
* If the given APC Object is currently queued, it is removed from the queue * queue and any calls to the registered routines are cancelled.
* 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 BOOLEAN
STDCALL NTAPI
KeRemoveQueueApc(PKAPC Apc) KeRemoveQueueApc(IN PKAPC Apc)
{ {
PKTHREAD Thread = Apc->Thread; PKTHREAD Thread = Apc->Thread;
PKAPC_STATE ApcState; PKAPC_STATE ApcState;
BOOLEAN Inserted; BOOLEAN Inserted;
KLOCK_QUEUE_HANDLE ApcLock; KLOCK_QUEUE_HANDLE ApcLock;
ASSERT_APC(Apc);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Get the APC lock */ /* Get the APC lock */
KiAcquireApcLock(Thread, &ApcLock); KiAcquireApcLock(Thread, &ApcLock);
/* Check if it's inserted */ /* 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; 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); RemoveEntryList(&Apc->ApcListEntry);
/* If the Queue is completely empty, then no more APCs are pending */ /* 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) if (Apc->ApcMode == KernelMode)
{ {
/* No more pending kernel APCs */
ApcState->KernelApcPending = FALSE; ApcState->KernelApcPending = FALSE;
} }
else else
{ {
/* No more pending user APCs */
ApcState->UserApcPending = FALSE; ApcState->UserApcPending = FALSE;
} }
} }
/* Release dispatcher lock */
KiReleaseDispatcherLockFromDpcLevel();
} }
/* Release the lock and return */ /* Release the lock and return */