RFC: Hybrid (wineserver / process-local) native semaphores

Daniel Santos daniel.santos at pobox.com
Thu Sep 10 01:07:48 CDT 2015


This patch set fixes most performance problems caused by 
ReleaseSemaphore() and WaitForSingle/MultipleObject(s) making server 
calls. One victim of this is Star Wars Battlefront 
(https://bugs.winehq.org/show_bug.cgi?id=29582), where the majority of 
the CPU time is spent on context switching while the program spams 
ReleaseSemaphore, WaitForSingle/MultipleObject(s) and 
GetForgroundWindow, the later of which I made a work-around hack for and 
that some players have been using.

This patch set doubles performance of bug #29582. (When combined with 
GetForgroundWindow hack the problem is completely resolved.) The patch 
set works by having the server create a POSIX semaphore object and 
sharing the key to that object with the client process, enabling the 
client process to be able to implement ReleaseSemaphore and 
optimistic-case wait calls (where no blocking is reburied) without a 
server call. Blocking waits and any wait-multiple that cannot be 
resolved in the client process (e.g., bWaitAll=TRUE and objects include 
non-semaphores)  is still handled by the server. (Implementing blocking 
wait calls on the client can yield some performance improvements because 
a context switch to another thread in the same program won't require 
swapping out the memory map & such, but I would expect this to be less 
significant.)

However, upon further experimentation, I discovered that POSIX 
semaphores in glibc are actually implemented using a shared memory page, 
which may not be acceptable since a bad process can corrupt that page 
and potentially cause sem_* function calls in the server to fail as well 
as other client programs fail and/or deadlock. I am working on a System 
V adaptation, but I thought it would be a good idea to see feedback & 
comments now.

Another problem is that this causes the threadpool test fails at line 
1299, where the previous "release all semaphores and wait for callback" 
test is done in reverse order. I presume this is due to the nature of 
the linux scheduler being inconsistent with how Windows *happens* to 
schedule its threads. I have an idea for a fix for this already, but I 
will still have to dig deeper into it.

The code is still in experimental quality (assert(0)s and such) and I've 
already re-worked the configure.ac stuff, I'm mostly concerned with 
feedback on the general scheme.

Thanks!
Daniel




More information about the wine-devel mailing list