asynchronous io

Hello,

  1. When createfile function is called with FILE_FLAG_OVERLAPPED it means that given device will be used for asynchronous io and (as documentation says) DeviceIoControl function should be called with properly initialized OVERLAPPED structure with event fow which we should wait to be sure that operation has been completed. now: Is there ANY exception from rule above? I mean is there any correct scenario possible that I open device with FILE_FLAG_OVERLAPPED and will do DeviceIoControl w/o OVERLAPPED structrure?

  2. Can somebody describe a little bit how internall windows kernel realizes this asynchronous IO? Or just to do comparsion in windows kernel behavior between synchronous and asynchronous calls?

thanks in advance

A Windows driver does not care, all I/O is treated as async. Basically a
small portion of the I/O manager handles the question of sync versus async,
and everything else just acts asynchronous.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Monday, July 29, 2013 4:51 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] asynchronous io

Hello,

  1. When createfile function is called with FILE_FLAG_OVERLAPPED it means
    that given device will be used for asynchronous io and (as documentation
    says) DeviceIoControl function should be called with properly initialized
    OVERLAPPED structure with event fow which we should wait to be sure that
    operation has been completed. now: Is there ANY exception from rule above? I
    mean is there any correct scenario possible that I open device with
    FILE_FLAG_OVERLAPPED and will do DeviceIoControl w/o OVERLAPPED structrure?

  2. Can somebody describe a little bit how internall windows kernel realizes
    this asynchronous IO? Or just to do comparsion in windows kernel behavior
    between synchronous and asynchronous calls?

thanks in advance


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

1 you must always provided the OVERLAPPED struct if opened as overlapped

2 when not opened as overlapped, the io manager uses a lock embedded in the file object to serialize io. When overlapped, no lock is taken

d

Bent from my phone


From: xxxxx@gmail.commailto:xxxxx
Sent: ?7/?29/?2013 1:51 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: [ntdev] asynchronous io

Hello,

1. When createfile function is called with FILE_FLAG_OVERLAPPED it means that given device will be used for asynchronous io and (as documentation says) DeviceIoControl function should be called with properly initialized OVERLAPPED structure with event fow which we should wait to be sure that operation has been completed. now: Is there ANY exception from rule above? I mean is there any correct scenario possible that I open device with FILE_FLAG_OVERLAPPED and will do DeviceIoControl w/o OVERLAPPED structrure?

2. Can somebody describe a little bit how internall windows kernel realizes this asynchronous IO? Or just to do comparsion in windows kernel behavior between synchronous and asynchronous calls?

thanks in advance


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

Also, you should only wait on the event if the call returned FALSE with last error ERROR_IO_PENDING.

> Hello,

  1. When createfile function is called with FILE_FLAG_OVERLAPPED it means
    that given device will be used for asynchronous io and (as documentation
    says) DeviceIoControl function should be called with properly initialized
    OVERLAPPED structure with event fow which we should wait to be sure that
    operation has been completed. now: Is there ANY exception from rule above?
    I mean is there any correct scenario possible that I open device with
    FILE_FLAG_OVERLAPPED and will do DeviceIoControl w/o OVERLAPPED
    structrure?

Actually, I never use the hEvent member; but if you don’t care, you MUST
set it to NULL. Waiting on events is a pretty losing idea most of the
time. To me, there is only one sane way to implement asynchronous I/O and
that is to use I/O Completion Ports. Waiting on events can be more
complex than it is worth. You have to somehow map the index of the event
to the information associated with it, then remove the event from the
handle array and make sure your index-to-associated-information map
reflects the new handle array. The one exception is what I call
“pseudo-synchronous I/O”, where you are working on a device that can
handle multiple IRPs concurrently, but that’s another discussion.

I have built apps using hEvent waiting, using callback I/O, using
“pseudo-synchronous” I/O, and I/O Completion Ports, and of all the methods
IOCPs were the easiest to write, maintain, and required virtually no
effort to debug.

Note that the OVERLAPPED structure must have a lifetime of the I/O
operation itself, so only in very restricted scenarios does it make sense
to have it as a local variable, so if you build a structure of the form

typedef struct {
OVERLAPPED ovl;
…your information associated with the I/O operation
…including buffer pointers, and anything else you need
} MY_OVERLAPPED, *PMY_OVERLAPPED;

then allocate these on the heap, when the IOCP gets the pointer to the
OVERLAPPED structure, you can use casting to widen it to the larger
structure, and everything you need is there.

I could give a long lecture on why callback I/O is a complete disaster in
multicore systems, but the simple summary is that the callback must be
handled by the thread that initializes the I/O, and only happens if you
get that thread into alertable wait state. This becomes a limiting factor
on I/O throughput.

  1. Can somebody describe a little bit how internall windows kernel
    realizes this asynchronous IO? Or just to do comparsion in windows kernel
    behavior between synchronous and asynchronous calls?

thanks in advance

Essentially, the driver does not care. The I/O Manager handles the
translation from an I/O request and the scheduling. When the I/O Manager
sends an IRP to the driver, it looks at the nature of the handle. For a
synchronous handle, it tells the scheduler to deschedule the thread that
issued the call. For async I/O, when control returns to the I/O Manager,
it looks at the return code; if it is STATUS_PENDING, it resumes the
thread with the result FALSE and the thread’s GetLastError() value set to
ERROR_IO_PENDING (if I recall the name correctly). When the IRP is
completed, the I/O Manager will take action to queue a APC (for callback
I/O), set an event (if in the OVERLAPPED structure), or enqueue a request
in the IOCP queue (for I/O Completion Port handling). The rest is just
messy details, such as what happens if the IRP is completed before control
returns from the top-level dispatch handler; it does the right thing.
Consider it Magic. But below the I/O Manager, you almost never, ever have
to care about the nature of the request. There is no issue of
“realization”; it just deals with all of this magic in the I/O Manager.
You should expect your driver will get multiple I/O requests concurrently
from any number of threads. There are a huge number of driver bugs you
can uncover if you just create an asynchronous handle and send down a few
dozen requests. A driver which follows all the guidelines given will not
care; one where there are serious deviations from the proper guidelines,
the driver will crash in a variety of very ugly ways when confronted with
multiple incoming IRPs.
joe


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

The vista and later thread pool APIs abstract completion ports and provide a much better async io story in terms of resource usage and management

d

Bent from my phone


From: xxxxx@flounder.commailto:xxxxx
Sent: ?7/?29/?2013 11:27 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: Re: [ntdev] asynchronous io

> Hello,
>
> 1. When createfile function is called with FILE_FLAG_OVERLAPPED it means
> that given device will be used for asynchronous io and (as documentation
> says) DeviceIoControl function should be called with properly initialized
> OVERLAPPED structure with event fow which we should wait to be sure that
> operation has been completed. now: Is there ANY exception from rule above?
> I mean is there any correct scenario possible that I open device with
> FILE_FLAG_OVERLAPPED and will do DeviceIoControl w/o OVERLAPPED
> structrure?
>

Actually, I never use the hEvent member; but if you don’t care, you MUST
set it to NULL. Waiting on events is a pretty losing idea most of the
time. To me, there is only one sane way to implement asynchronous I/O and
that is to use I/O Completion Ports. Waiting on events can be more
complex than it is worth. You have to somehow map the index of the event
to the information associated with it, then remove the event from the
handle array and make sure your index-to-associated-information map
reflects the new handle array. The one exception is what I call
“pseudo-synchronous I/O”, where you are working on a device that can
handle multiple IRPs concurrently, but that’s another discussion.

I have built apps using hEvent waiting, using callback I/O, using
“pseudo-synchronous” I/O, and I/O Completion Ports, and of all the methods
IOCPs were the easiest to write, maintain, and required virtually no
effort to debug.

Note that the OVERLAPPED structure must have a lifetime of the I/O
operation itself, so only in very restricted scenarios does it make sense
to have it as a local variable, so if you build a structure of the form

typedef struct {
OVERLAPPED ovl;
…your information associated with the I/O operation
…including buffer pointers, and anything else you need
} MY_OVERLAPPED, *PMY_OVERLAPPED;

then allocate these on the heap, when the IOCP gets the pointer to the
OVERLAPPED structure, you can use casting to widen it to the larger
structure, and everything you need is there.

I could give a long lecture on why callback I/O is a complete disaster in
multicore systems, but the simple summary is that the callback must be
handled by the thread that initializes the I/O, and only happens if you
get that thread into alertable wait state. This becomes a limiting factor
on I/O throughput.

> 2. Can somebody describe a little bit how internall windows kernel
> realizes this asynchronous IO? Or just to do comparsion in windows kernel
> behavior between synchronous and asynchronous calls?
>
> thanks in advance

Essentially, the driver does not care. The I/O Manager handles the
translation from an I/O request and the scheduling. When the I/O Manager
sends an IRP to the driver, it looks at the nature of the handle. For a
synchronous handle, it tells the scheduler to deschedule the thread that
issued the call. For async I/O, when control returns to the I/O Manager,
it looks at the return code; if it is STATUS_PENDING, it resumes the
thread with the result FALSE and the thread’s GetLastError() value set to
ERROR_IO_PENDING (if I recall the name correctly). When the IRP is
completed, the I/O Manager will take action to queue a APC (for callback
I/O), set an event (if in the OVERLAPPED structure), or enqueue a request
in the IOCP queue (for I/O Completion Port handling). The rest is just
messy details, such as what happens if the IRP is completed before control
returns from the top-level dispatch handler; it does the right thing.
Consider it Magic. But below the I/O Manager, you almost never, ever have
to care about the nature of the request. There is no issue of
“realization”; it just deals with all of this magic in the I/O Manager.
You should expect your driver will get multiple I/O requests concurrently
from any number of threads. There are a huge number of driver bugs you
can uncover if you just create an asynchronous handle and send down a few
dozen requests. A driver which follows all the guidelines given will not
care; one where there are serious deviations from the proper guidelines,
the driver will crash in a variety of very ugly ways when confronted with
multiple incoming IRPs.
joe
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

>operation has been completed. now: Is there ANY exception from rule above?

Sometimes yes, but you should not rely on this, this is undocumented.

“Get/set property” IOCTLs for a COM port are the sample.

This occurs if the IRP is processed synchronously by the driver, without pending. If the driver will pend the IRP - then you will not be able to get a completion notification in this case.

  1. Can somebody describe a little bit how internall windows kernel realizes this asynchronous IO?

OVERLAPPED is split in kernel32.dll to UserEvent, UserIosb (Internal/InternalHigh) and ByteOffset.

These values are passed as parameters to NtDeviceIoControlFile.

Then, when kernel’s NtDeviceIoControlFile will build the IRP, it will fill Irp->UserEvent and ->UserIosb with these values. They will be used for completion notification.

Also, for read/write calls, the byte offset in the stack location will be set from the parameter of NtRead/WriteFile, not from FileObject->CurrentByteOffset, and the underlying driver should not advance FileObject->CurrentByteOffset.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

>A Windows driver does not care, all I/O is treated as async. Basically a

small portion of the I/O manager handles the question of sync versus async,
and everything else just acts asynchronous.

With one exception:

  • Windows drivers should not block in dispatch routines (this breaks the overlapped IO).
  • but, if the IO operation is surely not overlapped (IoIsOperationSynchronous), they are allowed to block.

FSDs, for instance, offload the IRP to the pool’s thread if they cannot take the FCB locks without blocking.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

Hello again,
I’m sorry for late response,
Next question: In case I created a top level driver with some filtering realized with CmCalbacks - does it change anything if from usermode I will do createfile with file_flag_overlapped or not?
Or on what it CAN depend?
Basically from usermode I’m queryging wheter application is able to do something or not. and I’m doing it in loop (max 3 times) taking informaiton in 3 different ways (different places) - and quesion is if it is ok to do this querying with createfile with overlapped io? Is it possibe (even theoretically that my top level driver will return pending anyhow? or it will always return what I have in my dispatch IO?

thank you.

xxxxx@gmail.com wrote:

Next question: In case I created a top level driver with some filtering realized with CmCalbacks - does it change anything if from usermode I will do createfile with file_flag_overlapped or not?
Or on what it CAN depend?
Basically from usermode I’m queryging wheter application is able to do something or not. and I’m doing it in loop (max 3 times) taking informaiton in 3 different ways (different places) - and quesion is if it is ok to do this querying with createfile with overlapped io? Is it possibe (even theoretically that my top level driver will return pending anyhow? or it will always return what I have in my dispatch IO?

I’m not sure I follow the question you’re asking. If your driver always
holds on to the request until it is completed, then it doesn’t make any
difference whether the app uses overlapped I/O or not. The thread will
be blocked in kernel mode until you complete the request.

If the driver returns “pending” immediately, then the behavior depends
on the overlapped flag. If the app uses overlapped I/O, then it will
get control back immediately and can do something else. If the app does
not use overlapped, then the thread will block in the I/O manager until
the request is completed.

The kernel will never invent a return code for you. If you return
pending, then pending is returned. If you don’t, then it isn’t.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> Hello again,

I’m sorry for late response,
Next question: In case I created a top level driver with some filtering
realized with CmCalbacks - does it change anything if from usermode I will
do createfile with file_flag_overlapped or not?
Or on what it CAN depend?
Basically from usermode I’m queryging wheter application is able to do
something or not. and I’m doing it in loop (max 3 times) taking
informaiton in 3 different ways (different places) - and quesion is if it
is ok to do this querying with createfile with overlapped io? Is it
possibe (even theoretically that my top level driver will return pending
anyhow? or it will always return what I have in my dispatch IO?

thank you.

First, overlapped I/O is just like regular I/O. The key is tht if you
have an I/O function FIO(h,…) tnen in synchronous mode you can write
A(); FIO(); B(); and get the desired effect. But with async I/O, you
would have to write A(); FIO(h,…); wait(e(h)); B(); which sort of
defeats the purpose of having asynchronous I/O.

The key here is a major paradigm shift: you have to stop associating
sequentiality of execution with sequentiality of syntax. Treat this
concept as largely an artifact of programming prehistory, when “multicore”
meant “we’re going to need two forklifts to get it off the trucks instead
of one forklift to get it off the truck.”

So in the driver, you just fill in te information or set te error code,
and complete the request. You see nothing special to indicate this is
synchronous or asynchronous. Just Do It. An important consideration is
how this request fits into tge sequentiality model of general I/O. For
example, it doesn’t matter if you are asking if the device is capable of
doing something if that is an intrinsic property of the device; it is
always true, or it is always false. You can just complete this request.
No problem. But consider a serial port doing asynchrnous writes. There
are a pending set of writes for the device, W0, W1, …, Wn, where W0 is
the head of the queue. If you DeviceIoControl to change te baud rate, it
changes the baud rate immediately. It might even be in the middle of a
character! So, consider that Wn contained a message to the recipient to
change to a new baud rate. Oopsie. Ok, we’ll wait for Wn to complete.
Unfortunately, te serial driver completes the request after it places the
last character of Wn into the transmit buffer (I hope they fixed this).
At 9600 baud, it takes 3ms to send the character, and on modern machines,
even those of a decade ago (when I had this problem), 3ms was more tan
enough time to respond to the completion request and send the baud rate
change down, and te baud rate change happened in te middle of transmitting
the last character (the checksum). When you do DeviceIoControl, match
them to te logic of your API interface, not to the logic of the device.

Now, consider that you are using an IOCP (the only sane way to do asyc
I/O, in my opinion; straightforward, maximizes concurrency, scales to
large-core environments). You want to do A(); FIO(); B(); where FIO() is
your query. The way to handle this is in a thread. The thread waits for
the completion of FIO() then executes B(). Now you say you are doing te
query in three places. Your pattern is A1(); FIO(); B1(); and somewhere
else, A2(); FIO(); B2(); and A3(); FIO(); B3();. How do you handle this?
The easiest way is to package a function pointer with the OVERLAPPED
structure. Let this be called ovl->F(). So now your sequence is

A1(); ovl->F = &B1(); FIO();
A2(); ovl->F = &B2(); FIO();
A3(); ovl->F = &B3(); FIO();

Now the handler thread is
while(true)
{ /* receiver loop */
OVERLAPPED * ovl;
GetQueuedRequest(…, &ovl, …);
ovl->F();
} /* receiver loop */

Note tat this sketch is at best pseudocode. For example, error checking
and casts are left as an Exercise For The Reader. Also, there is no way
to add anything to an OVERLAPPED structure. Ah, but there is. Consider
te following:

typedef (__stdcall void FIOCONTINUATION *)(…args…);

then we can write

typedef struct {
OVERLAPPED ovl;
FIOCONTINUATION F;
} MYOVERLAPPED;

MYOVERLAPPED * ovl = (MYOVERLAPPED *)malloc(sizeof(MYOVERLAPPED), …);

FIO(h, …, (OVERLAPPED *) ovl;

Note that the MYOVERLAPPED structure can contain any information you need,
such as te infrmation required to pass to F(). Or you can put a complete
struct there, and call F with a pointer to its parameter data.

When I program in C++, I create an abstract superclass:

class B {
virtual void F() PURE;
… stuff
};

class B1 : public B {
virtual void F();
};

repeat above for B2 and B3

Then I can do
typedef struct {
OVERLAPPED ovl;
B* Action;
};

Then I can write
A1(); ovl = new MYOVERLAPPED; ovl->Action = new B1(…); FIO(h, …,
(OVERLAPPED *)ovl);

and in the loop you do
ovl->Action.F();

Key here is to adopt a new paradigm of application construction. In the
driver, you don’t care.

As in the past, much of the casting and error detection and processing are
LAAEFTR. But I’ve built multiple apps using a variety of tese techniques.
What is important to realize is that to convert an app from synchronous
to asynchronous I/O is absolutely NOT a trivial operation; one of the
contracts I didn’t get was a massive piece of trash that I later
discovered was based on a Microsoft example on multithreaded asynchronous
network I/O (other than the fact that the author understood nothing about
asynchronous network connection, threading, or synchronization, there was
nothing wrong with it. I got it nuked from te MSDN examples, and an
analysis of its failure modes and a complete rewrite are on my MVP Tips
Web site. I quoted them a price, and they had no budget to cover that
price. But the rewrite would have been a massive effort.

So don’t worry about what the driver has to do; it doesn’t matter. But
make sure the app isn’t a hacked-together pile of crap as the programmer
tries to warp a synchronous pattern into an asynchronous pattern.
joe


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I cannot understand how are CmCallbacks related to file IO.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> Hello again,
> I’m sorry for late response,
> Next question: In case I created a top level driver with some filtering realized with CmCalbacks - does it change anything if from usermode I will do createfile with file_flag_overlapped or not?
> Or on what it CAN depend?
> Basically from usermode I’m queryging wheter application is able to do something or not. and I’m doing it in loop (max 3 times) taking informaiton in 3 different ways (different places) - and quesion is if it is ok to do this querying with createfile with overlapped io? Is it possibe (even theoretically that my top level driver will return pending anyhow? or it will always return what I have in my dispatch IO?
>
> thank you.
>