Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygen_threads.c
Go to the documentation of this file.
00001 /* 00002 * 00003 * 00004 * Copyright (c) 1994 00005 * Hewlett-Packard Company 00006 * 00007 * Copyright (c) 1996,1997 00008 * Silicon Graphics Computer Systems, Inc. 00009 * 00010 * Copyright (c) 1997 00011 * Moscow Center for SPARC Technology 00012 * 00013 * Copyright (c) 1999 00014 * Boris Fomitchev 00015 * 00016 * This material is provided "as is", with absolutely no warranty expressed 00017 * or implied. Any use is at your own risk. 00018 * 00019 * Permission to use or copy this software for any purpose is hereby granted 00020 * without fee, provided the above notices are retained on all copies. 00021 * Permission to modify the code and to distribute modified code is granted, 00022 * provided the above notices are retained, and a notice that the code was 00023 * modified is included with the above copyright notice. 00024 * 00025 */ 00026 #ifndef _STLP_THREADS_C 00027 #define _STLP_THREADS_C 00028 00029 #ifndef _STLP_INTERNAL_THREADS_H 00030 # include <stl/_threads.h> 00031 #endif 00032 00033 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) 00034 00035 #if defined (_STLP_SGI_THREADS) 00036 # include <time.h> 00037 #elif defined (_STLP_UNIX) 00038 # ifndef _STLP_INTERNAL_CTIME 00039 # include <stl/_ctime.h> 00040 # endif 00041 # if defined (_STLP_USE_NAMESPACES) && !defined (_STLP_VENDOR_GLOBAL_CSTD) 00042 using _STLP_VENDOR_CSTD::time_t; 00043 # endif 00044 # include <sys/time.h> 00045 #endif 00046 00047 _STLP_BEGIN_NAMESPACE 00048 00049 #if defined (_STLP_USE_ATOMIC_SWAP_MUTEX) 00050 template<int __32bits> 00051 _STLP_STATIC_MUTEX 00052 _Atomic_swap_struct<__32bits>::_S_swap_lock _STLP_MUTEX_INITIALIZER; 00053 # undef _STLP_USE_ATOMIC_SWAP_MUTEX 00054 #endif 00055 00056 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK) 00057 template <int __inst> 00058 unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max; 00059 00060 template <int __inst> 00061 unsigned _STLP_mutex_spin<__inst>::__last = 0; 00062 #endif // _STLP_USE_PTHREAD_SPINLOCK 00063 00064 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK) 00065 00066 # if defined (_STLP_SPARC_SOLARIS_THREADS) 00067 // underground function in libc.so; we do not want dependance on librt 00068 extern "C" int __nanosleep(const struct timespec*, struct timespec*); 00069 # define _STLP_NANOSLEEP __nanosleep 00070 # else 00071 # define _STLP_NANOSLEEP nanosleep 00072 # endif 00073 00074 template <int __inst> 00075 void _STLP_CALL 00076 _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec, unsigned int& __iteration) { 00077 # if defined (_STLP_WIN32THREADS) 00078 # if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) 00079 if (__iteration <= 4000) { 00080 // Use SwitchToThread because 00081 // 1) Sleep(1) often takes ~15 ms 00082 // 2) SwitchToThread yields to lower-priority threads 00083 // 4000 is enough to avoid Sleep and is used just to prevent infinite looping 00084 // This number is advised spin count for Heap management by Microsoft 00085 SwitchToThread(); 00086 } else { 00087 # endif 00088 if (__log_nsec <= 21) { 00089 /* Note from boost (www.boost.org): 00090 * Changed from Sleep(0) to Sleep(1). 00091 * According to MSDN, Sleep(0) will never yield to a lower-priority thread, 00092 * whereas Sleep(1) will. Performance seems not to be affected. */ 00093 Sleep(1); 00094 } else { 00095 Sleep(1 << (__log_nsec - 20)); 00096 } 00097 # if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) 00098 __iteration = 0; //reset to avoid sleeps sequence 00099 } 00100 # endif 00101 # elif defined(_STLP_OS2THREADS) 00102 if (__log_nsec <= 20) { 00103 DosSleep(0); 00104 } else { 00105 DosSleep(1 << (__log_nsec - 20)); 00106 } 00107 # elif defined (_STLP_UNIX) 00108 timespec __ts; 00109 /* Max sleep is 2**27nsec ~ 60msec */ 00110 __ts.tv_sec = 0; 00111 __ts.tv_nsec = 1 << __log_nsec; 00112 _STLP_NANOSLEEP(&__ts, 0); 00113 # endif 00114 } 00115 00116 template <int __inst> 00117 void _STLP_CALL 00118 _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) { 00119 # if defined(_STLP_ATOMIC_EXCHANGE) 00120 if (_Atomic_swap(__lock, 1)) { 00121 unsigned __my_spin_max = _STLP_mutex_spin<0>::__max; 00122 unsigned __my_last_spins = _STLP_mutex_spin<0>::__last; 00123 volatile unsigned __junk = 17; // Value doesn't matter. 00124 unsigned __i; 00125 00126 for (__i = 0; __i < __my_spin_max; ++__i) { 00127 if (__i < __my_last_spins/2 || *__lock) { 00128 __junk *= __junk; __junk *= __junk; 00129 __junk *= __junk; __junk *= __junk; 00130 } else { 00131 if (!_Atomic_swap(__lock, 1)) { 00132 // got it! 00133 // Spinning worked. Thus we're probably not being scheduled 00134 // against the other process with which we were contending. 00135 // Thus it makes sense to spin longer the next time. 00136 _STLP_mutex_spin<0>::__last = __i; 00137 _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__high_max; 00138 return; 00139 } 00140 } 00141 } 00142 00143 // We are probably being scheduled against the other process. Sleep. 00144 _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__low_max; 00145 00146 for (__i = 0 ;; ++__i) { 00147 int __log_nsec = __i + 6; 00148 00149 if (__log_nsec > 27) __log_nsec = 27; 00150 if (!_Atomic_swap(__lock, 1)) { 00151 break; 00152 } 00153 _S_nsec_sleep(__log_nsec, __i); 00154 } 00155 } /* first _Atomic_swap */ 00156 # endif 00157 } 00158 #endif // _STLP_USE_PTHREAD_SPINLOCK 00159 00160 _STLP_END_NAMESPACE 00161 00162 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */ 00163 #endif /* _STLP_THREADS_C */ 00164 00165 // Local Variables: 00166 // mode:C++ 00167 // End: Generated on Sun May 27 2012 04:29:38 for ReactOS by
1.7.6.1
|