$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r85401 - in trunk: boost/interprocess/detail boost/interprocess/sync boost/interprocess/sync/posix boost/interprocess/sync/spin libs/interprocess/test
From: igaztanaga_at_[hidden]
Date: 2013-08-20 04:47:17
Author: igaztanaga
Date: 2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)
New Revision: 85401
URL: http://svn.boost.org/trac/boost/changeset/85401
Log:
Fixes #9008
Added:
   trunk/boost/interprocess/detail/yield_k.hpp   (contents, props changed)
Text files modified: 
   trunk/boost/interprocess/detail/intermodule_singleton_common.hpp |     6 +                                       
   trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp  |     9 +                                       
   trunk/boost/interprocess/detail/os_thread_functions.hpp          |     3                                         
   trunk/boost/interprocess/detail/robust_emulation.hpp             |     5                                         
   trunk/boost/interprocess/detail/yield_k.hpp                      |   136 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/interprocess/sync/file_lock.hpp                      |     7 +                                       
   trunk/boost/interprocess/sync/posix/mutex.hpp                    |     3                                         
   trunk/boost/interprocess/sync/posix/recursive_mutex.hpp          |     4                                         
   trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp        |     3                                         
   trunk/boost/interprocess/sync/spin/condition.hpp                 |    12 +--                                     
   trunk/boost/interprocess/sync/spin/mutex.hpp                     |     6 +                                       
   trunk/boost/interprocess/sync/spin/semaphore.hpp                 |     6 +                                       
   trunk/libs/interprocess/test/robust_mutex_test.hpp               |     6 +                                       
   13 files changed, 177 insertions(+), 29 deletions(-)
Modified: trunk/boost/interprocess/detail/intermodule_singleton_common.hpp
==============================================================================
--- trunk/boost/interprocess/detail/intermodule_singleton_common.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/detail/intermodule_singleton_common.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -145,6 +145,7 @@
          //If previous state was initializing, this means that another winner thread is
          //trying to initialize the singleton. Just wait until completes its work.
          else if(previous_module_singleton_initialized == Initializing){
+            unsigned int k = 0;
             while(1){
                previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
                if(previous_module_singleton_initialized >= Initialized){
@@ -152,7 +153,7 @@
                   break;
                }
                else if(previous_module_singleton_initialized == Initializing){
-                  thread_yield();
+                  yield(k++);
                }
                else{
                   //This can't be happening!
@@ -206,6 +207,7 @@
    static void initialize_global_map_handle()
    {
       //Obtain unique map name and size
+      unsigned k = 0;
       while(1){
          //Try to pass map state to initializing
          ::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
@@ -218,7 +220,7 @@
          }
          //If some other thread is doing the work wait
          else if(tmp == Initializing){
-            thread_yield();
+            yield(k++);
          }
          else{ //(tmp == Uninitialized)
             //If not initialized try it again?
Modified: trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp
==============================================================================
--- trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -354,6 +354,7 @@
          //file and know if we have really created it or just open it
          //drop me a e-mail!
          bool completed = false;
+         unsigned k = 0;
          while(!completed){
             try{
                create_device<FileBased>(dev, id, size, perm, file_like_t());
@@ -384,7 +385,7 @@
             catch(...){
                throw;
             }
-            thread_yield();
+            yield(k++);
          }
       }
 
@@ -431,11 +432,12 @@
       else{
          if(FileBased){
             offset_t filesize = 0;
+            unsigned k = 0;
             while(filesize == 0){
                if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
                   throw interprocess_exception(error_info(system_error_code()));
                }
-               thread_yield();
+               yield(k++);
             }
             if(filesize == 1){
                throw interprocess_exception(error_info(corrupted_error));
@@ -447,8 +449,9 @@
          boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
          boost::uint32_t value = atomic_read32(patomic_word);
 
+         unsigned k = 0;
          while(value == InitializingSegment || value == UninitializedSegment){
-            thread_yield();
+            yield(k++);
             value = atomic_read32(patomic_word);
          }
 
Modified: trunk/boost/interprocess/detail/os_thread_functions.hpp
==============================================================================
--- trunk/boost/interprocess/detail/os_thread_functions.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/detail/os_thread_functions.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -15,8 +15,9 @@
 #include <boost/interprocess/detail/workaround.hpp>
 #include <boost/interprocess/streams/bufferstream.hpp>
 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
+#include <boost/interprocess/detail/yield_k.hpp>
 
-#if (defined BOOST_INTERPROCESS_WINDOWS)
+#if defined(BOOST_INTERPROCESS_WINDOWS)
 #  include <boost/interprocess/detail/win32_api.hpp>
 #else
 #  ifdef BOOST_HAS_UNISTD_H
Modified: trunk/boost/interprocess/detail/robust_emulation.hpp
==============================================================================
--- trunk/boost/interprocess/detail/robust_emulation.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/detail/robust_emulation.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -236,7 +236,7 @@
       }
       else{
          //Do the dead owner checking each spin_threshold lock tries
-         ipcdetail::thread_yield();
+         yield(spin_count);
          ++spin_count;
          if(spin_count > spin_threshold){
             //Check if owner dead and take ownership if possible
@@ -292,6 +292,7 @@
    if(now >= abs_time)
       return this->try_lock();
 
+   unsigned k = 0;
    do{
       if(this->try_lock()){
          break;
@@ -302,7 +303,7 @@
          return this->try_lock();
       }
       // relinquish current time slice
-      ipcdetail::thread_yield();
+      ipcdetail::yield(k++);
    }while (true);
 
    return true;
Added: trunk/boost/interprocess/detail/yield_k.hpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/boost/interprocess/detail/yield_k.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -0,0 +1,136 @@
+//This file was copied from boost/smart_ptr/detail and
+//modified here to avoid dependencies with that library
+#ifndef BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
+#define BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+//  yield_k.hpp
+//
+//  Copyright (c) 2008 Peter Dimov
+//
+//  void yield( unsigned k );
+//
+//  Typical use:
+//
+//  for( unsigned k = 0; !try_lock(); ++k ) yield( k );
+//
+//  Distributed under the Boost Software License, Version 1.0.
+//  See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+// BOOST_INTERPROCESS_SMT_PAUSE
+
+#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
+
+extern "C" void _mm_pause();
+#pragma intrinsic( _mm_pause )
+
+#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
+
+#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+
+#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
+
+#endif
+
+//
+
+#if defined (BOOST_INTERPROCESS_WINDOWS)
+
+#include <boost/interprocess/detail/win32_api.hpp>
+
+namespace boost
+{
+namespace interprocess
+{
+namespace ipcdetail
+{
+
+inline void yield( unsigned k )
+{
+   if( k < 4 )
+   {
+   }
+#if defined( BOOST_INTERPROCESS_SMT_PAUSE )
+   else if( k < 16 ){
+      BOOST_INTERPROCESS_SMT_PAUSE
+   }
+#endif
+   else if( k < 32 ){
+      //Try to yield to another thread running on the current processor
+      if(!winapi::SwitchToThread()){
+         //If not yield to any thread of same or higher priority on any processor
+         boost::interprocess::winapi::Sleep(0);
+      }
+   }
+   else{
+      //Yields to any thread on any processor
+      boost::interprocess::winapi::Sleep(1);
+   }
+}
+
+} // namespace ipcdetail
+} // namespace interprocess
+} // namespace boost
+
+#else
+
+#include <sched.h>
+#include <time.h>
+
+namespace boost
+{
+namespace interprocess
+{
+namespace ipcdetail
+{
+
+inline void yield( unsigned k )
+{
+    if( k < 4 )
+    {
+    }
+#if defined( BOOST_INTERPROCESS_SMT_PAUSE )
+    else if( k < 16 )
+    {
+        BOOST_INTERPROCESS_SMT_PAUSE
+    }
+#endif
+    else if( k < 32 || k & 1 )
+    {
+        sched_yield();
+    }
+    else
+    {
+        // g++ -Wextra warns on {} or {0}
+        struct timespec rqtp = { 0, 0 };
+
+        // POSIX says that timespec has tv_sec and tv_nsec
+        // But it doesn't guarantee order or placement
+
+        rqtp.tv_sec = 0;
+        rqtp.tv_nsec = 1000;
+
+        nanosleep( &rqtp, 0 );
+    }
+}
+
+} // namespace ipcdetail
+} // namespace interprocess
+} // namespace boost
+
+#endif
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
Modified: trunk/boost/interprocess/sync/file_lock.hpp
==============================================================================
--- trunk/boost/interprocess/sync/file_lock.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/file_lock.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -149,7 +149,7 @@
       using namespace boost::detail;
 
       if(now >= abs_time) return false;
-
+      unsigned k = 0;
       do{
          if(!ipcdetail::try_acquire_file_lock(hnd, acquired))
             return false;
@@ -164,7 +164,7 @@
                return true;
             }
             // relinquish current time slice
-            ipcdetail::thread_yield();
+            ipcdetail::yield(k++);
          }
       }while (true);
    }
@@ -178,6 +178,7 @@
 
       if(now >= abs_time) return false;
 
+      unsigned k = 0;
       do{
          if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired))
             return false;
@@ -192,7 +193,7 @@
                return true;
             }
             // relinquish current time slice
-            ipcdetail::thread_yield();
+            ipcdetail::yield(k++);
          }
       }while (true);
    }
Modified: trunk/boost/interprocess/sync/posix/mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/mutex.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/posix/mutex.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -119,6 +119,7 @@
    //Obtain current count and target time
    boost::posix_time::ptime now = microsec_clock::universal_time();
 
+   unsigned k = 0;
    do{
       if(this->try_lock()){
          break;
@@ -129,7 +130,7 @@
          return false;
       }
       // relinquish current time slice
-     thread_yield();
+      ipcdetail::yield(k++);
    }while (true);
    return true;
 
Modified: trunk/boost/interprocess/sync/posix/recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/recursive_mutex.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/posix/recursive_mutex.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -108,7 +108,7 @@
 
    //Obtain current count and target time
    boost::posix_time::ptime now = microsec_clock::universal_time();
-
+   unsigned k = 0;
    do{
       if(this->try_lock()){
          break;
@@ -119,7 +119,7 @@
          return false;
       }
       // relinquish current time slice
-     thread_yield();
+      yield(k++);
    }while (true);
    return true;
 
Modified: trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -195,10 +195,11 @@
    return false;
    #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
    boost::posix_time::ptime now;
+   unsigned k = 0;
    do{
       if(semaphore_try_wait(handle))
          return true;
-      thread_yield();
+      yield(k++);
    }while((now = microsec_clock::universal_time()) < abs_time);
    return false;
    #endif   //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
Modified: trunk/boost/interprocess/sync/spin/condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/spin/condition.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/spin/condition.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -140,15 +140,10 @@
    }
 
    //Notify that all threads should execute wait logic
+   unsigned k = 0;
    while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
-      thread_yield();
+      yield(k++);
    }
-/*
-   //Wait until the threads are woken
-   while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), 0)){
-      thread_yield();
-   }
-*/
    //The enter mutex will rest locked until the last waiting thread unlocks it
 }
 
@@ -211,8 +206,9 @@
    while(1){
       //The thread sleeps/spins until a spin_condition commands a notification
       //Notification occurred, we will lock the checking mutex so that
+      unsigned k = 0;
       while(atomic_read32(&m_command) == SLEEP){
-         thread_yield();
+         yield(k++);
 
          //Check for timeout
          if(tout_enabled){
Modified: trunk/boost/interprocess/sync/spin/mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/spin/mutex.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/spin/mutex.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -60,6 +60,7 @@
 
 inline void spin_mutex::lock(void)
 {
+   unsigned k = 0;
    do{
       boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
 
@@ -67,7 +68,7 @@
             break;
       }
       // relinquish current timeslice
-      ipcdetail::thread_yield();
+      ipcdetail::yield(k++);
    }while (true);
 }
 
@@ -86,6 +87,7 @@
    //Obtain current count and target time
    boost::posix_time::ptime now = microsec_clock::universal_time();
 
+   unsigned k = 0;
    do{
       if(this->try_lock()){
          break;
@@ -96,7 +98,7 @@
          return false;
       }
       // relinquish current time slice
-     ipcdetail::thread_yield();
+      ipcdetail::yield(k++);
    }while (true);
 
    return true;
Modified: trunk/boost/interprocess/sync/spin/semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/spin/semaphore.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/boost/interprocess/sync/spin/semaphore.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -59,9 +59,10 @@
 
 inline void spin_semaphore::wait()
 {
+   unsigned k = 0;
    while(!ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0))){
       while(ipcdetail::atomic_read32(&m_count) == 0){
-         ipcdetail::thread_yield();
+         ipcdetail::yield(k++);
       }
    }
 }
@@ -80,6 +81,7 @@
    //Obtain current count and target time
    boost::posix_time::ptime now(microsec_clock::universal_time());
 
+   unsigned k = 0;
    do{
       if(this->try_wait()){
          break;
@@ -90,7 +92,7 @@
          return this->try_wait();
       }
       // relinquish current time slice
-      ipcdetail::thread_yield();
+      ipcdetail::yield(k++);
    }while (true);
    return true;
 }
Modified: trunk/libs/interprocess/test/robust_mutex_test.hpp
==============================================================================
--- trunk/libs/interprocess/test/robust_mutex_test.hpp	Tue Aug 20 02:06:12 2013	(r85400)
+++ trunk/libs/interprocess/test/robust_mutex_test.hpp	2013-08-20 04:47:17 EDT (Tue, 20 Aug 2013)	(r85401)
@@ -66,8 +66,9 @@
          return 1;
 
       //Wait until child locks the mutexes and dies
+      unsigned k = 0;
       while(!*go_ahead){
-         ipcdetail::thread_yield();
+         ipcdetail::yield(k++);
       }
 
       std::cout << "... recovering mutex[0]" << std::endl;
@@ -163,8 +164,9 @@
          }
 
          //Wait until child locks the 2nd mutex and dies
+         unsigned k = 0;
          while(!*go_ahead2){
-            ipcdetail::thread_yield();
+            ipcdetail::yield(k++);
          }
 
          //Done, now try to lock number 3 to see if robust