1 _threads.c |
1 /* |
|
2 * |
|
3 * |
|
4 * Copyright (c) 1994 |
|
5 * Hewlett-Packard Company |
|
6 * |
|
7 * Copyright (c) 1996,1997 |
|
8 * Silicon Graphics Computer Systems, Inc. |
|
9 * |
|
10 * Copyright (c) 1997 |
|
11 * Moscow Center for SPARC Technology |
|
12 * |
|
13 * Copyright (c) 1999 |
|
14 * Boris Fomitchev |
|
15 * |
|
16 * This material is provided "as is", with absolutely no warranty expressed |
|
17 * or implied. Any use is at your own risk. |
|
18 * |
|
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. |
|
24 * |
|
25 */ |
|
26 #ifndef _STLP_THREADS_C |
|
27 #define _STLP_THREADS_C |
|
28 |
|
29 #ifndef _STLP_INTERNAL_THREADS_H |
|
30 # include <stl/_threads.h> |
|
31 #endif |
|
32 |
|
33 # if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) |
|
34 |
|
35 # if defined(_STLP_SGI_THREADS) |
|
36 # include <time.h> |
|
37 # elif defined (_STLP_UNIX) |
|
38 # include <ctime> |
|
39 # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD) |
|
40 using _STLP_VENDOR_CSTD::time_t; |
|
41 # endif |
|
42 # include <sys/time.h> |
|
43 # endif |
|
44 |
|
45 _STLP_BEGIN_NAMESPACE |
|
46 |
|
47 # if (_STLP_STATIC_TEMPLATE_DATA > 0) |
|
48 |
|
49 # ifdef _STLP_THREADS |
|
50 # if !defined(_STLP_ATOMIC_EXCHANGE) && (defined(_STLP_PTHREADS) || defined(_STLP_UITHREADS) || defined(_STLP_OS2THREADS) || defined(_STLP_USE_PTHREAD_SPINLOCK)) |
|
51 template<int __dummy> |
|
52 _STLP_STATIC_MUTEX |
|
53 _Swap_lock_struct<__dummy>::_S_swap_lock _STLP_MUTEX_INITIALIZER; |
|
54 # endif |
|
55 # endif //_STLP_THREADS |
|
56 |
|
57 # ifndef _STLP_USE_PTHREAD_SPINLOCK |
|
58 template <int __inst> |
|
59 unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max; |
|
60 |
|
61 template <int __inst> |
|
62 unsigned _STLP_mutex_spin<__inst>::__last = 0; |
|
63 # endif // _STLP_USE_PTHREAD_SPINLOCK |
|
64 |
|
65 # else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ |
|
66 |
|
67 # if defined(_STLP_PTHREADS) || defined(_STLP_UITHREADS) || defined(_STLP_OS2THREADS) |
|
68 __DECLARE_INSTANCE(_STLP_STATIC_MUTEX, _Swap_lock_struct<0>::_S_swap_lock, |
|
69 _STLP_MUTEX_INITIALIZER ); |
|
70 # endif /* _STLP_PTHREADS */ |
|
71 |
|
72 # ifndef _STLP_USE_PTHREAD_SPINLOCK |
|
73 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__max, =30); |
|
74 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__last, =0); |
|
75 # endif // _STLP_USE_PTHREAD_SPINLOCK |
|
76 |
|
77 # endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ |
|
78 |
|
79 #ifndef _STLP_USE_PTHREAD_SPINLOCK |
|
80 |
|
81 #ifdef _STLP_SPARC_SOLARIS_THREADS |
|
82 // underground function in libc.so; we do not want dependance on librt |
|
83 extern "C" int __nanosleep(const struct timespec*, struct timespec*); |
|
84 # define _STLP_NANOSLEEP __nanosleep |
|
85 #else |
|
86 # define _STLP_NANOSLEEP nanosleep |
|
87 #endif |
|
88 |
|
89 template <int __inst> |
|
90 void _STLP_CALL |
|
91 _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) { |
|
92 # if defined(_STLP_WIN32THREADS) |
|
93 if (__log_nsec <= 20) { |
|
94 // Note from boost (www.boost.org): |
|
95 // Changed to Sleep(1) from Sleep(0). |
|
96 // According to MSDN, Sleep(0) will never yield |
|
97 // to a lower-priority thread, whereas Sleep(1) |
|
98 // will. Performance seems not to be affected. |
|
99 Sleep(1); |
|
100 } else { |
|
101 Sleep(1 << (__log_nsec - 20)); |
|
102 } |
|
103 # elif defined(_STLP_OS2THREADS) |
|
104 if (__log_nsec <= 20) { |
|
105 DosSleep(0); |
|
106 } else { |
|
107 DosSleep(1 << (__log_nsec - 20)); |
|
108 } |
|
109 # elif defined (_STLP_UNIX) |
|
110 timespec __ts; |
|
111 /* Max sleep is 2**27nsec ~ 60msec */ |
|
112 __ts.tv_sec = 0; |
|
113 __ts.tv_nsec = 1 << __log_nsec; |
|
114 _STLP_NANOSLEEP(&__ts, 0); |
|
115 # endif |
|
116 } |
|
117 |
|
118 |
|
119 template <int __inst> |
|
120 void _STLP_CALL |
|
121 _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) |
|
122 { |
|
123 #if defined(_STLP_ATOMIC_EXCHANGE) |
|
124 if (_Atomic_swap(__lock, 1)) { |
|
125 unsigned __my_spin_max = _STLP_mutex_spin<0>::__max; |
|
126 unsigned __my_last_spins = _STLP_mutex_spin<0>::__last; |
|
127 volatile unsigned __junk = 17; // Value doesn't matter. |
|
128 unsigned __i; |
|
129 |
|
130 for (__i = 0; __i < __my_spin_max; ++__i) { |
|
131 if (__i < __my_last_spins/2 || *__lock) { |
|
132 __junk *= __junk; __junk *= __junk; |
|
133 __junk *= __junk; __junk *= __junk; |
|
134 } else { |
|
135 if (!_Atomic_swap(__lock, 1)) { |
|
136 // got it! |
|
137 // Spinning worked. Thus we're probably not being scheduled |
|
138 // against the other process with which we were contending. |
|
139 // Thus it makes sense to spin longer the next time. |
|
140 _STLP_mutex_spin<0>::__last = __i; |
|
141 _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__high_max; |
|
142 return; |
|
143 } |
|
144 } |
|
145 } |
|
146 |
|
147 // We are probably being scheduled against the other process. Sleep. |
|
148 _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__low_max; |
|
149 |
|
150 for (__i = 0 ;; ++__i) { |
|
151 int __log_nsec = __i + 6; |
|
152 |
|
153 if (__log_nsec > 27) __log_nsec = 27; |
|
154 if (!_Atomic_swap(__lock, 1)) { |
|
155 break; |
|
156 } |
|
157 _S_nsec_sleep(__log_nsec); |
|
158 } |
|
159 |
|
160 } /* first _Atomic_swap */ |
|
161 # endif |
|
162 } |
|
163 #endif // _STLP_USE_PTHREAD_SPINLOCK |
|
164 |
|
165 _STLP_END_NAMESPACE |
|
166 |
|
167 # endif /* BUILDING_STLPORT */ |
|
168 #endif /* _STLP_THREADS_C */ |
|
169 |
|
170 // Local Variables: |
|
171 // mode:C++ |
|
172 // End: |