Re: Event handling mechanism in Windows

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Feb 26, 1:48 pm, "Ivan Brugiolo [MSFT]"
<ivanb...@xxxxxxxxxxxxxxxxxxxx> wrote:
       Q-1) How does the kenel knows which thread's
     APC to queue this APC request to?

The IRP that originated the request `points back` to the requestor thread.

       Q-2) Will it be a user mode APC or a kernel mode APC?

It depends which mode the thread was/is executing

       Q-3) I assume that APC queue and Message queue are different.

Yes, they are.

8) The APC is delivered when the thread gets into an "alertable wait"

Here is an example:

This is the RIT (Raw input thread)

1: kd> .thread 85a37030
Implicit thread is now 85a37030
1: kd> kb
  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr  Args to Child
87fe1c40 818a0fee 85a37030 00000000 85a370c0 nt!KiSwapContext+0x26
87fe1c84 8189d707 85a37030 00000001 81888370 nt!KiSwapThread+0x481
87fe1cd8 9083e5be 00000004 85a0ea90 00000001
nt!KeWaitForMultipleObjects+0x568
87fe1d34 9083ebdc 00000001 00000002 89628450 win32k!RawInputThread+0x505
87fe1d48 9090ad0c 00000004 00bdf924 87fe1d64
win32k!xxxCreateSystemThreads+0x4a
87fe1d58 8188a55a 00000004 00bdf964 76e31584 win32k!NtUserCallNoParam+0x1b
87fe1d58 76e31584 00000004 00bdf964 76e31584 nt!KiFastCallEntry+0x12a
00bdf964 00000000 00000000 00000000 00000000 ntdll!KiFastSystemCallRet

You can clearly see that it is in alertable wait state.
The thread has pended an IRP request to the (HID)Keyboard-class driver.

1: kd> .frame 2
02 87fe1cd8 9083e5be nt!KeWaitForMultipleObjects+0x568
1: kd> dv /V
87fe1ce0 @ebp+0x08           Count = 4
87fe1ce4 @ebp+0x0c          Object = 0x85a0ea90
87fe1ce8 @ebp+0x10        WaitType = WaitAny (1)
87fe1cec @ebp+0x14      WaitReason = WrUserRequest (13)
87fe1cf0 @ebp+0x18        WaitMode = 0 ''
87fe1cf4 @ebp+0x1c       Alertable = 0x01 '' <<<<<<<<<<<<<<<<<<<<<

This is where the DPC completed the pended IRP
(I pressed `s` for example on my HID-device)

1: kd> g
Breakpoint 1 hit
nt!IopfCompleteRequest+0x6c:
8189caa8 83466024        add     dword ptr [esi+60h],24h

0: kd> k
ChildEBP RetAddr
8193baa4 8b7f5e36 nt!IopfCompleteRequest+0x18e
8193bac0 93a3984d kbdclass!KeyboardClassServiceCallback+0x182
8193bae4 8af54d36 kbdhid!KbdHid_InsertCodesIntoQueue+0x91
8193baf8 8af54dbd HIDPARSE!HidP_KbdPutKey+0x30
8193bb14 8af550a6 HIDPARSE!HidP_TranslateUsage+0x7b
8193bb44 93a39a79 HIDPARSE!HidP_TranslateUsageAndPagesToI8042ScanCodes+0x66
8193bb74 8189cb50 kbdhid!KbdHid_ReadComplete+0x1ad
8193bbb0 93a2ab62 nt!IopfCompleteRequest+0x112
8193bbcc 93a2ace2 HIDCLASS!HidpDistributeInterruptReport+0xae
8193bc04 8189cb50 HIDCLASS!HidpInterruptReadComplete+0x16c
8193bc40 8ac7606d nt!IopfCompleteRequest+0x112
8193bc70 8ac7745f USBPORT!USBPORT_Core_iCompleteDoneTransfer+0x800
8193bc9c 8ac78b0b USBPORT!USBPORT_Core_iIrpCsqCompleteDoneTransfer+0x489
8193bcc4 8ac72d3e USBPORT!USBPORT_Core_UsbIocDpc_Worker+0x101
8193bce8 8188f282 USBPORT!USBPORT_Xdpc_Worker+0x228
8193bd50 8189e2c3 nt!KiRetireDpcList+0x198
8193bd54 00000000 nt!KiIdleLoop+0x43

now the APC of the RIT is invoked

1: kd> k
ChildEBP RetAddr
87fe1be4 818a9f60 win32k!InputApc
87fe1c34 818a100e nt!KiDeliverApc+0x138
87fe1c84 8189d707 nt!KiSwapThread+0x4a1
87fe1cd8 9083e5be nt!KeWaitForMultipleObjects+0x568
87fe1d34 9083ebdc win32k!RawInputThread+0x505
87fe1d48 9090ad0c win32k!xxxCreateSystemThreads+0x4a
87fe1d58 8188a55a win32k!NtUserCallNoParam+0x1b
87fe1d58 76e31584 nt!KiFastCallEntry+0x12a
00bdf964 00000000 ntdll!KiFastSystemCallRet

and the APC adds a message to the message queue of the foreground thread

0: kd> k
ChildEBP RetAddr
87fe1aac 908ab363 win32k!AllocQEntry+0x63
87fe1ac4 9095754d win32k!PostInputMessage+0x46
87fe1b38 90955e73 win32k!xxxKeyEvent+0x8a4
87fe1b70 9096d405 win32k!xxxProcessKeyEvent+0x290
87fe1bb0 9096d479 win32k!ProcessKeyboardInputWorker+0x2dc
87fe1bd0 90918622 win32k!ProcessKeyboardInput+0x68
87fe1be4 818a9f60 win32k!InputApc+0x58
87fe1c34 818a100e nt!KiDeliverApc+0x138
87fe1c84 8189d707 nt!KiSwapThread+0x4a1
87fe1cd8 9083e5be nt!KeWaitForMultipleObjects+0x568
87fe1d34 9083ebdc win32k!RawInputThread+0x505
87fe1d48 9090ad0c win32k!xxxCreateSystemThreads+0x4a
87fe1d58 8188a55a win32k!NtUserCallNoParam+0x1b
87fe1d58 76e31584 nt!KiFastCallEntry+0x12a
00bdf964 00000000 ntdll!KiFastSystemCallRet

and here is where GetMessage() picks it up

1: kd> k
ChildEBP RetAddr
98570b18 908ab91a win32k!DelQEntry+0x38
98570b34 908a70b8 win32k!xxxSkipSysMsg+0xab
98570c80 908fe97f win32k!xxxScanSysQueue+0x159e
98570ce8 908ffa64 win32k!xxxRealInternalGetMessage+0x32e
98570d4c 8188a55a win32k!NtUserGetMessage+0x3f
98570d4c 76e31584 nt!KiFastCallEntry+0x12a
0022f888 75a1dbff ntdll!KiFastSystemCallRet
0022f88c 75a1dc32 USER32!NtUserGetMessage+0xc
0022f8a8 003a159f USER32!GetMessageW+0x33
0022fcac 003a574c taskmgr!wWinMain+0x5f3
0022fd40 755779a3 taskmgr!__wmainCRTStartup+0x150
0022fd4c 76e1093b KERNELBASE!BaseThreadInitThunk+0xe
0022fd8c 76e1090e ntdll!__RtlUserThreadStart+0x23
0022fda4 00000000 ntdll!_RtlUserThreadStart+0x1b

--
This posting is provided "AS IS" with no warranties, and confers no rights..
Use of any included script samples are subject to the terms specified athttp://www.microsoft.com/info/cpyright.htm

"smawsk" <sk.sma...@xxxxxxxxx> wrote in message

news:5dcf61ac-480c-45a6-be60-e3b34e8bf556@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx



I have posted this question to other groups. But did not find an
answer.
Here's the question. Any thoughts on this is highly appreciated.
===================================================================
Hi,

I have some doubts regarding the event handling process in Windows. I
referred many books (Windows Internals, Programming Applications for
Microsoft

Windows, Windows System Programming) but could not find a complete
picture of the event handling mechanism. I did search on the internet
too.

Can some one please point me towards any resource on the internet or
some book that describes the entire process in detail?

I understood the process in bits and pieces. I have summarised my
understanding of the process below. Please correct me.

I will take the example of a keyboard event. SEE Q-1, Q-2, Q-3, Q-4
AND Q-5 FOR QUESTIONS.

1) User has hit some key on the key board and generates a hardware
interrupt
2) CPU is interrupted by the Interrupt Controller which converts the
IRQ to an interrupt number representing the interrupt.
3) The interrupt number is used as an index into the Interrupt
Dispatch Table to get the address of the Kernel routine to be executed
for that particular interrupt.
4) The Kernel routine calls the Kernel Interrupt Dispatcher which
raises the IRQL to the Device IRQL of the device which raised the
interrupt and starts executing the ISR.
5) The ISR gathers the volatile information from the device and queues
a DPC to be executed later and returns to the dispatcher.
6) The dispatcher lowers the IRQL to the one which was earlier. When
the IRQL is about to drop to DPC/Dispatch Level, the DPC gets
processed.
7) The DPC routine is executed which completes the task of I/O
operation. Now the data in the kernel mode buffer has to be copied to
the address space of the process containing the thread. So it queues
an APC in the thread's APC queue.

=================================================================
       Q-1) How does the kenel knows which thread's APC to queue this
APC
request to?
       Q-2) Will it be a user mode APC or a kernel mode APC?
       Q-3) I assume that APC queue and Message queue are different.
Am I
right?
==================================================================
Jeffrey Richter discusses about this topic in Windows Messaging. He
referrs to something called as RIT (Raw Input Thread). But I could not
find any thing related to RIT in Windows Internals by Solomon.
Does it has something to do with Foreground process and GUI thread?

I am not entirely clear on this topic.

8) The APC is delivered when the thread gets into an "alertable wait"
state.
===========================================================================­===========
       Q-4) From this APC queue, how does it gets transferred to the
thread's message queue?
I mean, when GetMessage() is called in the message loop the MSG
structure is filled in with the message ID and the other data.
Where is this message queue implemented. Each GUI thread has a message
queue(s), but where is it implemeted in the thread object. Neither the
KTHREAD block NOR the Thread Environment Block has any reference to
such queue.

Q-5) Does a mouse event also requires an APC? Since there is no data
to be copied to the process address space. And how does the kernel
knows which thread's message queue to put this mouse event to?
===========================================================================­===========

I am totally lost. Some might argue that these details are not
required from a programmers perspective, but this would help me in
better understanding the Operating System.

Thanks in advance.

Warm Regards.- Hide quoted text -

- Show quoted text -

Hi,

Thanks a ton for your detailed explaination. That helped me a lot. But
still there are some question that are troubling me. Could you please
clarify my doubts?

When a thread calls some I/O related function, an IRP is created for
this request and the Kernel (I/O manager)
has information about the thread which called this
method(GetCurrentThread()). So it can make an entry in the IRP to
point to the
thread object.

THe association between the IRP and the requestor thread is clear in
the above case.

But the situation looks a bit different in the case when a hardware
event is generated.
Assume that The thread is in an alertable wait state, and hence the
thread is put in the wait queue. And now the event is generated.
How does it finds which thread from the wait queue should be the one
to receive this APC?
Is there any information in the thread object which identifies it as a
foreground thread?

In the first case, the IO manager creates an IRP. In the second case,
who creates an IRP and appends it to the device queue (device IRP
queue)?Is It the device driver?

And where is this message queue implemented? I think its in the user
space. But which OS data structures represent a message queue?
To put it cearly, the KTHREAD block maintains a pointer to the APC
queue. Similarly how does a thread maintains information about its
message Q.

I am a bit curious to know how you debugged the entire event handling
mechanism. I have not done it earlier. Did you use kd or winDbg?
I have just started investigation into the ocean of Windows
archiecture. Could you please advise me what is the right methodology
of understanding the architecture of Windows? I am unable to find all
the required information in one single book and in a process of
reading from multiple resources , I am getting completely lost.
Like which books should be read first? Could you please point me to
some good articles/papers on Internet which explain things in a simple
way.

Thanks a lot again.

Warm Regards.


.



Relevant Pages

  • Re: WdfRequesSend causes WDF access violation
    ... IN WDFQUEUE Queue, ... IN WDFREQUEST Request ... Start the IRP on the device. ...
    (microsoft.public.development.device.drivers)
  • Re: DeviceIoControl blocks even in Overlapped I/O mode? How is this possible?
    ... (IRP in your case) ... queue might not continue running until after the queue processing logic has ... the rules of the stack in which your driver exists. ... I took your suggestion and reversed the order of calling ...
    (microsoft.public.development.device.drivers)
  • Re: DeviceIoControl blocks even in Overlapped I/O mode? How is this possible?
    ... I did assume that queue processing is done by a worker thread that could be ... STATUS_PENDING never touching the IRP after 2 in the dispatch function ...
    (microsoft.public.development.device.drivers)
  • Re: DeviceIoControl blocks even in Overlapped I/O mode? How is this possible?
    ... if you are managing the queue the order is not critical. ... Omitting the IoMarkIrpPending or doing it after the return from the ... dispatch routine, could have caused the behavior you describe. ... STATUS_PENDING never touching the IRP after 2 in the dispatch function ...
    (microsoft.public.development.device.drivers)
  • Re: Combining IoCsqRemoveNextIrp with own Cancellation Routine?
    ... once you pulled the irp off the queue and this is a long lived irp that will not be completed until a very long time, you can use Irp->Cancel to occasionally see what you want to do. ... if you need to have a group of requests queued up + one active cancelable request you can always use 2 CSQs and put the single cancelable request in the 2nd queue ... Please do not send e-mail directly to this alias. ...
    (microsoft.public.development.device.drivers)