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