aio_reap.2 (2010 09)
a
aio_reap(2) aio_reap(2)
The timeout parameter must be either NULL or point to a
timespec structure that has a timeout
time specified. If a
NULL
pointer is specified, then no timeout handling is performed and aio_reap()
blocks until waitfor AIO requests are available. If
timeout points to a zero-value timespec struc-
ture,
aio_reap() returns immediately after checking for any completed AIO requests (behaves similar
to poll()).
The
aio_reap() function call returns to the calling process in any of the following conditions:
1. the specified number of completed requests are available, or
2. the timeout time has elapsed, or
3. a signal has interrupted the function, or
4. an error situation is detected.
In all cases,
aio_reap() will attempt to collect as many IOs as possible at the time of its return, even if
less than waitfor IOs have completed when a timeout, signal, or error interrupts
aio_reap(). If
more than
waitfor IOs have completed, aio_reap() will attempt to return up to
nent IOs. As a
result, the value of
completed_count
should be checked after all calls to
aio_reap() (regardless of
its return value or errno status).
Light-Weight Polling Mode
When called with all
NULL arguments (except for completed_count
), aio_reap will simply return
in
completed_count
the number of IOs that have completed and are ready for collection.
In light-weight polling mode,
aio_reap() is implemented to execute quickly, without requiring the cost
of a regular system call. This allows applications to poll for completed IOs without incurring significant
costs.
(Note: all releases will provide this polling functionality, but the actual mechanism by which lightweight
polling is implemented is release specific. However, it should in all cases be faster than a regular system
call.)
Multithreading Notes
The
aio_reap() interface is completely thread safe, but there are three issues that multithreaded
applications should be aware of:
The first is starvation. When multiple threads concurrently perform
aio_reap() calls, there is no
guarantee that completed I/Os will be distributed fairly across the calls. For example, if 50
I/Os are
issued and two threads call
aio_reap() with waitfor=25 and nent=50, there is no guarantee that
both threads will collect any particular number of I/Os. In fact, one possible outcome is that the first
thread’s call to aio_reap() will collect all 50 I/Os, and the second thread will have none to collect.
Multithreaded applications should take this possibility into consideration, and make appropriate use of
timeout values to prevent unbounded waits in starvation situations.
Another related issue is that when threads perform
aio_reap() calls, they can collect I/Os issued by
any thread in the process (not just the calling thread). As an example, if thread A and thread B each
issue 10 I/Os, and then each calls aio_reap() with waitfor=10 and nent=10, no assumptions can
be made about which I/Os each call to aio_reap() will collect. Thread A’s call to aio_reap() might
collect all 10 of thread A’s I/Os, all 10 of thread B’s I/Os, or any mixture of the two. The only guaranteed
behavior is that the first call to aio_reap() will collect the first 10 I/Os to complete.
The third issue is that it is possible for multiple threads to disrupt execution of
aio_reap() if they cor-
rupt the arguments to aio_reap() during its execution. For example, problems can arise if one thread
of a multithreaded application invalidates the completed_count pointer used by another thread con-
currently executing a call to
aio_reap() (e.g. by freeing or mlocking the corresponding memory). If
this happens, it is possible for aio_reap() to complete I/Os and fill in aio_completion_t struc-
tures but then be unable to update completed_count. In this case aio_reap() will return with
errno set to [EFAULT], but will have no way to let the application know how many IOs it has completed.
The completed I/Os will be stored in list, but the application will not be able to know how many I/Os
have completed, so it is possible to lose I/Os in this case. Multithreaded applications must avoid this
situation.
Usage Notes
To use
aio_reap(), link in the realtime library by specifying -lrt on the compiler or linker command
line. Then, before making any AIO function calls, initialize the reap mechanism by calling aio_reap()
in lightweight mode, as shown in this example:
2 Hewlett-Packard Company − 2 − HP-UX 11i Version 3: September 2010