]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/stl/stl/_threads.c
Add STLport 5.1.4
[polintos/scott/priv.git] / include / c++ / stl / stl / _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 #  ifndef _STLP_INTERNAL_CTIME
39 #    include <stl/_ctime.h>
40 #  endif
41 #  if defined (_STLP_USE_NAMESPACES) && !defined (_STLP_VENDOR_GLOBAL_CSTD)
42 using _STLP_VENDOR_CSTD::time_t;
43 #  endif
44 #  include <sys/time.h>
45 #endif
46
47 _STLP_BEGIN_NAMESPACE
48
49 #if (_STLP_STATIC_TEMPLATE_DATA > 0)
50
51 #  if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
52 template<int __32bits>
53 _STLP_STATIC_MUTEX
54 _Atomic_swap_struct<__32bits>::_S_swap_lock _STLP_MUTEX_INITIALIZER;
55 #    undef _STLP_USE_ATOMIC_SWAP_MUTEX
56 #  endif
57
58 #  if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
59 template <int __inst>
60 unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max;
61
62 template <int __inst>
63 unsigned _STLP_mutex_spin<__inst>::__last = 0;
64 #  endif // _STLP_USE_PTHREAD_SPINLOCK
65
66 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
67
68 #  if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
69 __DECLARE_INSTANCE(_STLP_STATIC_MUTEX, _Atomic_swap_struct<sizeof(__stl_atomic_t) == sizeof(void*)>::_S_swap_lock,
70                    _STLP_MUTEX_INITIALIZER  );
71 #    undef _STLP_USE_ATOMIC_SWAP_MUTEX
72 #  endif /* _STLP_PTHREADS */
73
74 #  if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
75 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__max,  =30);
76 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__last, =0);
77 #  endif // _STLP_USE_PTHREAD_SPINLOCK
78
79 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
80
81 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
82
83 #  if defined (_STLP_SPARC_SOLARIS_THREADS)
84 // underground function in libc.so; we do not want dependance on librt
85 extern "C" int __nanosleep(const struct timespec*, struct timespec*);
86 #    define _STLP_NANOSLEEP __nanosleep
87 #  else
88 #    define _STLP_NANOSLEEP nanosleep
89 #  endif
90
91 template <int __inst>
92 void _STLP_CALL
93 _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) {
94 #  if defined (_STLP_WIN32THREADS)
95   if (__log_nsec <= 20) {
96     // Note from boost (www.boost.org):
97     // Changed to Sleep(1) from Sleep(0).
98     // According to MSDN, Sleep(0) will never yield
99     // to a lower-priority thread, whereas Sleep(1)
100     // will. Performance seems not to be affected.
101     Sleep(1);
102   } else {
103     Sleep(1 << (__log_nsec - 20));
104   }
105 #  elif defined(_STLP_OS2THREADS)
106   if (__log_nsec <= 20) {
107     DosSleep(0);
108   } else {
109     DosSleep(1 << (__log_nsec - 20));
110   }
111 #  elif defined (_STLP_UNIX)
112   timespec __ts;
113   /* Max sleep is 2**27nsec ~ 60msec      */
114   __ts.tv_sec = 0;
115   __ts.tv_nsec = 1 << __log_nsec;
116   _STLP_NANOSLEEP(&__ts, 0);
117 #  endif
118 }
119
120 template <int __inst>
121 void  _STLP_CALL
122 _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) {
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   } /* first _Atomic_swap */
160 #  endif
161 }
162 #endif // _STLP_USE_PTHREAD_SPINLOCK
163
164 _STLP_END_NAMESPACE
165
166 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */
167 #endif /*  _STLP_THREADS_C */
168
169 // Local Variables:
170 // mode:C++
171 // End: