mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
@@ -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?
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
136
include/boost/interprocess/detail/yield_k.hpp
Normal file
136
include/boost/interprocess/detail/yield_k.hpp
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user