From: Torge Matthies tmatthies@codeweavers.com
--- dlls/ntdll/unix/server.c | 4 ++++ server/thread.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 51a83f472e1..c52daa18cce 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -602,6 +602,10 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT sigset_t old_set; int signaled;
+ /* Ensure writes so far are visible to other threads, so that we can avoid sending a memory barrier APC + * from NtFlushProcessWriteBuffers to this thread while it is sleeping. */ + MemoryBarrier(); + memset( &result, 0, sizeof(result) );
do diff --git a/server/thread.c b/server/thread.c index 9eed1e5bbdf..bf3bda0a058 100644 --- a/server/thread.c +++ b/server/thread.c @@ -2112,8 +2112,9 @@ DECL_HANDLER(flush_process_write_buffers) struct thread_apc *apc; int success;
- /* Do not send a memory barrier APC to the current thread or a terminated thread. */ - if (thread == current || thread->state == TERMINATED) continue; + /* Do not send a memory barrier APC to the current thread or a terminated thread. A memory barrier is also + * unnecessary for waiting threads, because server_select performs a memory barrier. */ + if (thread == current || thread->state == TERMINATED || thread->wait) continue;
if (!(apc = create_apc( ¤t->obj, &call ))) break;