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 ...@@ -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 ); 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 (status == STATUS_PENDING)
{ {
if (!timeout) if (!timeout)
...@@ -3173,6 +3175,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetOverlappedResultEx( HANDLE file, OVERLAPPED *ov ...@@ -3173,6 +3175,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetOverlappedResultEx( HANDLE file, OVERLAPPED *ov
return FALSE; 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; status = overlapped->Internal;
if (status == STATUS_PENDING) status = STATUS_SUCCESS; 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 ...@@ -367,6 +367,24 @@ static inline void set_async_iosb( client_ptr_t iosb, NTSTATUS status, ULONG_PTR
{ {
if (!iosb) return; 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()) if (in_wow64_call())
{ {
struct iosb32 struct iosb32
...@@ -374,18 +392,18 @@ static inline void set_async_iosb( client_ptr_t iosb, NTSTATUS status, ULONG_PTR ...@@ -374,18 +392,18 @@ static inline void set_async_iosb( client_ptr_t iosb, NTSTATUS status, ULONG_PTR
NTSTATUS Status; NTSTATUS Status;
ULONG Information; ULONG Information;
} *io = wine_server_get_ptr( iosb ); } *io = wine_server_get_ptr( iosb );
io->Status = status;
io->Information = info; io->Information = info;
WriteRelease( &io->Status, status );
} }
else else
{ {
IO_STATUS_BLOCK *io = wine_server_get_ptr( iosb ); IO_STATUS_BLOCK *io = wine_server_get_ptr( iosb );
io->Information = info;
#ifdef NONAMELESSUNION #ifdef NONAMELESSUNION
io->u.Status = status; WriteRelease( &io->u.Status, status );
#else #else
io->Status = status; WriteRelease( &io->Status, status );
#endif #endif
io->Information = info;
} }
} }
......
...@@ -3710,7 +3710,9 @@ BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped, ...@@ -3710,7 +3710,9 @@ BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
return FALSE; 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 (status == STATUS_PENDING)
{ {
if (!fWait) if (!fWait)
...@@ -3722,6 +3724,8 @@ BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped, ...@@ -3722,6 +3724,8 @@ BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s), if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : SOCKET2HANDLE(s),
INFINITE ) == WAIT_FAILED) INFINITE ) == WAIT_FAILED)
return FALSE; 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; 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