[interprocess] (OS X) waiting on condition variable = CPU 100% + fans running loud

Hi, I was implementing a kind of server using shared memory. The server should keep idle, waiting for a request and I do this by waiting on a condition variable, of course. I then noticed my fans running high when I let the server waiting a little longer while testing and discovered this happens simply because of some busy loop implementation for condition waiting. Is there any reason for that? Given the interprocess library age, there's no way for implementing a non-busy interprocess condition variable waiting available? https://svn.boost.org/trac/boost/ticket/6108 Regards, Francisco Lopes

hi,
Hi, I was implementing a kind of server using shared memory. The server should keep idle, waiting for a request and I do this by waiting on a condition variable, of course.
I then noticed my fans running high when I let the server waiting a little longer while testing and discovered this happens simply because of some busy loop implementation for condition waiting.
Is there any reason for that?
Given the interprocess library age, there's no way for implementing a non-busy interprocess condition variable waiting available?
not sure if it is related, but it somehow reminds me of an issue that unnamed semaphores are not implemented on osx ... compare [1] tim [1] http://heldercorreia.com/blog/semaphores-in-mac-os-x

El 05/01/2013 17:34, Francisco Lopes escribió:
Hi, I was implementing a kind of server using shared memory. The server should keep idle, waiting for a request and I do this by waiting on a condition variable, of course.
I then noticed my fans running high when I let the server waiting a little longer while testing and discovered this happens simply because of some busy loop implementation for condition waiting.
Is there any reason for that? Given the interprocess library age, no way for implementing a non-busy interprocess condition variable waiting is available?
MacOS does not support POSIX process-shared synchronization primitives and it's pretty hard to emulate them without kernel help (I think it's the only "major" modern UNIX OS without that support). I haven't found any library that tries to emulate them on MacOs to get some ideas about the emulation. We have a similar problem in Windows, and there is a very early emulation that avoids spinning but it's still too buggy to be the default. Sadly this emulation idea does not work with MacOs due to differences in named synchronization mechanism lifetimes between windows and mac operating systems. It's maybe the biggest problem we have with Interprocess, sorry about that. Maybe you can avoid 100% CPU usage inserting sleeps between atomic operation tries in interprocess_mutex or interprocess_condition code. Sorry about the bad news. Ion
Eesponded by the library mantainer on boost-users, sad. 2013/1/6 Tim Blechmann <tim@klingt.org>
hi,
Hi, I was implementing a kind of server using shared memory. The server should keep idle, waiting for a request and I do this by waiting on a condition variable, of course.
I then noticed my fans running high when I let the server waiting a little longer while testing and discovered this happens simply because of some busy loop implementation for condition waiting.
Is there any reason for that?
Given the interprocess library age, there's no way for implementing a non-busy interprocess condition variable waiting available?
not sure if it is related, but it somehow reminds me of an issue that unnamed semaphores are not implemented on osx ... compare [1]
tim

It's maybe the biggest problem we have with Interprocess, sorry about that. Maybe you can avoid 100% CPU usage inserting sleeps between atomic operation tries in interprocess_mutex or interprocess_condition code. Sorry about the bad news. Ion
There's yield_k in <boost/smart_ptr/detail/yield_k.hpp> that could be useful here.

El 06/01/2013 16:52, Peter Dimov escribió:
It's maybe the biggest problem we have with Interprocess, sorry about that. Maybe you can avoid 100% CPU usage inserting sleeps between atomic operation tries in interprocess_mutex or interprocess_condition code. > Sorry about the bad news. Ion
There's yield_k in <boost/smart_ptr/detail/yield_k.hpp> that could be useful here.
Peter, very interesting, thanks for the hint, I'll add a ticket to avoid missing it. There are quite a few gems hidden under smart_ptr: very interesting the implementation of spinlock_xxx.hpp primitives, I'm not a threading expert but I guess these are more efficient that current full barrier atomic compare-exchange based interprocess primitives. Any chance to move those into boost/detail directory? These seem useful outside smart_ptr (just like lightweight_mutex.hpp, interlocked.hpp, etc.) Best, Ion

Ion Gaztañaga wrote:
Peter, very interesting, thanks for the hint, I'll add a ticket to avoid missing it. There are quite a few gems hidden under smart_ptr: very interesting the implementation of spinlock_xxx.hpp primitives, I'm not a threading expert but I guess these are more efficient that current full barrier atomic compare-exchange based interprocess primitives.
Any chance to move those into boost/detail directory? These seem useful outside smart_ptr (just like lightweight_mutex.hpp, interlocked.hpp, etc.)
These were in boost/detail at first, but I moved them into smart_ptr/detail so that it's clear to which library they belong; given that we'll be moving to separate repositories, this was obviously a good idea. :-) For the spinlocks, the way forward is to use std::atomic_flag, and much of the other stuff is also obsoleted by the C++11 atomics. Unfortunately, I was unable to get yield(k) into the standard.

El 06/01/2013 23:59, Peter Dimov escribió:
These were in boost/detail at first, but I moved them into smart_ptr/detail so that it's clear to which library they belong; given that we'll be moving to separate repositories, this was obviously a good idea. :-)
Ok, thanks.
For the spinlocks, the way forward is to use std::atomic_flag, and much of the other stuff is also obsoleted by the C++11 atomics. Unfortunately, I was unable to get yield(k) into the standard.
[CCing Tim duet to Boost.Atomic/Lockfree mention] We need to be compatible with C++03 compilers so I guess maybe Boost.Atomic/Boost.Lockfree might be a good candidates for these utilities. Best, Ion

For the spinlocks, the way forward is to use std::atomic_flag, and much of the other stuff is also obsoleted by the C++11 atomics. Unfortunately, I was unable to get yield(k) into the standard. [CCing Tim duet to Boost.Atomic/Lockfree mention]
We need to be compatible with C++03 compilers so I guess maybe Boost.Atomic/Boost.Lockfree might be a good candidates for these utilities.
i think it is a good idea to use boost/std atomics. smart_ptr has support for much more architectures, though ... it would be best to integrate all that architectures into boost.atomic ... cheers, tim

El 08/01/2013 14:38, Tim Blechmann escribió:
For the spinlocks, the way forward is to use std::atomic_flag, and much of the other stuff is also obsoleted by the C++11 atomics. Unfortunately, I was unable to get yield(k) into the standard. [CCing Tim duet to Boost.Atomic/Lockfree mention]
We need to be compatible with C++03 compilers so I guess maybe Boost.Atomic/Boost.Lockfree might be a good candidates for these utilities.
i think it is a good idea to use boost/std atomics. smart_ptr has support for much more architectures, though ... it would be best to integrate all that architectures into boost.atomic ...
Is there any plan to improve Boost.Atomic portability? I guess we have enough atomic experts in Boost but maybe we'll need to make some "call for experts" to support more architectures. I read from Boost.Atomic documentation that supported platforms are: - gcc 4.x: i386, x86_64, ppc32, ppc64, armv5, armv6, alpha - Visual Studio Express 2008/Windows XP, i386 That seems a bit limited unless under "GCC" we have several compilers compatible with GCC and MSVC (maybe Intel, Clang, Freescale? etc.). Maybe some Summer of code projects could help here. Ion

On Tue, Jan 8, 2013 at 7:50 PM, Ion Gaztañaga <igaztanaga@gmail.com> wrote:
I read from Boost.Atomic documentation that supported platforms are:
- gcc 4.x: i386, x86_64, ppc32, ppc64, armv5, armv6, alpha
- Visual Studio Express 2008/Windows XP, i386
That seems a bit limited unless under "GCC" we have several compilers compatible with GCC and MSVC (maybe Intel, Clang, Freescale? etc.).
In case of gcc inline assembler is used, which is also supported by Intel but not clang. On Windows compiler intrinsics or WinAPI are used. I believe Intel supports MSVC intrinsics on Windows. I'm not sure what solution is suitable for clang as I don't know if it supports any intrinsics and apparently it won't support inline assembler any time soon.

Andrey Semashev wrote:
On Tue, Jan 8, 2013 at 7:50 PM, Ion Gaztañaga <igaztanaga@gmail.com> wrote:
I read from Boost.Atomic documentation that supported platforms are:
- gcc 4.x: i386, x86_64, ppc32, ppc64, armv5, armv6, alpha
- Visual Studio Express 2008/Windows XP, i386
That seems a bit limited unless under "GCC" we have several compilers compatible with GCC and MSVC (maybe Intel, Clang, Freescale? etc.).
In case of gcc inline assembler is used, which is also supported by Intel but not clang. On Windows compiler intrinsics or WinAPI are used. I believe Intel supports MSVC intrinsics on Windows. I'm not sure what solution is suitable for clang as I don't know if it supports any intrinsics and apparently it won't support inline assembler any time soon.
Clang has std::atomic though, doesn't it? It probably supports the __sync intrinsics as well.

hi peter,
Clang has std::atomic though, doesn't it?
probably not unless you enable c++11. clang/c++11/osx does not work on 10.6 (it does not ship a c++11 compliant standard library) and clang/c++11/linux doesn't have a working std::thread implementation.
Actually, it seems to support the even better __atomic intrinsics:
http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
again, this requires gcc-4.7 ... what about people who are stuck at an older compiler? apple/gcc is probably still shipping 4.2, which does not even implement __sync primitives in a portable manner ... of course, if the compiler implements std::atomic, there is absolutely no need for boost::atomic in the first place ... the whole point is to provide a compatibility layer to provide c++11-style atomics for old compilers, that don't support c++11 atomics ... which, btw is one of the reason why the original author decided to use inline assembly instead of compiler intrinsics tim

El 08/01/2013 17:32, Tim Blechmann escribió:
of course, if the compiler implements std::atomic, there is absolutely no need for boost::atomic in the first place ... the whole point is to provide a compatibility layer to provide c++11-style atomics for old compilers, that don't support c++11 atomics ... which, btw is one of the reason why the original author decided to use inline assembly instead of compiler intrinsics
I have no experience on assembler coding, but porting assembler code from one compiler to another on the same architecture is hard? Looking at boost/smart_ptr/detail/sp_counted_base_xxx.hpp I see that gcc x86 code for atomic_exchange_and_add is: // int r = *pw; // *pw += dv; // return r; __asm__ __volatile__ ( "lock\n\t" "xadd %1, %0": "=m"( *pw ), "=r"( r ): // outputs (%0, %1) "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1) "memory", "cc" // clobbers ); whereas codewarrior code looks like this: // int r = *pw; // *pw += dv; // return r; asm { mov esi, [pw] mov eax, dv lock xadd dword ptr [esi], eax } Obviously we have "lock" and "xadd" on both cases but we have a lot of additional stuff in the gcc case. If porting between compilers in the same architecture is not very hard, Boost.Atomic already supports most widely used architectures (i386, x86_64, ppc32, ppc64, armv5, armv6, armv7, alpha), then support for more compilers wouldn't be hard to add. On the other hard, if we need to write a very different assembler in each compiler, the work will be much harder. Best, Ion

I read from Boost.Atomic documentation that supported platforms are:
- gcc 4.x: i386, x86_64, ppc32, ppc64, armv5, armv6, alpha
- Visual Studio Express 2008/Windows XP, i386
That seems a bit limited unless under "GCC" we have several compilers compatible with GCC and MSVC (maybe Intel, Clang, Freescale? etc.).
In case of gcc inline assembler is used, which is also supported by Intel but not clang. On Windows compiler intrinsics or WinAPI are used. I believe Intel supports MSVC intrinsics on Windows. I'm not sure what solution is suitable for clang as I don't know if it supports any intrinsics and apparently it won't support inline assembler any time soon.
it might be possible to get support for more platforms by supporting gcc(>=4.4)-style __sync builtins (iirc they are also supported by clang and intel) ... though clang seems to have an own set of atomic builtins (__c11_atomic_XXX) i'd very much appreciate if some platform experts would add support for their favorite platforms ... tim

Andrey Semashev <andrey.semashev@gmail.com> wrote:
On Tue, Jan 8, 2013 at 7:50 PM, Ion Gazta?aga <igaztanaga@gmail.com> wrote:
I read from Boost.Atomic documentation that supported platforms are:
- gcc 4.x: i386, x86_64, ppc32, ppc64, armv5, armv6, alpha
ARMv7 is also supported.
- Visual Studio Express 2008/Windows XP, i386
That seems a bit limited unless under "GCC" we have several compilers compatible with GCC and MSVC (maybe Intel, Clang, Freescale? etc.).
In case of gcc inline assembler is used, which is also supported by Intel but not clang.
I'm not sure what solution is suitable for clang as I don't know if it supports any intrinsics and apparently it won't support inline assembler any time soon.
It seems to me that clang does support gcc inline assembler; I'm using Boost.Atomic on iOS, and also shared_ptr<> on top of Boost.Atomic, and it works as expected. Why do you believe that clang doesn't support inline assembler? Phil.

On Tue, Jan 8, 2013 at 10:15 PM, Phil Endecott <spam_from_boost_dev@chezphil.org> wrote:
In case of gcc inline assembler is used, which is also supported by Intel but not clang.
I'm not sure what solution is suitable for clang as I don't know if it supports any intrinsics and apparently it won't support inline assembler any time soon.
It seems to me that clang does support gcc inline assembler; I'm using Boost.Atomic on iOS, and also shared_ptr<> on top of Boost.Atomic, and it works as expected. Why do you believe that clang doesn't support inline assembler?
Hmm, that's (good) news to me. I was under impression it doesn't support inline assembler. Do you know in what version the support was added?
participants (6)
-
Andrey Semashev
-
Francisco Lopes
-
Ion Gaztañaga
-
Peter Dimov
-
Phil Endecott
-
Tim Blechmann