ReactOS  0.4.14-dev-815-ge410a12
_threads.c
Go to the documentation of this file.
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)
43 # endif
44 # include <sys/time.h>
45 #endif
46 
48 
49 #if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
50 template<int __32bits>
53 # undef _STLP_USE_ATOMIC_SWAP_MUTEX
54 #endif
55 
56 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
57 template <int __inst>
58 unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max;
59 
60 template <int __inst>
62 #endif // _STLP_USE_PTHREAD_SPINLOCK
63 
64 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
65 
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
70 # else
71 # define _STLP_NANOSLEEP nanosleep
72 # endif
73 
74 template <int __inst>
75 void _STLP_CALL
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
85  SwitchToThread();
86  } else {
87 # endif
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. */
93  Sleep(1);
94  } else {
95  Sleep(1 << (__log_nsec - 20));
96  }
97 # if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
98  __iteration = 0; //reset to avoid sleeps sequence
99  }
100 # endif
101 # elif defined(_STLP_OS2THREADS)
102  if (__log_nsec <= 20) {
103  DosSleep(0);
104  } else {
105  DosSleep(1 << (__log_nsec - 20));
106  }
107 # elif defined (_STLP_UNIX)
108  timespec __ts;
109  /* Max sleep is 2**27nsec ~ 60msec */
110  __ts.tv_sec = 0;
111  __ts.tv_nsec = 1 << __log_nsec;
112  _STLP_NANOSLEEP(&__ts, 0);
113 # endif
114 }
115 
116 template <int __inst>
117 void _STLP_CALL
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.
124  unsigned __i;
125 
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;
130  } else {
131  if (!_Atomic_swap(__lock, 1)) {
132  // got it!
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.
137  _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__high_max;
138  return;
139  }
140  }
141  }
142 
143  // We are probably being scheduled against the other process. Sleep.
144  _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__low_max;
145 
146  for (__i = 0 ;; ++__i) {
147  int __log_nsec = __i + 6;
148 
149  if (__log_nsec > 27) __log_nsec = 27;
150  if (!_Atomic_swap(__lock, 1)) {
151  break;
152  }
153  _S_nsec_sleep(__log_nsec, __i);
154  }
155  } /* first _Atomic_swap */
156 # endif
157 }
158 #endif // _STLP_USE_PTHREAD_SPINLOCK
159 
161 
162 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */
163 #endif /* _STLP_THREADS_C */
164 
165 // Local Variables:
166 // mode:C++
167 // End:
BOOL WINAPI SwitchToThread(VOID)
Definition: thread.c:447
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
#define _STLP_STATIC_MUTEX
Definition: features.h:267
time_t tv_sec
Definition: time.h:89
_STLP_INLINE_LOOP _InputIter __last
Definition: _algo.h:68
long tv_nsec
Definition: time.h:90
#define _STLP_MUTEX_INITIALIZER
Definition: _threads.h:241
__kernel_time_t time_t
Definition: linux.h:252
#define _STLP_END_NAMESPACE
Definition: features.h:503
#define __max(a, b)
Definition: stdlib.h:113
Definition: time.h:88
#define _STLP_BEGIN_NAMESPACE
Definition: features.h:501
size_t __stl_atomic_t
Definition: _threads.h:232
__stl_atomic_t _STLP_CALL _Atomic_swap(_STLP_VOLATILE __stl_atomic_t *__p, __stl_atomic_t __q)
Definition: _threads.h:623
#define _STLP_CALL
Definition: _bc.h:131