diff options
author | Andreas Klebinger <klebinger.andreas@gmx.at> | 2020-06-22 15:54:33 +0200 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2020-07-15 16:41:03 -0400 |
commit | f260a7218f71398ad2dbca0f47feaf31c21081b3 (patch) | |
tree | 5015e547f94b4a2759c57cf37b69f44bcb54ffbc | |
parent | 916fc861520615149c66c1069f6cb661bc8b8483 (diff) | |
download | haskell-f260a7218f71398ad2dbca0f47feaf31c21081b3.tar.gz |
winio: Note why we don't use blocking waits.
-rw-r--r-- | libraries/base/GHC/Event/Windows.hsc | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/libraries/base/GHC/Event/Windows.hsc b/libraries/base/GHC/Event/Windows.hsc index fa9b901ea8..305ba10f3d 100644 --- a/libraries/base/GHC/Event/Windows.hsc +++ b/libraries/base/GHC/Event/Windows.hsc @@ -528,6 +528,30 @@ associateHandle Manager{..} h = -- completion FFI.associateHandleWithIOCP mgrIOCP h (fromIntegral $ ptrToWordPtr h) + +{- Note [Why use non-waiting getOverlappedResult requests.] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + When waiting for a request that is bound to be done soon + we spin inside waitForCompletion. There are multiple reasons + for this. + + In the non-threaded RTS we can't perform blocking calls to + C functions without blocking the whole RTS so immediately + a blocking call is not an option there. + + In the threaded RTS we don't use a blocking wait for different + reasons. In particular performing a waiting request using + getOverlappedResult uses the hEvent object embedded in the + OVERLAPPED structure to wait for a signal. + However we do not provide such an object as their creation + would incur to much overhead. Making a waiting request a + less useful operation as it doesn't guarantee that the + operation we were waiting one finished. Only that some + operation on the handle did. + +-} + -- | Start an overlapped I/O operation, and wait for its completion. If -- 'withOverlapped' is interrupted by an asynchronous exception, the operation -- will be canceled using @CancelIoEx@. @@ -638,6 +662,9 @@ withOverlappedEx mgr fname h offset startCB completionCB = do -- This status indicates that the request hasn't finished early, -- but it will finish shortly. The I/O manager will not be -- enqueuing this either. Also needs to be handled inline. + -- Sadly named pipes will always return this error, so in practice + -- we end up always handling them synchronously. There is no good + -- documentation on this. let will_finish_sync = lasterr == #{const ERROR_IO_INCOMPLETE} debugIO $ "== >*< " ++ show (finished, done_early, will_finish_sync, h, lpol, lasterr) @@ -756,6 +783,11 @@ withOverlappedEx mgr fname h offset startCB completionCB = do -- Wait for the request to finish as it was running before and -- The I/O manager won't enqueue it due to our optimizations to -- prevent context switches in such cases. + -- In the non-threaded case we must use a non-waiting query here + -- otherwise the RTS will lock up until we get a result back. + -- In the threaded case it can be beneficial to spin on the haskell + -- side versus + -- See also Note [Why use non-waiting getOverlappedResult requests.] res <- FFI.getOverlappedResult fhndl lpol False status <- FFI.overlappedIOStatus lpol case res of |