Skip to content

Commit 0df6182

Browse files
committed
- Add OS-native functions to obatin sistemwide thread IDs
- Rework OS_systemwide_thread_id_t to be portable between different native implementation and old emulation code
1 parent f656e80 commit 0df6182

File tree

2 files changed

+153
-95
lines changed

2 files changed

+153
-95
lines changed

include/boost/interprocess/detail/os_thread_functions.hpp

Lines changed: 131 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,32 @@
4545
# include <sched.h>
4646
# include <time.h>
4747
# include <errno.h>
48+
# include <sys/types.h>
4849
# ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
4950
//Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
5051
//others (FreeBSD & Darwin) need sys/types.h
51-
# include <sys/types.h>
5252
# include <sys/param.h>
5353
# include <sys/sysctl.h>
5454
# endif
5555
#if defined(__VXWORKS__)
5656
#include <vxCpuLib.h>
5757
#endif
58+
59+
#if defined(__linux__)
60+
#include <sys/syscall.h>
61+
#elif defined(__FreeBSD__)
62+
#include <pthread_np.h>
63+
#elif defined(__APPLE__)
64+
#include <pthread.h>
65+
#elif defined(__NetBSD__)
66+
#include <lwp.h>
67+
#elif defined(__OpenBSD__)
68+
#include <unistd.h>
69+
#elif defined(__sun) && defined(__SVR4)
70+
#include <thread.h>
71+
#endif
72+
73+
5874
//According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
5975
//Check MacOs first as macOS 10.12 SDK defines both CLOCK_MONOTONIC and
6076
//CLOCK_MONOTONIC_RAW and no clock_gettime.
@@ -95,8 +111,6 @@ struct OS_thread_t
95111
void* m_handle;
96112
};
97113

98-
typedef OS_thread_id_t OS_systemwide_thread_id_t;
99-
100114
//process
101115
inline OS_process_id_t get_current_process_id()
102116
{ return winapi::get_current_process_id(); }
@@ -198,26 +212,32 @@ inline void thread_yield()
198212
inline void thread_sleep_ms(unsigned int ms)
199213
{ winapi::sleep(ms); }
200214

201-
//systemwide thread
202-
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
203-
{
204-
return get_current_thread_id();
205-
}
206215

207-
inline void systemwide_thread_id_copy
208-
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
216+
class OS_systemwide_thread_id_t
209217
{
210-
to = from;
211-
}
218+
OS_thread_id_t m_thrhnd;
219+
220+
public:
221+
explicit OS_systemwide_thread_id_t(OS_thread_id_t thid)
222+
: m_thrhnd(thid)
223+
{}
224+
225+
OS_systemwide_thread_id_t()
226+
: m_thrhnd(get_invalid_thread_id())
227+
{}
212228

213-
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
229+
friend bool operator == (const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
230+
{ return id1.m_thrhnd == id2.m_thrhnd; }
231+
};
232+
233+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
214234
{
215-
return equal_thread_id(id1, id2);
235+
return OS_systemwide_thread_id_t(get_current_thread_id());
216236
}
217237

218238
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
219239
{
220-
return get_invalid_thread_id();
240+
return OS_systemwide_thread_id_t(get_invalid_thread_id());
221241
}
222242

223243
inline unsigned long long get_current_process_creation_time()
@@ -248,8 +268,95 @@ typedef pthread_t OS_thread_t;
248268
typedef pthread_t OS_thread_id_t;
249269
typedef pid_t OS_process_id_t;
250270

251-
struct OS_systemwide_thread_id_t
271+
//process
272+
inline OS_process_id_t get_current_process_id()
273+
{ return ::getpid(); }
274+
275+
inline OS_process_id_t get_invalid_process_id()
276+
{ return pid_t(0); }
277+
278+
//thread
279+
inline OS_thread_id_t get_current_thread_id()
280+
{ return ::pthread_self(); }
281+
282+
inline OS_thread_id_t get_invalid_thread_id()
283+
{
284+
static pthread_t invalid_id;
285+
return invalid_id;
286+
}
287+
288+
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
289+
{ return 0 != pthread_equal(id1, id2); }
290+
291+
292+
#if defined(__linux__)
293+
294+
typedef pid_t OS_systemwide_thread_id_t;
295+
296+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
297+
{ return (pid_t)syscall(SYS_gettid); }
298+
299+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
300+
{ return (pid_t)(-1); }
301+
302+
#elif defined(__FreeBSD__)
303+
304+
typedef int OS_systemwide_thread_id_t;
305+
306+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
307+
{ return pthread_getthreadid_np(); }
308+
309+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
310+
{ return -1; }
311+
312+
#elif defined(__APPLE__)
313+
314+
typedef uint64_t OS_systemwide_thread_id_t;
315+
316+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
317+
{ uint64_t tid; pthread_threadid_np(NULL, &tid); return tid; }
318+
319+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
320+
{ return (uint64_t)(-1); }
321+
322+
#elif defined(__NetBSD__)
323+
324+
typedef lwpid_t OS_systemwide_thread_id_t;
325+
326+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
327+
{ return _lwp_self(); }
328+
329+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
330+
{ return (lwpid_t)(-1); }
331+
332+
#elif defined(__OpenBSD__)
333+
334+
typedef pid_t OS_systemwide_thread_id_t;
335+
336+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
337+
{ return getthrid(); }
338+
339+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
340+
{ return (pid_t)(-1); }
341+
342+
#elif defined(__sun) && defined(__SVR4)
343+
344+
typedef thread_t OS_systemwide_thread_id_t;
345+
346+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
347+
{ return thr_self(); }
348+
349+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
350+
{ return (thread_t)(-1); }
351+
352+
#else //fallback to fragile pthread-based solution
353+
354+
class OS_systemwide_thread_id_t
252355
{
356+
pid_t pid;
357+
pthread_t tid;
358+
359+
public:
253360
OS_systemwide_thread_id_t()
254361
: pid(), tid()
255362
{}
@@ -262,49 +369,25 @@ struct OS_systemwide_thread_id_t
262369
: pid(x.pid), tid(x.tid)
263370
{}
264371

265-
OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
266-
: pid(x.pid), tid(x.tid)
267-
{}
268-
269372
OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
270373
{ pid = x.pid; tid = x.tid; return *this; }
271374

272-
OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
273-
{ pid = x.pid; tid = x.tid; return *this; }
274-
275-
void operator=(const OS_systemwide_thread_id_t &x) volatile
276-
{ pid = x.pid; tid = x.tid; }
277-
278-
pid_t pid;
279-
pthread_t tid;
375+
friend bool operator == (const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
376+
{ return id1.pid == id2.pid && (0 != pthread_equal(id1.tid, id2.tid)); }
280377
};
281378

282-
inline void systemwide_thread_id_copy
283-
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
379+
//systemwide thread
380+
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
284381
{
285-
to.pid = from.pid;
286-
to.tid = from.tid;
382+
return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
287383
}
288384

289-
//process
290-
inline OS_process_id_t get_current_process_id()
291-
{ return ::getpid(); }
292-
293-
inline OS_process_id_t get_invalid_process_id()
294-
{ return pid_t(0); }
295-
296-
//thread
297-
inline OS_thread_id_t get_current_thread_id()
298-
{ return ::pthread_self(); }
299-
300-
inline OS_thread_id_t get_invalid_thread_id()
385+
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
301386
{
302-
static pthread_t invalid_id;
303-
return invalid_id;
387+
return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
304388
}
305389

306-
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
307-
{ return 0 != pthread_equal(id1, id2); }
390+
#endif
308391

309392
inline void thread_yield()
310393
{ ::sched_yield(); }
@@ -461,22 +544,6 @@ inline void thread_sleep_ms(unsigned int ms)
461544
}
462545
}
463546

464-
//systemwide thread
465-
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
466-
{
467-
return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
468-
}
469-
470-
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
471-
{
472-
return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
473-
}
474-
475-
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
476-
{
477-
return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
478-
}
479-
480547
inline unsigned long long get_current_process_creation_time()
481548
{ return 0u; }
482549

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

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class spin_recursive_mutex
7676
private:
7777
spin_mutex m_mutex;
7878
unsigned int m_nLockCount;
79-
volatile ipcdetail::OS_systemwide_thread_id_t m_nOwner;
79+
volatile OS_systemwide_thread_id_t m_nOwner;
8080
volatile boost::uint32_t m_s;
8181
};
8282

@@ -87,11 +87,10 @@ inline spin_recursive_mutex::~spin_recursive_mutex(){}
8787

8888
inline void spin_recursive_mutex::lock()
8989
{
90-
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
91-
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
92-
handle_t old_id;
93-
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
94-
if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)){
90+
const OS_systemwide_thread_id_t thr_id(ipcdetail::get_current_systemwide_thread_id());
91+
OS_systemwide_thread_id_t old_id = const_cast<OS_systemwide_thread_id_t &>(m_nOwner);
92+
93+
if(thr_id == old_id){
9594
if((unsigned int)(m_nLockCount+1) == 0){
9695
//Overflow, throw an exception
9796
throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow");
@@ -100,18 +99,17 @@ inline void spin_recursive_mutex::lock()
10099
}
101100
else{
102101
m_mutex.lock();
103-
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
102+
const_cast<OS_systemwide_thread_id_t &>(m_nOwner) = thr_id;
104103
m_nLockCount = 1;
105104
}
106105
}
107106

108107
inline bool spin_recursive_mutex::try_lock()
109108
{
110-
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
111-
handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
112-
handle_t old_id;
113-
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
114-
if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it
109+
OS_systemwide_thread_id_t thr_id(ipcdetail::get_current_systemwide_thread_id());
110+
OS_systemwide_thread_id_t old_id = const_cast<OS_systemwide_thread_id_t &>(m_nOwner);
111+
112+
if(thr_id == old_id) { // we own it
115113
if((unsigned int)(m_nLockCount+1) == 0){
116114
//Overflow, throw an exception
117115
throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow");
@@ -120,7 +118,7 @@ inline bool spin_recursive_mutex::try_lock()
120118
return true;
121119
}
122120
if(m_mutex.try_lock()){
123-
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
121+
const_cast<OS_systemwide_thread_id_t &>(m_nOwner) = thr_id;
124122
m_nLockCount = 1;
125123
return true;
126124
}
@@ -130,11 +128,10 @@ inline bool spin_recursive_mutex::try_lock()
130128
template<class TimePoint>
131129
inline bool spin_recursive_mutex::timed_lock(const TimePoint &abs_time)
132130
{
133-
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
134-
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
135-
handle_t old_id;
136-
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
137-
if(ipcdetail::equal_systemwide_thread_id(thr_id , old_id)) { // we own it
131+
OS_systemwide_thread_id_t thr_id(ipcdetail::get_current_systemwide_thread_id());
132+
OS_systemwide_thread_id_t old_id = const_cast<OS_systemwide_thread_id_t &>(m_nOwner);
133+
134+
if(thr_id == old_id) { // we own it
138135
if((unsigned int)(m_nLockCount+1) == 0){
139136
//Overflow, throw an exception
140137
throw interprocess_exception("boost::interprocess::spin_recursive_mutex recursive lock overflow");
@@ -144,7 +141,7 @@ inline bool spin_recursive_mutex::timed_lock(const TimePoint &abs_time)
144141
}
145142
//m_mutex supports abs_time so no need to check it
146143
if(m_mutex.timed_lock(abs_time)){
147-
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
144+
const_cast<OS_systemwide_thread_id_t &>(m_nOwner) = thr_id;
148145
m_nLockCount = 1;
149146
return true;
150147
}
@@ -153,27 +150,21 @@ inline bool spin_recursive_mutex::timed_lock(const TimePoint &abs_time)
153150

154151
inline void spin_recursive_mutex::unlock()
155152
{
156-
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
157-
handle_t old_id;
158-
ipcdetail::systemwide_thread_id_copy(m_nOwner, old_id);
159-
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
160-
(void)old_id;
161-
(void)thr_id;
162-
BOOST_ASSERT(ipcdetail::equal_systemwide_thread_id(thr_id, old_id));
153+
BOOST_ASSERT(ipcdetail::get_current_systemwide_thread_id() == const_cast<const OS_systemwide_thread_id_t &>(m_nOwner));
154+
163155
--m_nLockCount;
164156
if(!m_nLockCount){
165-
const handle_t new_id(ipcdetail::get_invalid_systemwide_thread_id());
166-
ipcdetail::systemwide_thread_id_copy(new_id, m_nOwner);
157+
const OS_systemwide_thread_id_t new_id(ipcdetail::get_invalid_systemwide_thread_id());
158+
const_cast<OS_systemwide_thread_id_t &>(m_nOwner) = new_id;
167159
m_mutex.unlock();
168160
}
169161
}
170162

171163
inline void spin_recursive_mutex::take_ownership()
172164
{
173-
typedef ipcdetail::OS_systemwide_thread_id_t handle_t;
174165
this->m_nLockCount = 1;
175-
const handle_t thr_id(ipcdetail::get_current_systemwide_thread_id());
176-
ipcdetail::systemwide_thread_id_copy(thr_id, m_nOwner);
166+
const OS_systemwide_thread_id_t thr_id(ipcdetail::get_current_systemwide_thread_id());
167+
const_cast<OS_systemwide_thread_id_t &>(m_nOwner) = thr_id;
177168
}
178169

179170
} //namespace ipcdetail {

0 commit comments

Comments
 (0)