]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/interprocess/include/boost/interprocess/detail/os_thread_functions.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / interprocess / include / boost / interprocess / detail / os_thread_functions.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 //Thread launching functions are adapted from boost/detail/lightweight_thread.hpp
12 //
13 // boost/detail/lightweight_thread.hpp
14 //
15 // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
16 // Copyright (c) 2008 Peter Dimov
17 //
18 // Distributed under the Boost Software License, Version 1.0.
19 // See accompanying file LICENSE_1_0.txt or copy at
20 // http://www.boost.org/LICENSE_1_0.txt
21
22 #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
23 #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
24
25 #ifndef BOOST_CONFIG_HPP
26 # include <boost/config.hpp>
27 #endif
28 #
29 #if defined(BOOST_HAS_PRAGMA_ONCE)
30 # pragma once
31 #endif
32
33 #include <boost/interprocess/detail/config_begin.hpp>
34 #include <boost/interprocess/detail/workaround.hpp>
35 #include <boost/interprocess/streams/bufferstream.hpp>
36 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
37 #include <cstddef>
38 #include <ostream>
39
40 #if defined(BOOST_INTERPROCESS_WINDOWS)
41 # include <boost/interprocess/detail/win32_api.hpp>
42 # include <process.h>
43 #else
44 # include <pthread.h>
45 # include <unistd.h>
46 # include <sched.h>
47 # include <time.h>
48 # ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
49 //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
50 //others (FreeBSD & Darwin) need sys/types.h
51 # include <sys/types.h>
52 # include <sys/param.h>
53 # include <sys/sysctl.h>
54 # endif
55 //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
56 # if defined(CLOCK_MONOTONIC_PRECISE) //BSD
57 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
58 # elif defined(CLOCK_MONOTONIC_RAW) //Linux
59 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
60 # elif defined(CLOCK_HIGHRES) //Solaris
61 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
62 # elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
63 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
64 # elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
65 # include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
66 # define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
67 # else
68 # error "No high resolution steady clock in your system, please provide a patch"
69 # endif
70 #endif
71
72 namespace boost {
73 namespace interprocess {
74 namespace ipcdetail{
75
76 #if defined (BOOST_INTERPROCESS_WINDOWS)
77
78 typedef unsigned long OS_process_id_t;
79 typedef unsigned long OS_thread_id_t;
80 struct OS_thread_t
81 {
82 OS_thread_t()
83 : m_handle()
84 {}
85
86
87 void* handle() const
88 { return m_handle; }
89
90 void* m_handle;
91 };
92
93 typedef OS_thread_id_t OS_systemwide_thread_id_t;
94
95 //process
96 inline OS_process_id_t get_current_process_id()
97 { return winapi::get_current_process_id(); }
98
99 inline OS_process_id_t get_invalid_process_id()
100 { return OS_process_id_t(0); }
101
102 //thread
103 inline OS_thread_id_t get_current_thread_id()
104 { return winapi::get_current_thread_id(); }
105
106 inline OS_thread_id_t get_invalid_thread_id()
107 { return OS_thread_id_t(0xffffffff); }
108
109 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
110 { return id1 == id2; }
111
112 //return the system tick in ns
113 inline unsigned long get_system_tick_ns()
114 {
115 unsigned long curres;
116 winapi::set_timer_resolution(10000, 0, &curres);
117 //Windows API returns the value in hundreds of ns
118 return (curres - 1ul)*100ul;
119 }
120
121 //return the system tick in us
122 inline unsigned long get_system_tick_us()
123 {
124 unsigned long curres;
125 winapi::set_timer_resolution(10000, 0, &curres);
126 //Windows API returns the value in hundreds of ns
127 return (curres - 1ul)/10ul + 1ul;
128 }
129
130 typedef unsigned __int64 OS_highres_count_t;
131
132 inline unsigned long get_system_tick_in_highres_counts()
133 {
134 __int64 freq;
135 unsigned long curres;
136 winapi::set_timer_resolution(10000, 0, &curres);
137 //Frequency in counts per second
138 if(!winapi::query_performance_frequency(&freq)){
139 //Tick resolution in ms
140 return (curres-1ul)/10000ul + 1ul;
141 }
142 else{
143 //In femtoseconds
144 __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL;
145 __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL;
146 return static_cast<unsigned long>(tick_counts);
147 }
148 }
149
150 inline OS_highres_count_t get_current_system_highres_count()
151 {
152 __int64 count;
153 if(!winapi::query_performance_counter(&count)){
154 count = winapi::get_tick_count();
155 }
156 return count;
157 }
158
159 inline void zero_highres_count(OS_highres_count_t &count)
160 { count = 0; }
161
162 inline bool is_highres_count_zero(const OS_highres_count_t &count)
163 { return count == 0; }
164
165 template <class Ostream>
166 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
167 {
168 ostream << count;
169 return ostream;
170 }
171
172 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
173 { return l - r; }
174
175 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
176 { return l < r; }
177
178 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
179 { return l < static_cast<OS_highres_count_t>(r); }
180
181 inline void thread_sleep_tick()
182 { winapi::sleep_tick(); }
183
184 inline void thread_yield()
185 { winapi::sched_yield(); }
186
187 inline void thread_sleep(unsigned int ms)
188 { winapi::sleep(ms); }
189
190 //systemwide thread
191 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
192 {
193 return get_current_thread_id();
194 }
195
196 inline void systemwide_thread_id_copy
197 (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
198 {
199 to = from;
200 }
201
202 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
203 {
204 return equal_thread_id(id1, id2);
205 }
206
207 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
208 {
209 return get_invalid_thread_id();
210 }
211
212 inline long double get_current_process_creation_time()
213 {
214 winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
215
216 winapi::get_process_times
217 ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
218
219 typedef long double ldouble_t;
220 const ldouble_t resolution = (100.0l/1000000000.0l);
221 return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
222 CreationTime.dwLowDateTime*resolution;
223 }
224
225 inline unsigned int get_num_cores()
226 {
227 winapi::system_info sysinfo;
228 winapi::get_system_info( &sysinfo );
229 //in Windows dw is long which is equal in bits to int
230 return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
231 }
232
233 #else //#if defined (BOOST_INTERPROCESS_WINDOWS)
234
235 typedef pthread_t OS_thread_t;
236 typedef pthread_t OS_thread_id_t;
237 typedef pid_t OS_process_id_t;
238
239 struct OS_systemwide_thread_id_t
240 {
241 OS_systemwide_thread_id_t()
242 : pid(), tid()
243 {}
244
245 OS_systemwide_thread_id_t(pid_t p, pthread_t t)
246 : pid(p), tid(t)
247 {}
248
249 OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
250 : pid(x.pid), tid(x.tid)
251 {}
252
253 OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
254 : pid(x.pid), tid(x.tid)
255 {}
256
257 OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
258 { pid = x.pid; tid = x.tid; return *this; }
259
260 OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
261 { pid = x.pid; tid = x.tid; return *this; }
262
263 void operator=(const OS_systemwide_thread_id_t &x) volatile
264 { pid = x.pid; tid = x.tid; }
265
266 pid_t pid;
267 pthread_t tid;
268 };
269
270 inline void systemwide_thread_id_copy
271 (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
272 {
273 to.pid = from.pid;
274 to.tid = from.tid;
275 }
276
277 //process
278 inline OS_process_id_t get_current_process_id()
279 { return ::getpid(); }
280
281 inline OS_process_id_t get_invalid_process_id()
282 { return pid_t(0); }
283
284 //thread
285 inline OS_thread_id_t get_current_thread_id()
286 { return ::pthread_self(); }
287
288 inline OS_thread_id_t get_invalid_thread_id()
289 {
290 static pthread_t invalid_id;
291 return invalid_id;
292 }
293
294 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
295 { return 0 != pthread_equal(id1, id2); }
296
297 inline void thread_yield()
298 { ::sched_yield(); }
299
300 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
301 typedef struct timespec OS_highres_count_t;
302 #else
303 typedef unsigned long long OS_highres_count_t;
304 #endif
305
306 inline unsigned long get_system_tick_ns()
307 {
308 #ifdef _SC_CLK_TCK
309 long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec
310 if(ticks_per_second <= 0){ //Try a typical value on error
311 ticks_per_second = 100;
312 }
313 return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul;
314 #else
315 #error "Can't obtain system tick value for your system, please provide a patch"
316 #endif
317 }
318
319 inline unsigned long get_system_tick_in_highres_counts()
320 {
321 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
322 return get_system_tick_ns();
323 #else
324 mach_timebase_info_data_t info;
325 mach_timebase_info(&info);
326 //ns
327 return static_cast<unsigned long>
328 (
329 static_cast<double>(get_system_tick_ns())
330 / (static_cast<double>(info.numer) / info.denom)
331 );
332 #endif
333 }
334
335 //return system ticks in us
336 inline unsigned long get_system_tick_us()
337 {
338 return (get_system_tick_ns()-1)/1000ul + 1ul;
339 }
340
341 inline OS_highres_count_t get_current_system_highres_count()
342 {
343 #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
344 struct timespec count;
345 ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
346 return count;
347 #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
348 return ::mach_absolute_time();
349 #endif
350 }
351
352 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
353
354 inline void zero_highres_count(OS_highres_count_t &count)
355 { count.tv_sec = 0; count.tv_nsec = 0; }
356
357 inline bool is_highres_count_zero(const OS_highres_count_t &count)
358 { return count.tv_sec == 0 && count.tv_nsec == 0; }
359
360 template <class Ostream>
361 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
362 {
363 ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
364 return ostream;
365 }
366
367 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
368 {
369 OS_highres_count_t res;
370
371 if (l.tv_nsec < r.tv_nsec){
372 res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
373 res.tv_sec = l.tv_sec - 1 - r.tv_sec;
374 }
375 else{
376 res.tv_nsec = l.tv_nsec - r.tv_nsec;
377 res.tv_sec = l.tv_sec - r.tv_sec;
378 }
379
380 return res;
381 }
382
383 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
384 { return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); }
385
386 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
387 { return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); }
388
389 #else
390
391 inline void zero_highres_count(OS_highres_count_t &count)
392 { count = 0; }
393
394 inline bool is_highres_count_zero(const OS_highres_count_t &count)
395 { return count == 0; }
396
397 template <class Ostream>
398 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
399 {
400 ostream << count ;
401 return ostream;
402 }
403
404 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
405 { return l - r; }
406
407 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
408 { return l < r; }
409
410 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
411 { return l < static_cast<OS_highres_count_t>(r); }
412
413 #endif
414
415 inline void thread_sleep_tick()
416 {
417 struct timespec rqt;
418 //Sleep for the half of the tick time
419 rqt.tv_sec = 0;
420 rqt.tv_nsec = get_system_tick_ns()/2;
421 ::nanosleep(&rqt, 0);
422 }
423
424 inline void thread_sleep(unsigned int ms)
425 {
426 struct timespec rqt;
427 rqt.tv_sec = ms/1000u;
428 rqt.tv_nsec = (ms%1000u)*1000000u;
429 ::nanosleep(&rqt, 0);
430 }
431
432 //systemwide thread
433 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
434 {
435 return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
436 }
437
438 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
439 {
440 return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
441 }
442
443 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
444 {
445 return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
446 }
447
448 inline long double get_current_process_creation_time()
449 { return 0.0L; }
450
451 inline unsigned int get_num_cores()
452 {
453 #ifdef _SC_NPROCESSORS_ONLN
454 long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
455 // sysconf returns -1 if the name is invalid, the option does not exist or
456 // does not have a definite limit.
457 // if sysconf returns some other negative number, we have no idea
458 // what is going on. Default to something safe.
459 if(cores <= 0){
460 return 1;
461 }
462 //Check for overflow (unlikely)
463 else if(static_cast<unsigned long>(cores) >=
464 static_cast<unsigned long>(static_cast<unsigned int>(-1))){
465 return static_cast<unsigned int>(-1);
466 }
467 else{
468 return static_cast<unsigned int>(cores);
469 }
470 #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
471 int request[2] = { CTL_HW, HW_NCPU };
472 int num_cores;
473 std::size_t result_len = sizeof(num_cores);
474 if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
475 //Return a safe value
476 return 1;
477 }
478 else{
479 return static_cast<unsigned int>(num_cores);
480 }
481 #endif
482 }
483
484 inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg)
485 { return pthread_create(thread, 0, start_routine, arg); }
486
487 inline void thread_join(OS_thread_t thread)
488 { (void)pthread_join(thread, 0); }
489
490 #endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
491
492 typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
493
494 inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
495 {
496 bufferstream bstream(pid_str, sizeof(pid_str));
497 bstream << pid << std::ends;
498 }
499
500 inline void get_pid_str(pid_str_t &pid_str)
501 { get_pid_str(pid_str, get_current_process_id()); }
502
503 #if defined(BOOST_INTERPROCESS_WINDOWS)
504
505 inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg )
506 {
507 void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
508
509 if( h != 0 ){
510 thread->m_handle = h;
511 return 0;
512 }
513 else{
514 return 1;
515 }
516
517 thread->m_handle = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
518 return thread->m_handle != 0;
519 }
520
521 inline void thread_join( OS_thread_t thread)
522 {
523 winapi::wait_for_single_object( thread.handle(), winapi::infinite_time );
524 winapi::close_handle( thread.handle() );
525 }
526
527 #endif
528
529 class abstract_thread
530 {
531 public:
532 virtual ~abstract_thread() {}
533 virtual void run() = 0;
534 };
535
536 template<class T>
537 class os_thread_func_ptr_deleter
538 {
539 public:
540 explicit os_thread_func_ptr_deleter(T* p)
541 : m_p(p)
542 {}
543
544 T *release()
545 { T *p = m_p; m_p = 0; return p; }
546
547 T *get() const
548 { return m_p; }
549
550 T *operator ->() const
551 { return m_p; }
552
553 ~os_thread_func_ptr_deleter()
554 { delete m_p; }
555
556 private:
557 T *m_p;
558 };
559
560 #if defined(BOOST_INTERPROCESS_WINDOWS)
561
562 inline unsigned __stdcall launch_thread_routine( void * pv )
563 {
564 os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
565 pt->run();
566 return 0;
567 }
568
569 #else
570
571 extern "C" void * launch_thread_routine( void * pv );
572
573 inline void * launch_thread_routine( void * pv )
574 {
575 os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
576 pt->run();
577 return 0;
578 }
579
580 #endif
581
582 template<class F>
583 class launch_thread_impl
584 : public abstract_thread
585 {
586 public:
587 explicit launch_thread_impl( F f )
588 : f_( f )
589 {}
590
591 void run()
592 { f_(); }
593
594 private:
595 F f_;
596 };
597
598 template<class F>
599 inline int thread_launch( OS_thread_t & pt, F f )
600 {
601 os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) );
602
603 int r = thread_create(&pt, launch_thread_routine, p.get());
604 if( r == 0 ){
605 p.release();
606 }
607
608 return r;
609 }
610
611 } //namespace ipcdetail{
612 } //namespace interprocess {
613 } //namespace boost {
614
615 #include <boost/interprocess/detail/config_end.hpp>
616
617 #endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP