|
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