mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 08:50:49 +00:00
ntdll: Use an acquire/release pair on the IOSB status.
This commit is contained in:
parent
7c2af26a62
commit
282120a9c5
|
@ -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 );
|
||||
#ifdef NONAMELESSUNION
|
||||
io->u.Status = status;
|
||||
#else
|
||||
io->Status = status;
|
||||
#endif
|
||||
io->Information = info;
|
||||
#ifdef NONAMELESSUNION
|
||||
WriteRelease( &io->u.Status, status );
|
||||
#else
|
||||
WriteRelease( &io->Status, status );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue