[Interprocess] Experimental Win32 Mutexes

I'm running Boost 1.52 on Windows 7, Visual Studio 2010. I noticed in sync\interprocess_mutex.hpp there is a windows mutex implementation that is hidden behind the BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION macro. The comment indicates that it is "Experimental". Could someone shed some light on what is Experimental about it and what the general plans for this feature are? I was having a problem with many processes all spin-locking when allocating shared memory that I traced down to the old mutex implementation for shared memory. I enabled the experimental feature in my local build ( by commenting out the above macro in the detail\workaround.hpp file) and it seems to fix my problems. My performance is much improved. But what are my risks for using this implementation? I'm a little nervous to depend on something marked as "Experimental". Thanks Rob Brink

Le 09/11/12 19:05, Brink, Robert (GE Aviation, US) a écrit :
I'm running Boost 1.52 on Windows 7, Visual Studio 2010.
I noticed in sync\interprocess_mutex.hpp there is a windows mutex implementation that is hidden behind the BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION macro. The comment indicates that it is "Experimental".
Could someone shed some light on what is Experimental about it and what the general plans for this feature are?
I was having a problem with many processes all spin-locking when allocating shared memory that I traced down to the old mutex implementation for shared memory. I enabled the experimental feature in my local build ( by commenting out the above macro in the detail\workaround.hpp file) and it seems to fix my problems. My performance is much improved. But what are my risks for using this implementation? I'm a little nervous to depend on something marked as "Experimental".
Hi, in http://www.boost.org/doc/libs/1_52_0/doc/html/interprocess/acknowledgements_... it is included Boost 1.37 Release * Added |BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION| macro option to force the use of generic emulation code for process-shared synchronization primitives instead of native POSIX functions. As the documentation says this macro is Posix specific (for the user) and as the macro is defined by default on windows I guess that there are some bugs in the windows specific implementation. Ion, I think that the documentation should include this information somewhere else the release notes. HTH, Vicente

El 09/11/2012 19:05, Brink, Robert (GE Aviation, US) escribió:
I'm running Boost 1.52 on Windows 7, Visual Studio 2010.
I noticed in sync\interprocess_mutex.hpp there is a windows mutex implementation that is hidden behind the BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION macro. The comment indicates that it is "Experimental".
Could someone shed some light on what is Experimental about it and what the general plans for this feature are?
I was having a problem with many processes all spin-locking when allocating shared memory that I traced down to the old mutex implementation for shared memory.
Which kind of problem? Spinlocks are quite simple so unless it's a performance-related issue, I can't imagine what can be wrong with spinlock-based mutexes.
I enabled the experimental feature in my local build ( by commenting out the above macro in the detail\workaround.hpp file) and it seems to fix my problems. My performance is much improved. But what are my risks for using this implementation? I'm a little nervous to depend on something marked as "Experimental".
A better windows implementation was needed, but it's not easy to write it. I don't know of any PTHREAD_PROCESS_SHARED windows emulation. Cygwin does not even try to emulate it. The implementation is not optimized, I had no time to test it thoroughly, and in some aspects it's a bit tricky (each process stores the already created synchronization handles in a header-only singleton implementation that stores the synchronization map into the current and max count of a named semaphore!). I also creates windows named resources (named mutexes, and semaphores) on the fly, I don't know if we'll hit some process or kernel related limits with this approach. If you and some Interprocess users can test it and give some feedback, we could make them default in a future Boost release, but this will create a binary incompatibility in windows systems so we must be sure this implementation is better than the old one. Before we break the ABI, we need to make sure performance is correct. Current implementation is suboptimal in many aspects (a hash and map lookup to obtain the handle of the primitive is overkill IMHO and performance might worse as the number of synchronization primitives grow). We maybe need to write a spinlock-based fast path and use named synchronization primitives in case of contention. I'm glad to hear it worked for you, but I can't guarantee the implementation is well tested and the ABI will surely change. Any feedaback you could give me it would be very valuable. Best, Ion

Which kind of problem? Spinlocks are quite simple so unless it's a performance-related issue, I can't imagine what can be wrong with spinlock-based mutexes.
The problems I was having was from performance. I had roughly 20 processes that would allocate some shared memory every 50ms or so. Periodically each process would slow to a crawl while the machine became sluggish. Looking at the problem in Process Explorer I saw each process was reporting ~1,500,000 context switches per second. (Normally ~100/sec) I attached a debugger and sure enough it stopped right in the shared memory allocator mutex. Once I switched to the new algorithm, I no longer see the massive spike in context switches. I did not notice any adverse effect to the execution speed. Though even if there was a small penalty I'd pay it to avoid the large spikes.
The implementation is not optimized, I had no time to test it thoroughly, and in some aspects it's a bit tricky (each process stores the already created synchronization handles in a header-only singleton implementation that stores the synchronization map into the current and max count of a named semaphore!). I also creates windows named resources (named mutexes, and semaphores) on the fly, I don't know if we'll hit some process or kernel related limits with this approach.
I'm not sure about other use cases, but in my application I don't use many mutexes in shared memory. It is mainly the allocation mutex that everyone uses and maybe 100-200 ones that are only used by 2-3 processes. I don't think that I will approach those limits, but I can't speak for others.
If you and some Interprocess users can test it and give some feedback, we could make them default in a future Boost release, but this will create a binary incompatibility in windows systems so we must be sure this implementation is better than the old one.
I was mostly curious if there were known problems. Because this has improved my behavior significantly I will probably continue to run on this implementation. I will be sure and post to the group if I run into any problems. I have control over all processes that are connecting to this shared memory and they all are released in lock-step at this point. I should be able to handle any future ABI changes without issue. Thanks for the response. Rob

We have been running the experimental Win32 mutex branch for about a month. Functionally it is still working fine. Performance is good enough for us at this point. We are not seeing any memory corruption due to faulty mutexes or anything. However, we are seeing some debug asserts pop up. I'm not 100% positive what causes it, but it seems that as we scale up our system we tend to get tripped up by the assert in boost\interprocess\sync\windows\mutex.hpp, Line 61. It appears that when we create the mutex, we are getting an "already exists" winapi error. Looking at the windows documentation this seems to be given if the mutex already exists, but the mutex is returned anyways. The commentary in the boost code indicates that it wants a mutex to be created and not opened, but I'm not sure why that is. Like I said above, we are not seeing adverse behavior because of this. But it is very annoying to run in debug mode with the assert windows popping up. Sometimes that can be a significant number of pop-ups. Any advice to offer? Hopefully this usage report helps. Rob Brink

El 11/12/2012 15:46, Brink, Robert (GE Aviation, US) escribió:
However, we are seeing some debug asserts pop up. I'm not 100% positive what causes it, but it seems that as we scale up our system we tend to get tripped up by the assert in boost\interprocess\sync\windows\mutex.hpp, Line 61. It appears that when we create the mutex, we are getting an "already exists" winapi error. Looking at the windows documentation this seems to be given if the mutex already exists, but the mutex is returned anyways. The commentary in the boost code indicates that it wants a mutex to be created and not opened, but I'm not sure why that is.
When the shared memory mutex constructor is called, a new named mutex is created with a unique name (based on a timestamp), so no other mutex should exist with that name. I see that in sync_utils.hpp's obtain_mutex() function popen_created is initialized to true when mutex is created or opened, but I think there's a bug as it's never assigned false when the mutex already exists. Maybe a previous garbage value can cause problems. Try to add else if(popen_created){ *popen_created = false; } to obtain_mutex() and obtain_semaphore() functions in ync_utils.hpp to see if it helps. Best, Ion
participants (3)
-
Brink, Robert (GE Aviation, US)
-
Ion Gaztañaga
-
Vicente J. Botet Escriba