ReactOS 0.4.15-dev-8222-g9164419
_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)
42using _STLP_VENDOR_CSTD::time_t;
43# endif
44# include <sys/time.h>
45#endif
46
48
49#if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
50template<int __32bits>
53# undef _STLP_USE_ATOMIC_SWAP_MUTEX
54#endif
55
56#if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
57template <int __inst>
58unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max;
59
60template <int __inst>
61unsigned _STLP_mutex_spin<__inst>::__last = 0;
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
68extern "C" int __nanosleep(const struct timespec*, struct timespec*);
69# define _STLP_NANOSLEEP __nanosleep
70# else
71# define _STLP_NANOSLEEP nanosleep
72# endif
73
74template <int __inst>
75void _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
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
116template <int __inst>
117void _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.
136 _STLP_mutex_spin<0>::__last = __i;
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:
#define _STLP_CALL
Definition: _bc.h:131
size_t __stl_atomic_t
Definition: _threads.h:232
#define _STLP_MUTEX_INITIALIZER
Definition: _threads.h:241
__stl_atomic_t _STLP_CALL _Atomic_swap(_STLP_VOLATILE __stl_atomic_t *__p, __stl_atomic_t __q)
Definition: _threads.h:623
#define _STLP_STATIC_MUTEX
Definition: features.h:267
#define _STLP_BEGIN_NAMESPACE
Definition: features.h:501
#define _STLP_END_NAMESPACE
Definition: features.h:503
Definition: time.h:88
long tv_nsec
Definition: time.h:90
time_t tv_sec
Definition: time.h:89
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
BOOL WINAPI SwitchToThread(void)
Definition: thread.c:448