Skip to content

Commit 856d0d3

Browse files
committed
Fixes #9008
[SVN r85401]
1 parent d0df508 commit 856d0d3

File tree

13 files changed

+177
-29
lines changed

13 files changed

+177
-29
lines changed

include/boost/interprocess/detail/intermodule_singleton_common.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,15 @@ class intermodule_singleton_common
145145
//If previous state was initializing, this means that another winner thread is
146146
//trying to initialize the singleton. Just wait until completes its work.
147147
else if(previous_module_singleton_initialized == Initializing){
148+
unsigned int k = 0;
148149
while(1){
149150
previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
150151
if(previous_module_singleton_initialized >= Initialized){
151152
//Already initialized, or exception thrown by initializer thread
152153
break;
153154
}
154155
else if(previous_module_singleton_initialized == Initializing){
155-
thread_yield();
156+
yield(k++);
156157
}
157158
else{
158159
//This can't be happening!
@@ -206,6 +207,7 @@ class intermodule_singleton_common
206207
static void initialize_global_map_handle()
207208
{
208209
//Obtain unique map name and size
210+
unsigned k = 0;
209211
while(1){
210212
//Try to pass map state to initializing
211213
::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
@@ -218,7 +220,7 @@ class intermodule_singleton_common
218220
}
219221
//If some other thread is doing the work wait
220222
else if(tmp == Initializing){
221-
thread_yield();
223+
yield(k++);
222224
}
223225
else{ //(tmp == Uninitialized)
224226
//If not initialized try it again?

include/boost/interprocess/detail/managed_open_or_create_impl.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ class managed_open_or_create_impl
354354
//file and know if we have really created it or just open it
355355
//drop me a e-mail!
356356
bool completed = false;
357+
unsigned k = 0;
357358
while(!completed){
358359
try{
359360
create_device<FileBased>(dev, id, size, perm, file_like_t());
@@ -384,7 +385,7 @@ class managed_open_or_create_impl
384385
catch(...){
385386
throw;
386387
}
387-
thread_yield();
388+
yield(k++);
388389
}
389390
}
390391

@@ -431,11 +432,12 @@ class managed_open_or_create_impl
431432
else{
432433
if(FileBased){
433434
offset_t filesize = 0;
435+
unsigned k = 0;
434436
while(filesize == 0){
435437
if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
436438
throw interprocess_exception(error_info(system_error_code()));
437439
}
438-
thread_yield();
440+
yield(k++);
439441
}
440442
if(filesize == 1){
441443
throw interprocess_exception(error_info(corrupted_error));
@@ -447,8 +449,9 @@ class managed_open_or_create_impl
447449
boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
448450
boost::uint32_t value = atomic_read32(patomic_word);
449451

452+
unsigned k = 0;
450453
while(value == InitializingSegment || value == UninitializedSegment){
451-
thread_yield();
454+
yield(k++);
452455
value = atomic_read32(patomic_word);
453456
}
454457

include/boost/interprocess/detail/os_thread_functions.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
#include <boost/interprocess/detail/workaround.hpp>
1616
#include <boost/interprocess/streams/bufferstream.hpp>
1717
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
18+
#include <boost/interprocess/detail/yield_k.hpp>
1819

19-
#if (defined BOOST_INTERPROCESS_WINDOWS)
20+
#if defined(BOOST_INTERPROCESS_WINDOWS)
2021
# include <boost/interprocess/detail/win32_api.hpp>
2122
#else
2223
# ifdef BOOST_HAS_UNISTD_H

include/boost/interprocess/detail/robust_emulation.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ inline void robust_spin_mutex<Mutex>::lock()
236236
}
237237
else{
238238
//Do the dead owner checking each spin_threshold lock tries
239-
ipcdetail::thread_yield();
239+
yield(spin_count);
240240
++spin_count;
241241
if(spin_count > spin_threshold){
242242
//Check if owner dead and take ownership if possible
@@ -292,6 +292,7 @@ inline bool robust_spin_mutex<Mutex>::timed_lock
292292
if(now >= abs_time)
293293
return this->try_lock();
294294

295+
unsigned k = 0;
295296
do{
296297
if(this->try_lock()){
297298
break;
@@ -302,7 +303,7 @@ inline bool robust_spin_mutex<Mutex>::timed_lock
302303
return this->try_lock();
303304
}
304305
// relinquish current time slice
305-
ipcdetail::thread_yield();
306+
ipcdetail::yield(k++);
306307
}while (true);
307308

308309
return true;
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//This file was copied from boost/smart_ptr/detail and
2+
//modified here to avoid dependencies with that library
3+
#ifndef BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
4+
#define BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
5+
6+
// MS compatible compilers support #pragma once
7+
8+
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
9+
# pragma once
10+
#endif
11+
12+
//
13+
// yield_k.hpp
14+
//
15+
// Copyright (c) 2008 Peter Dimov
16+
//
17+
// void yield( unsigned k );
18+
//
19+
// Typical use:
20+
//
21+
// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
22+
//
23+
// Distributed under the Boost Software License, Version 1.0.
24+
// See accompanying file LICENSE_1_0.txt or copy at
25+
// http://www.boost.org/LICENSE_1_0.txt
26+
//
27+
28+
#include <boost/interprocess/detail/config_begin.hpp>
29+
#include <boost/interprocess/detail/workaround.hpp>
30+
31+
// BOOST_INTERPROCESS_SMT_PAUSE
32+
33+
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
34+
35+
extern "C" void _mm_pause();
36+
#pragma intrinsic( _mm_pause )
37+
38+
#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
39+
40+
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
41+
42+
#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
43+
44+
#endif
45+
46+
//
47+
48+
#if defined (BOOST_INTERPROCESS_WINDOWS)
49+
50+
#include <boost/interprocess/detail/win32_api.hpp>
51+
52+
namespace boost
53+
{
54+
namespace interprocess
55+
{
56+
namespace ipcdetail
57+
{
58+
59+
inline void yield( unsigned k )
60+
{
61+
if( k < 4 )
62+
{
63+
}
64+
#if defined( BOOST_INTERPROCESS_SMT_PAUSE )
65+
else if( k < 16 ){
66+
BOOST_INTERPROCESS_SMT_PAUSE
67+
}
68+
#endif
69+
else if( k < 32 ){
70+
//Try to yield to another thread running on the current processor
71+
if(!winapi::SwitchToThread()){
72+
//If not yield to any thread of same or higher priority on any processor
73+
boost::interprocess::winapi::Sleep(0);
74+
}
75+
}
76+
else{
77+
//Yields to any thread on any processor
78+
boost::interprocess::winapi::Sleep(1);
79+
}
80+
}
81+
82+
} // namespace ipcdetail
83+
} // namespace interprocess
84+
} // namespace boost
85+
86+
#else
87+
88+
#include <sched.h>
89+
#include <time.h>
90+
91+
namespace boost
92+
{
93+
namespace interprocess
94+
{
95+
namespace ipcdetail
96+
{
97+
98+
inline void yield( unsigned k )
99+
{
100+
if( k < 4 )
101+
{
102+
}
103+
#if defined( BOOST_INTERPROCESS_SMT_PAUSE )
104+
else if( k < 16 )
105+
{
106+
BOOST_INTERPROCESS_SMT_PAUSE
107+
}
108+
#endif
109+
else if( k < 32 || k & 1 )
110+
{
111+
sched_yield();
112+
}
113+
else
114+
{
115+
// g++ -Wextra warns on {} or {0}
116+
struct timespec rqtp = { 0, 0 };
117+
118+
// POSIX says that timespec has tv_sec and tv_nsec
119+
// But it doesn't guarantee order or placement
120+
121+
rqtp.tv_sec = 0;
122+
rqtp.tv_nsec = 1000;
123+
124+
nanosleep( &rqtp, 0 );
125+
}
126+
}
127+
128+
} // namespace ipcdetail
129+
} // namespace interprocess
130+
} // namespace boost
131+
132+
#endif
133+
134+
#include <boost/interprocess/detail/config_end.hpp>
135+
136+
#endif // #ifndef BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED

include/boost/interprocess/sync/file_lock.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class file_lock
149149
using namespace boost::detail;
150150

151151
if(now >= abs_time) return false;
152-
152+
unsigned k = 0;
153153
do{
154154
if(!ipcdetail::try_acquire_file_lock(hnd, acquired))
155155
return false;
@@ -164,7 +164,7 @@ class file_lock
164164
return true;
165165
}
166166
// relinquish current time slice
167-
ipcdetail::thread_yield();
167+
ipcdetail::yield(k++);
168168
}
169169
}while (true);
170170
}
@@ -178,6 +178,7 @@ class file_lock
178178

179179
if(now >= abs_time) return false;
180180

181+
unsigned k = 0;
181182
do{
182183
if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired))
183184
return false;
@@ -192,7 +193,7 @@ class file_lock
192193
return true;
193194
}
194195
// relinquish current time slice
195-
ipcdetail::thread_yield();
196+
ipcdetail::yield(k++);
196197
}
197198
}while (true);
198199
}

include/boost/interprocess/sync/posix/mutex.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
119119
//Obtain current count and target time
120120
boost::posix_time::ptime now = microsec_clock::universal_time();
121121

122+
unsigned k = 0;
122123
do{
123124
if(this->try_lock()){
124125
break;
@@ -129,7 +130,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
129130
return false;
130131
}
131132
// relinquish current time slice
132-
thread_yield();
133+
ipcdetail::yield(k++);
133134
}while (true);
134135
return true;
135136

include/boost/interprocess/sync/posix/recursive_mutex.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
108108

109109
//Obtain current count and target time
110110
boost::posix_time::ptime now = microsec_clock::universal_time();
111-
111+
unsigned k = 0;
112112
do{
113113
if(this->try_lock()){
114114
break;
@@ -119,7 +119,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
119119
return false;
120120
}
121121
// relinquish current time slice
122-
thread_yield();
122+
yield(k++);
123123
}while (true);
124124
return true;
125125

include/boost/interprocess/sync/posix/semaphore_wrapper.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,11 @@ inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &
195195
return false;
196196
#else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
197197
boost::posix_time::ptime now;
198+
unsigned k = 0;
198199
do{
199200
if(semaphore_try_wait(handle))
200201
return true;
201-
thread_yield();
202+
yield(k++);
202203
}while((now = microsec_clock::universal_time()) < abs_time);
203204
return false;
204205
#endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS

include/boost/interprocess/sync/spin/condition.hpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,10 @@ inline void spin_condition::notify(boost::uint32_t command)
140140
}
141141

142142
//Notify that all threads should execute wait logic
143+
unsigned k = 0;
143144
while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
144-
thread_yield();
145+
yield(k++);
145146
}
146-
/*
147-
//Wait until the threads are woken
148-
while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), 0)){
149-
thread_yield();
150-
}
151-
*/
152147
//The enter mutex will rest locked until the last waiting thread unlocks it
153148
}
154149

@@ -211,8 +206,9 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled,
211206
while(1){
212207
//The thread sleeps/spins until a spin_condition commands a notification
213208
//Notification occurred, we will lock the checking mutex so that
209+
unsigned k = 0;
214210
while(atomic_read32(&m_command) == SLEEP){
215-
thread_yield();
211+
yield(k++);
216212

217213
//Check for timeout
218214
if(tout_enabled){

0 commit comments

Comments
 (0)