- May 7, 2013
- 10,400
This is going to be a short post since there isn't too much which can be said about this bugcheck. I'm going to assume that you're familiar with DPC objects, but if you're not, then I would strongly suggest reading about them.
As many of you are probably aware, the thread scheduler is disabled at IRQL Level 2 (DISPATCH_LEVEL), the level in which DPCs are running on a given processor, therefore it is fairly obvious why it would be an illegal operation to attempt a context switch to a different thread. It’s simply impossible.
The first thing to do is to dump the call stack of the offending thread. In most circumstances, WinDbg will have switched to the appropriate thread context for you.
As we can clearly see, a thread switch was being attempted by the responsible thread. It is actually the nt!SwapContext function which is responsible for raising the bugcheck by checking if a DPC routine is currently executing. The function will check the DpcRoutineActive field of the KPRCB structure, if set to true, then the bugcheck is thrown as shown above.
The currently active DPC can be found by dumping the DpcData field of the KPRCB structure mentioned earlier.
This field is an array of _KDPC_DATA structures. These two elements point to normal and threaded DPCs. The first element is used for normal and the second element is used for threaded.
The ActiveDpc field points to the currently active DPC on the given processor. Remember all DPC objects are represented by the _KDPC structure which is allocated from non-paged pool. Unfortunately, since this was a Minidump, then the information wasn’t able to be parsed correctly from the dump file. However, I hope this post has provided some insight into why this bugcheck is caused and what can be done to debug it.
References:
Windows Internals - A look into SwapContext routine
KDPC_DATA
As many of you are probably aware, the thread scheduler is disabled at IRQL Level 2 (DISPATCH_LEVEL), the level in which DPCs are running on a given processor, therefore it is fairly obvious why it would be an illegal operation to attempt a context switch to a different thread. It’s simply impossible.
Rich (BB code):
ATTEMPTED_SWITCH_FROM_DPC (b8)
A wait operation, attach process, or yield was attempted from a DPC routine.
This is an illegal operation and the stack track will lead to the offending
code and original DPC routine.
Arguments:
Arg1: ffffd3802c9f2540, Original thread which is the cause of the failure
Arg2: ffff8c870e252100, New thread
Arg3: 0000000000000000, Stack address of the original thread
Arg4: 0000000000000000
The first thing to do is to dump the call stack of the offending thread. In most circumstances, WinDbg will have switched to the appropriate thread context for you.
Rich (BB code):
17: kd> knL
# Child-SP RetAddr Call Site
00 ffff8083`d4c47598 fffff801`18ffe492 nt!KeBugCheckEx
01 ffff8083`d4c475a0 fffff801`18ffdca6 nt!SwapContext+0x512 << Raise bugcheck
02 ffff8083`d4c475e0 fffff801`18e0c970 nt!KiSwapContext+0x76
03 ffff8083`d4c47720 fffff801`18e0be9f nt!KiSwapThread+0x500 << Crash here!
04 ffff8083`d4c477d0 fffff801`18e0b743 nt!KiCommitThreadWait+0x14f
05 ffff8083`d4c47870 fffff801`191f7551 nt!KeWaitForSingleObject+0x233
06 ffff8083`d4c47960 fffff801`191f75fa nt!ObWaitForSingleObject+0x91
07 ffff8083`d4c479c0 fffff801`190088b5 nt!NtWaitForSingleObject+0x6a
08 ffff8083`d4c47a00 00000000`76fd1cfc nt!KiSystemServiceCopyEnd+0x25
09 00000000`0c69ef38 00000000`00000000 0x76fd1cfc
As we can clearly see, a thread switch was being attempted by the responsible thread. It is actually the nt!SwapContext function which is responsible for raising the bugcheck by checking if a DPC routine is currently executing. The function will check the DpcRoutineActive field of the KPRCB structure, if set to true, then the bugcheck is thrown as shown above.
Rich (BB code):
17: kd> !prcb
PRCB for Processor 17 at fffff780ffff0000:
Current IRQL -- 2
Threads-- Current ffff8c870e252100 Next 0000000000000000 Idle ffffd3802c9f2540
Processor Index 17 Number (0, 17) GroupSetMember 20000
Interrupt Count -- 10587878
Times -- Dpc 0002b8bd Interrupt 00052847
Kernel 0078a87d User 00037ef4
Rich (BB code):
17: kd> dt _KPRCB fffff780ffff0000 -y DpcRoutineActive
nt!_KPRCB
+0x312a DpcRoutineActive : 0x1 ''
The currently active DPC can be found by dumping the DpcData field of the KPRCB structure mentioned earlier.
Rich (BB code):
17: kd> dt _KPRCB -y DpcData
nt!_KPRCB
+0x30c0 DpcData : [2] _KDPC_DATA
This field is an array of _KDPC_DATA structures. These two elements point to normal and threaded DPCs. The first element is used for normal and the second element is used for threaded.
Rich (BB code):
17: kd> dt _KDPC_DATA
nt!_KDPC_DATA
+0x000 DpcList : _KDPC_LIST
+0x010 DpcLock : Uint8B
+0x018 DpcQueueDepth : Int4B
+0x01c DpcCount : Uint4B
+0x020 ActiveDpc : Ptr64 _KDPC
The ActiveDpc field points to the currently active DPC on the given processor. Remember all DPC objects are represented by the _KDPC structure which is allocated from non-paged pool. Unfortunately, since this was a Minidump, then the information wasn’t able to be parsed correctly from the dump file. However, I hope this post has provided some insight into why this bugcheck is caused and what can be done to debug it.
References:
Windows Internals - A look into SwapContext routine
KDPC_DATA