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