Commit 282120a9 authored by Jinoh Kang's avatar Jinoh Kang Committed by Alexandre Julliard

ntdll: Use an acquire/release pair on the IOSB status.

parent 7c2af26a
......@@ -3156,7 +3156,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetOverlappedResultEx( HANDLE file, OVERLAPPED *ov
TRACE( "(%p %p %p %lu %d)\n", file, overlapped, result, timeout, alertable );
status = overlapped->Internal;
/* Paired with the write-release in set_async_iosb() in ntdll; see the
* latter for details. */
status = ReadAcquire( (LONG *)&overlapped->Internal );
if (status == STATUS_PENDING)
{
if (!timeout)
......@@ -3173,6 +3175,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetOverlappedResultEx( HANDLE file, OVERLAPPED *ov
return FALSE;
}
/* We don't need to give this load acquire semantics; the wait above
* already guarantees that the IOSB and output buffer are filled. */
status = overlapped->Internal;
if (status == STATUS_PENDING) status = STATUS_SUCCESS;
}
......
......@@ -367,6 +367,24 @@ static inline void set_async_iosb( client_ptr_t iosb, NTSTATUS status, ULONG_PTR
{
if (!iosb) return;
/* GetOverlappedResult() and WSAGetOverlappedResult() expect that if the
* status is written, that the information (and buffer, which was written
* earlier from the async callback) will be available. Hence we need to
* store the status last, with release semantics to ensure that those
* writes are visible. This release is paired with a read-acquire in
* GetOverlappedResult() and WSAGetOverlappedResult():
*
* CPU 0 (set_async_iosb) CPU 1 (GetOverlappedResultEx)
* =========================== ===========================
* write buffer
* write Information
* WriteRelease(Status) <--------.
* |
* |
* (paired with) `-> ReadAcquire(Status)
* read Information
*/
if (in_wow64_call())
{
struct iosb32
......@@ -374,18 +392,18 @@ static inline void set_async_iosb( client_ptr_t iosb, NTSTATUS status, ULONG_PTR
NTSTATUS Status;
ULONG Information;
} *io = wine_server_get_ptr( iosb );
io->Status = status;
io->Information = info;
WriteRelease( &io->Status, status );
}
else
{
IO_STATUS_BLOCK *io = wine_server_get_ptr( iosb );
io->Information = info;
#ifdef NONAMELESSUNION
io->u.Status = status;
WriteRelease( &io->u.Status, status );
#else
io->Status = status;
WriteRelease( &io->Status, status );
#endif
io->Information = info;
}
}
......
......@@ -3710,7 +3710,9 @@ BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
return FALSE;
}
status = lpOverlapped->Internal;
/* Paired with the write-release in set_async_iosb() in ntdll; see the
* latter for details. */
status = ReadAcquire( (LONG *)&lpOverlapped->Internal );
if (status == STATUS_PENDING)
{
if (!fWait)
......@@ -3722,6 +3724,8 @@ BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s),
INFINITE ) == WAIT_FAILED)
return FALSE;
/* We don't need to give this load acquire semantics; the wait above
* already guarantees that the IOSB and output buffer are filled. */
status = lpOverlapped->Internal;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment