5 * Hewlett-Packard Company
7 * Copyright (c) 1996,1997
8 * Silicon Graphics Computer Systems, Inc.
11 * Moscow Center for SPARC Technology
16 * This material is provided "as is", with absolutely no warranty expressed
17 * or implied. Any use is at your own risk.
19 * Permission to use or copy this software for any purpose is hereby granted
20 * without fee, provided the above notices are retained on all copies.
21 * Permission to modify the code and to distribute modified code is granted,
22 * provided the above notices are retained, and a notice that the code was
23 * modified is included with the above copyright notice.
26 #ifndef _STLP_THREADS_C
27 #define _STLP_THREADS_C
29 #ifndef _STLP_INTERNAL_THREADS_H
30 # include <stl/_threads.h>
33 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
35 #if defined (_STLP_SGI_THREADS)
37 #elif defined (_STLP_UNIX)
38 # ifndef _STLP_INTERNAL_CTIME
39 # include <stl/_ctime.h>
41 # if defined (_STLP_USE_NAMESPACES) && !defined (_STLP_VENDOR_GLOBAL_CSTD)
42 using _STLP_VENDOR_CSTD::time_t;
44 # include <sys/time.h>
49 #if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
50 template<int __32bits
>
52 _Atomic_swap_struct
<__32bits
>::_S_swap_lock _STLP_MUTEX_INITIALIZER
;
53 # undef _STLP_USE_ATOMIC_SWAP_MUTEX
56 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
58 unsigned _STLP_mutex_spin
<__inst
>::__max
= _STLP_mutex_spin
<__inst
>::__low_max
;
61 unsigned _STLP_mutex_spin
<__inst
>::__last
= 0;
62 #endif // _STLP_USE_PTHREAD_SPINLOCK
64 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
66 # if defined (_STLP_SPARC_SOLARIS_THREADS)
67 // underground function in libc.so; we do not want dependance on librt
68 extern "C" int __nanosleep(const struct timespec
*, struct timespec
*);
69 # define _STLP_NANOSLEEP __nanosleep
71 # define _STLP_NANOSLEEP nanosleep
76 _STLP_mutex_spin
<__inst
>::_S_nsec_sleep(int __log_nsec
, unsigned int& __iteration
) {
77 # if defined (_STLP_WIN32THREADS)
78 # if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
79 if (__iteration
<= 4000) {
80 // Use SwitchToThread because
81 // 1) Sleep(1) often takes ~15 ms
82 // 2) SwitchToThread yields to lower-priority threads
83 // 4000 is enough to avoid Sleep and is used just to prevent infinite looping
84 // This number is advised spin count for Heap management by Microsoft
88 if (__log_nsec
<= 21) {
89 /* Note from boost (www.boost.org):
90 * Changed from Sleep(0) to Sleep(1).
91 * According to MSDN, Sleep(0) will never yield to a lower-priority thread,
92 * whereas Sleep(1) will. Performance seems not to be affected. */
95 Sleep(1 << (__log_nsec
- 20));
97 # if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
98 __iteration
= 0; //reset to avoid sleeps sequence
101 # elif defined(_STLP_OS2THREADS)
102 if (__log_nsec
<= 20) {
105 DosSleep(1 << (__log_nsec
- 20));
107 # elif defined (_STLP_UNIX)
109 /* Max sleep is 2**27nsec ~ 60msec */
111 __ts
.tv_nsec
= 1 << __log_nsec
;
112 _STLP_NANOSLEEP(&__ts
, 0);
116 template <int __inst
>
118 _STLP_mutex_spin
<__inst
>::_M_do_lock(volatile __stl_atomic_t
* __lock
) {
119 # if defined(_STLP_ATOMIC_EXCHANGE)
120 if (_Atomic_swap(__lock
, 1)) {
121 unsigned __my_spin_max
= _STLP_mutex_spin
<0>::__max
;
122 unsigned __my_last_spins
= _STLP_mutex_spin
<0>::__last
;
123 volatile unsigned __junk
= 17; // Value doesn't matter.
126 for (__i
= 0; __i
< __my_spin_max
; ++__i
) {
127 if (__i
< __my_last_spins
/2 || *__lock
) {
128 __junk
*= __junk
; __junk
*= __junk
;
129 __junk
*= __junk
; __junk
*= __junk
;
131 if (!_Atomic_swap(__lock
, 1)) {
133 // Spinning worked. Thus we're probably not being scheduled
134 // against the other process with which we were contending.
135 // Thus it makes sense to spin longer the next time.
136 _STLP_mutex_spin
<0>::__last
= __i
;
137 _STLP_mutex_spin
<0>::__max
= _STLP_mutex_spin
<0>::__high_max
;
143 // We are probably being scheduled against the other process. Sleep.
144 _STLP_mutex_spin
<0>::__max
= _STLP_mutex_spin
<0>::__low_max
;
146 for (__i
= 0 ;; ++__i
) {
147 int __log_nsec
= __i
+ 6;
149 if (__log_nsec
> 27) __log_nsec
= 27;
150 if (!_Atomic_swap(__lock
, 1)) {
153 _S_nsec_sleep(__log_nsec
, __i
);
155 } /* first _Atomic_swap */
158 #endif // _STLP_USE_PTHREAD_SPINLOCK
162 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */
163 #endif /* _STLP_THREADS_C */