]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/include/boost/thread/win32/thread_primitives.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / thread / include / boost / thread / win32 / thread_primitives.hpp
1 #ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
2 #define BOOST_WIN32_THREAD_PRIMITIVES_HPP
3
4 // win32_thread_primitives.hpp
5 //
6 // (C) Copyright 2005-7 Anthony Williams
7 // (C) Copyright 2007 David Deakins
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12
13 #include <boost/thread/detail/config.hpp>
14 #include <boost/predef/platform.h>
15 #include <boost/throw_exception.hpp>
16 #include <boost/assert.hpp>
17 #include <boost/thread/exceptions.hpp>
18 #include <boost/detail/interlocked.hpp>
19 #include <boost/detail/winapi/config.hpp>
20 //#include <boost/detail/winapi/synchronization.hpp>
21 #include <algorithm>
22
23 #if BOOST_PLAT_WINDOWS_RUNTIME
24 #include <thread>
25 #endif
26
27 #if defined( BOOST_USE_WINDOWS_H )
28 # include <windows.h>
29
30 namespace boost
31 {
32 namespace detail
33 {
34 namespace win32
35 {
36 typedef HANDLE handle;
37 typedef SYSTEM_INFO system_info;
38 typedef unsigned __int64 ticks_type;
39 typedef FARPROC farproc_t;
40 unsigned const infinite=INFINITE;
41 unsigned const timeout=WAIT_TIMEOUT;
42 handle const invalid_handle_value=INVALID_HANDLE_VALUE;
43 unsigned const event_modify_state=EVENT_MODIFY_STATE;
44 unsigned const synchronize=SYNCHRONIZE;
45 unsigned const wait_abandoned=WAIT_ABANDONED;
46 unsigned const create_event_initial_set = 0x00000002;
47 unsigned const create_event_manual_reset = 0x00000001;
48 unsigned const event_all_access = EVENT_ALL_ACCESS;
49 unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
50
51
52 # ifdef BOOST_NO_ANSI_APIS
53 # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
54 using ::CreateMutexW;
55 using ::CreateEventW;
56 using ::CreateSemaphoreW;
57 # else
58 using ::CreateMutexExW;
59 using ::CreateEventExW;
60 using ::CreateSemaphoreExW;
61 # endif
62 using ::OpenEventW;
63 using ::GetModuleHandleW;
64 # else
65 using ::CreateMutexA;
66 using ::CreateEventA;
67 using ::OpenEventA;
68 using ::CreateSemaphoreA;
69 using ::GetModuleHandleA;
70 # endif
71 #if BOOST_PLAT_WINDOWS_RUNTIME
72 using ::GetNativeSystemInfo;
73 using ::GetTickCount64;
74 #else
75 using ::GetSystemInfo;
76 using ::GetTickCount;
77 #endif
78 using ::CloseHandle;
79 using ::ReleaseMutex;
80 using ::ReleaseSemaphore;
81 using ::SetEvent;
82 using ::ResetEvent;
83 using ::WaitForMultipleObjectsEx;
84 using ::WaitForSingleObjectEx;
85 using ::GetCurrentProcessId;
86 using ::GetCurrentThreadId;
87 using ::GetCurrentThread;
88 using ::GetCurrentProcess;
89 using ::DuplicateHandle;
90 #if !BOOST_PLAT_WINDOWS_RUNTIME
91 using ::SleepEx;
92 using ::Sleep;
93 using ::QueueUserAPC;
94 using ::GetProcAddress;
95 #endif
96 }
97 }
98 }
99 #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
100
101 # ifdef UNDER_CE
102 # ifndef WINAPI
103 # ifndef _WIN32_WCE_EMULATION
104 # define WINAPI __cdecl // Note this doesn't match the desktop definition
105 # else
106 # define WINAPI __stdcall
107 # endif
108 # endif
109
110 # ifdef __cplusplus
111 extern "C" {
112 # endif
113 typedef int BOOL;
114 typedef unsigned long DWORD;
115 typedef void* HANDLE;
116 # include <kfuncs.h>
117 # ifdef __cplusplus
118 }
119 # endif
120 # endif
121
122 # ifdef __cplusplus
123 extern "C" {
124 # endif
125 struct _SYSTEM_INFO;
126 # ifdef __cplusplus
127 }
128 #endif
129
130 namespace boost
131 {
132 namespace detail
133 {
134 namespace win32
135 {
136 # ifdef _WIN64
137 typedef unsigned __int64 ulong_ptr;
138 # else
139 typedef unsigned long ulong_ptr;
140 # endif
141 typedef void* handle;
142 typedef _SYSTEM_INFO system_info;
143 typedef unsigned __int64 ticks_type;
144 typedef int (__stdcall *farproc_t)();
145 unsigned const infinite=~0U;
146 unsigned const timeout=258U;
147 handle const invalid_handle_value=(handle)(-1);
148 unsigned const event_modify_state=2;
149 unsigned const synchronize=0x100000u;
150 unsigned const wait_abandoned=0x00000080u;
151 unsigned const create_event_initial_set = 0x00000002;
152 unsigned const create_event_manual_reset = 0x00000001;
153 unsigned const event_all_access = 0x1F0003;
154 unsigned const semaphore_all_access = 0x1F0003;
155
156 extern "C"
157 {
158 struct _SECURITY_ATTRIBUTES;
159 # ifdef BOOST_NO_ANSI_APIS
160 # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
161 __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
162 __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
163 __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
164 # else
165 __declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
166 __declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
167 __declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
168 # endif
169 __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
170 __declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*);
171 # else
172 __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
173 __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
174 __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
175 __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
176 __declspec(dllimport) void* __stdcall GetModuleHandleA(char const*);
177 # endif
178 #if BOOST_PLAT_WINDOWS_RUNTIME
179 __declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
180 __declspec(dllimport) ticks_type __stdcall GetTickCount64();
181 #else
182 __declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
183 __declspec(dllimport) unsigned long __stdcall GetTickCount();
184 #endif
185 __declspec(dllimport) int __stdcall CloseHandle(void*);
186 __declspec(dllimport) int __stdcall ReleaseMutex(void*);
187 __declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int);
188 __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable);
189 __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
190 __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
191 #if !BOOST_PLAT_WINDOWS_RUNTIME
192 __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
193 __declspec(dllimport) void __stdcall Sleep(unsigned long);
194 typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
195 __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
196 __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *);
197 #endif
198
199 # ifndef UNDER_CE
200 __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
201 __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
202 __declspec(dllimport) void* __stdcall GetCurrentThread();
203 __declspec(dllimport) void* __stdcall GetCurrentProcess();
204 __declspec(dllimport) int __stdcall SetEvent(void*);
205 __declspec(dllimport) int __stdcall ResetEvent(void*);
206 # else
207 using ::GetCurrentProcessId;
208 using ::GetCurrentThreadId;
209 using ::GetCurrentThread;
210 using ::GetCurrentProcess;
211 using ::SetEvent;
212 using ::ResetEvent;
213 # endif
214 }
215 }
216 }
217 }
218 #else
219 # error "Win32 functions not available"
220 #endif
221
222 #include <boost/config/abi_prefix.hpp>
223
224 namespace boost
225 {
226 namespace detail
227 {
228 namespace win32
229 {
230 namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); }
231 #if !BOOST_PLAT_WINDOWS_RUNTIME
232 extern "C"
233 {
234 #ifdef _MSC_VER
235 long _InterlockedCompareExchange(long volatile *, long, long);
236 #pragma intrinsic(_InterlockedCompareExchange)
237 #elif defined(__MINGW64_VERSION_MAJOR)
238 long _InterlockedCompareExchange(long volatile *, long, long);
239 #else
240 // Mingw doesn't provide intrinsics
241 #define _InterlockedCompareExchange InterlockedCompareExchange
242 #endif
243 }
244 // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar
245 inline ticks_type __stdcall GetTickCount64emulation()
246 {
247 static volatile long count = 0xFFFFFFFF;
248 unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone;
249 ticks_type current_tick64;
250
251 previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0);
252 current_tick32 = GetTickCount();
253
254 if(previous_count == 0xFFFFFFFF)
255 {
256 // count has never been written
257 unsigned long initial_count;
258 initial_count = current_tick32 >> 28;
259 previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF);
260
261 current_tick64 = initial_count;
262 current_tick64 <<= 28;
263 current_tick64 += current_tick32 & 0x0FFFFFFF;
264 return current_tick64;
265 }
266
267 previous_count_zone = previous_count & 15;
268 current_tick32_zone = current_tick32 >> 28;
269
270 if(current_tick32_zone == previous_count_zone)
271 {
272 // The top four bits of the 32-bit tick count haven't changed since count was last written.
273 current_tick64 = previous_count;
274 current_tick64 <<= 28;
275 current_tick64 += current_tick32 & 0x0FFFFFFF;
276 return current_tick64;
277 }
278
279 if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15))
280 {
281 // The top four bits of the 32-bit tick count have been incremented since count was last written.
282 _InterlockedCompareExchange(&count, previous_count + 1, previous_count);
283 current_tick64 = previous_count + 1;
284 current_tick64 <<= 28;
285 current_tick64 += current_tick32 & 0x0FFFFFFF;
286 return current_tick64;
287 }
288
289 // Oops, we weren't called often enough, we're stuck
290 return 0xFFFFFFFF;
291 }
292 #else
293 #endif
294 inline detail::gettickcount64_t GetTickCount64_()
295 {
296 static detail::gettickcount64_t gettickcount64impl;
297 if(gettickcount64impl)
298 return gettickcount64impl;
299
300 // GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
301 // and kernel32 isn't used in Windows Phone.
302 #if BOOST_PLAT_WINDOWS_RUNTIME
303 gettickcount64impl = &GetTickCount64;
304 #else
305 farproc_t addr=GetProcAddress(
306 #if !defined(BOOST_NO_ANSI_APIS)
307 GetModuleHandleA("KERNEL32.DLL"),
308 #else
309 GetModuleHandleW(L"KERNEL32.DLL"),
310 #endif
311 "GetTickCount64");
312 if(addr)
313 gettickcount64impl=(detail::gettickcount64_t) addr;
314 else
315 gettickcount64impl=&GetTickCount64emulation;
316 #endif
317 return gettickcount64impl;
318 }
319
320 enum event_type
321 {
322 auto_reset_event=false,
323 manual_reset_event=true
324 };
325
326 enum initial_event_state
327 {
328 event_initially_reset=false,
329 event_initially_set=true
330 };
331
332 inline handle create_event(
333 #if !defined(BOOST_NO_ANSI_APIS)
334 const char *mutex_name,
335 #else
336 const wchar_t *mutex_name,
337 #endif
338 event_type type,
339 initial_event_state state)
340 {
341 #if !defined(BOOST_NO_ANSI_APIS)
342 handle const res = win32::CreateEventA(0, type, state, mutex_name);
343 #elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
344 handle const res = win32::CreateEventW(0, type, state, mutex_name);
345 #else
346 handle const res = win32::CreateEventExW(
347 0,
348 mutex_name,
349 type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
350 event_all_access);
351 #endif
352 return res;
353 }
354
355 inline handle create_anonymous_event(event_type type,initial_event_state state)
356 {
357 handle const res = create_event(0, type, state);
358 if(!res)
359 {
360 boost::throw_exception(thread_resource_error());
361 }
362 return res;
363 }
364
365 inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
366 {
367 #if !defined(BOOST_NO_ANSI_APIS)
368 handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
369 #else
370 #if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
371 handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
372 #else
373 handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
374 #endif
375 #endif
376 return res;
377 }
378
379 inline handle create_anonymous_semaphore(long initial_count,long max_count)
380 {
381 handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
382 if(!res)
383 {
384 boost::throw_exception(thread_resource_error());
385 }
386 return res;
387 }
388
389 inline handle duplicate_handle(handle source)
390 {
391 handle const current_process=GetCurrentProcess();
392 long const same_access_flag=2;
393 handle new_handle=0;
394 bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
395 if(!success)
396 {
397 boost::throw_exception(thread_resource_error());
398 }
399 return new_handle;
400 }
401
402 inline void release_semaphore(handle semaphore,long count)
403 {
404 BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
405 }
406
407 inline void get_system_info(system_info *info)
408 {
409 #if BOOST_PLAT_WINDOWS_RUNTIME
410 win32::GetNativeSystemInfo(info);
411 #else
412 win32::GetSystemInfo(info);
413 #endif
414 }
415
416 inline void sleep(unsigned long milliseconds)
417 {
418 if(milliseconds == 0)
419 {
420 #if BOOST_PLAT_WINDOWS_RUNTIME
421 std::this_thread::yield();
422 #else
423 ::boost::detail::win32::Sleep(0);
424 #endif
425 }
426 else
427 {
428 #if BOOST_PLAT_WINDOWS_RUNTIME
429 ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
430 #else
431 ::boost::detail::win32::Sleep(milliseconds);
432 #endif
433 }
434 }
435
436 #if BOOST_PLAT_WINDOWS_RUNTIME
437 class BOOST_THREAD_DECL scoped_winrt_thread
438 {
439 public:
440 scoped_winrt_thread() : m_completionHandle(invalid_handle_value)
441 {}
442
443 ~scoped_winrt_thread()
444 {
445 if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
446 {
447 CloseHandle(m_completionHandle);
448 }
449 }
450
451 typedef unsigned(__stdcall * thread_func)(void *);
452 bool start(thread_func address, void *parameter, unsigned int *thrdId);
453
454 handle waitable_handle() const
455 {
456 BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value);
457 return m_completionHandle;
458 }
459
460 private:
461 handle m_completionHandle;
462 };
463 #endif
464 class BOOST_THREAD_DECL handle_manager
465 {
466 private:
467 handle handle_to_manage;
468 handle_manager(handle_manager&);
469 handle_manager& operator=(handle_manager&);
470
471 void cleanup()
472 {
473 if(handle_to_manage && handle_to_manage!=invalid_handle_value)
474 {
475 BOOST_VERIFY(CloseHandle(handle_to_manage));
476 }
477 }
478
479 public:
480 explicit handle_manager(handle handle_to_manage_):
481 handle_to_manage(handle_to_manage_)
482 {}
483 handle_manager():
484 handle_to_manage(0)
485 {}
486
487 handle_manager& operator=(handle new_handle)
488 {
489 cleanup();
490 handle_to_manage=new_handle;
491 return *this;
492 }
493
494 operator handle() const
495 {
496 return handle_to_manage;
497 }
498
499 handle duplicate() const
500 {
501 return duplicate_handle(handle_to_manage);
502 }
503
504 void swap(handle_manager& other)
505 {
506 std::swap(handle_to_manage,other.handle_to_manage);
507 }
508
509 handle release()
510 {
511 handle const res=handle_to_manage;
512 handle_to_manage=0;
513 return res;
514 }
515
516 bool operator!() const
517 {
518 return !handle_to_manage;
519 }
520
521 ~handle_manager()
522 {
523 cleanup();
524 }
525 };
526 }
527 }
528 }
529
530 #if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
531
532 namespace boost
533 {
534 namespace detail
535 {
536 namespace win32
537 {
538 #if _MSC_VER==1400
539 extern "C" unsigned char _interlockedbittestandset(long *a,long b);
540 extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
541 #else
542 extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
543 extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
544 #endif
545
546 #pragma intrinsic(_interlockedbittestandset)
547 #pragma intrinsic(_interlockedbittestandreset)
548
549 inline bool interlocked_bit_test_and_set(long* x,long bit)
550 {
551 return _interlockedbittestandset(x,bit)!=0;
552 }
553
554 inline bool interlocked_bit_test_and_reset(long* x,long bit)
555 {
556 return _interlockedbittestandreset(x,bit)!=0;
557 }
558
559 }
560 }
561 }
562 #define BOOST_THREAD_BTS_DEFINED
563 #elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
564 namespace boost
565 {
566 namespace detail
567 {
568 namespace win32
569 {
570 inline bool interlocked_bit_test_and_set(long* x,long bit)
571 {
572 #ifndef BOOST_INTEL_CXX_VERSION
573 __asm {
574 mov eax,bit;
575 mov edx,x;
576 lock bts [edx],eax;
577 setc al;
578 };
579 #else
580 bool ret;
581 __asm {
582 mov eax,bit
583 mov edx,x
584 lock bts [edx],eax
585 setc al
586 mov ret, al
587 };
588 return ret;
589
590 #endif
591 }
592
593 inline bool interlocked_bit_test_and_reset(long* x,long bit)
594 {
595 #ifndef BOOST_INTEL_CXX_VERSION
596 __asm {
597 mov eax,bit;
598 mov edx,x;
599 lock btr [edx],eax;
600 setc al;
601 };
602 #else
603 bool ret;
604 __asm {
605 mov eax,bit
606 mov edx,x
607 lock btr [edx],eax
608 setc al
609 mov ret, al
610 };
611 return ret;
612
613 #endif
614 }
615
616 }
617 }
618 }
619 #define BOOST_THREAD_BTS_DEFINED
620 #endif
621
622 #ifndef BOOST_THREAD_BTS_DEFINED
623
624 namespace boost
625 {
626 namespace detail
627 {
628 namespace win32
629 {
630 inline bool interlocked_bit_test_and_set(long* x,long bit)
631 {
632 long const value=1<<bit;
633 long old=*x;
634 do
635 {
636 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
637 if(current==old)
638 {
639 break;
640 }
641 old=current;
642 }
643 while(true) ;
644 return (old&value)!=0;
645 }
646
647 inline bool interlocked_bit_test_and_reset(long* x,long bit)
648 {
649 long const value=1<<bit;
650 long old=*x;
651 do
652 {
653 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
654 if(current==old)
655 {
656 break;
657 }
658 old=current;
659 }
660 while(true) ;
661 return (old&value)!=0;
662 }
663 }
664 }
665 }
666 #endif
667
668 #include <boost/config/abi_suffix.hpp>
669
670 #endif