[SVN r85401]
This commit is contained in:
Ion Gaztañaga
2013-08-20 08:47:17 +00:00
parent d0df5089d3
commit 856d0d3f41
13 changed files with 177 additions and 29 deletions

View File

@@ -145,6 +145,7 @@ class intermodule_singleton_common
//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 @@ class intermodule_singleton_common
break;
}
else if(previous_module_singleton_initialized == Initializing){
thread_yield();
yield(k++);
}
else{
//This can't be happening!
@@ -206,6 +207,7 @@ class intermodule_singleton_common
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 @@ class intermodule_singleton_common
}
//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?

View File

@@ -354,6 +354,7 @@ class managed_open_or_create_impl
//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 @@ class managed_open_or_create_impl
catch(...){
throw;
}
thread_yield();
yield(k++);
}
}
@@ -431,11 +432,12 @@ class managed_open_or_create_impl
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 @@ class managed_open_or_create_impl
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);
}

View File

@@ -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

View File

@@ -236,7 +236,7 @@ inline void robust_spin_mutex<Mutex>::lock()
}
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 @@ inline bool robust_spin_mutex<Mutex>::timed_lock
if(now >= abs_time)
return this->try_lock();
unsigned k = 0;
do{
if(this->try_lock()){
break;
@@ -302,7 +303,7 @@ inline bool robust_spin_mutex<Mutex>::timed_lock
return this->try_lock();
}
// relinquish current time slice
ipcdetail::thread_yield();
ipcdetail::yield(k++);
}while (true);
return true;

View File

@@ -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

View File

@@ -149,7 +149,7 @@ class file_lock
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 @@ class file_lock
return true;
}
// relinquish current time slice
ipcdetail::thread_yield();
ipcdetail::yield(k++);
}
}while (true);
}
@@ -178,6 +178,7 @@ class file_lock
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 @@ class file_lock
return true;
}
// relinquish current time slice
ipcdetail::thread_yield();
ipcdetail::yield(k++);
}
}while (true);
}

View File

@@ -119,6 +119,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
//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 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
return false;
}
// relinquish current time slice
thread_yield();
ipcdetail::yield(k++);
}while (true);
return true;

View File

@@ -108,7 +108,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
//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 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
return false;
}
// relinquish current time slice
thread_yield();
yield(k++);
}while (true);
return true;

View File

@@ -195,10 +195,11 @@ inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &
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

View File

@@ -140,15 +140,10 @@ inline void spin_condition::notify(boost::uint32_t command)
}
//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 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled,
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){

View File

@@ -60,6 +60,7 @@ inline spin_mutex::~spin_mutex()
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 @@ inline void spin_mutex::lock(void)
break;
}
// relinquish current timeslice
ipcdetail::thread_yield();
ipcdetail::yield(k++);
}while (true);
}
@@ -86,6 +87,7 @@ inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
//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 @@ inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
return false;
}
// relinquish current time slice
ipcdetail::thread_yield();
ipcdetail::yield(k++);
}while (true);
return true;

View File

@@ -59,9 +59,10 @@ inline void spin_semaphore::post()
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 @@ inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
//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 @@ inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
return this->try_wait();
}
// relinquish current time slice
ipcdetail::thread_yield();
ipcdetail::yield(k++);
}while (true);
return true;
}

View File

@@ -66,8 +66,9 @@ int robust_mutex_test(int argc, char *argv[])
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 @@ int robust_mutex_test(int argc, char *argv[])
}
//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