Boost logo

Boost-Commit :

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


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk