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