williamr@2: /* williamr@2: * williamr@2: * williamr@2: * Copyright (c) 1994 williamr@2: * Hewlett-Packard Company williamr@2: * williamr@2: * Copyright (c) 1996,1997 williamr@2: * Silicon Graphics Computer Systems, Inc. williamr@2: * williamr@2: * Copyright (c) 1997 williamr@2: * Moscow Center for SPARC Technology williamr@2: * williamr@2: * Copyright (c) 1999 williamr@2: * Boris Fomitchev williamr@2: * williamr@2: * This material is provided "as is", with absolutely no warranty expressed williamr@2: * or implied. Any use is at your own risk. williamr@2: * williamr@2: * Permission to use or copy this software for any purpose is hereby granted williamr@2: * without fee, provided the above notices are retained on all copies. williamr@2: * Permission to modify the code and to distribute modified code is granted, williamr@2: * provided the above notices are retained, and a notice that the code was williamr@2: * modified is included with the above copyright notice. williamr@2: * williamr@2: */ williamr@2: #ifndef _STLP_THREADS_C williamr@2: #define _STLP_THREADS_C williamr@2: williamr@2: #ifndef _STLP_INTERNAL_THREADS_H williamr@2: # include williamr@2: #endif williamr@2: williamr@2: # if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) williamr@2: williamr@2: # if defined(_STLP_SGI_THREADS) williamr@2: # include williamr@2: # elif defined (_STLP_UNIX) williamr@2: # include williamr@2: # if defined (_STLP_USE_NAMESPACES) && ! defined (_STLP_VENDOR_GLOBAL_CSTD) williamr@2: using _STLP_VENDOR_CSTD::time_t; williamr@2: # endif williamr@2: # include williamr@2: # endif williamr@2: williamr@2: _STLP_BEGIN_NAMESPACE williamr@2: williamr@2: # if (_STLP_STATIC_TEMPLATE_DATA > 0) williamr@2: williamr@2: # ifdef _STLP_THREADS williamr@2: # if !defined(_STLP_ATOMIC_EXCHANGE) && (defined(_STLP_PTHREADS) || defined(_STLP_UITHREADS) || defined(_STLP_OS2THREADS) || defined(_STLP_USE_PTHREAD_SPINLOCK)) williamr@2: template williamr@2: _STLP_STATIC_MUTEX williamr@2: _Swap_lock_struct<__dummy>::_S_swap_lock _STLP_MUTEX_INITIALIZER; williamr@2: # endif williamr@2: # endif //_STLP_THREADS williamr@2: williamr@2: # ifndef _STLP_USE_PTHREAD_SPINLOCK williamr@2: template williamr@2: unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max; williamr@2: williamr@2: template williamr@2: unsigned _STLP_mutex_spin<__inst>::__last = 0; williamr@2: # endif // _STLP_USE_PTHREAD_SPINLOCK williamr@2: williamr@2: # else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ williamr@2: williamr@2: # if defined(_STLP_PTHREADS) || defined(_STLP_UITHREADS) || defined(_STLP_OS2THREADS) williamr@2: __DECLARE_INSTANCE(_STLP_STATIC_MUTEX, _Swap_lock_struct<0>::_S_swap_lock, williamr@2: _STLP_MUTEX_INITIALIZER ); williamr@2: # endif /* _STLP_PTHREADS */ williamr@2: williamr@2: # ifndef _STLP_USE_PTHREAD_SPINLOCK williamr@2: __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__max, =30); williamr@2: __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__last, =0); williamr@2: # endif // _STLP_USE_PTHREAD_SPINLOCK williamr@2: williamr@2: # endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ williamr@2: williamr@2: #ifndef _STLP_USE_PTHREAD_SPINLOCK williamr@2: williamr@2: #ifdef _STLP_SPARC_SOLARIS_THREADS williamr@2: // underground function in libc.so; we do not want dependance on librt williamr@2: extern "C" int __nanosleep(const struct timespec*, struct timespec*); williamr@2: # define _STLP_NANOSLEEP __nanosleep williamr@2: #else williamr@2: # define _STLP_NANOSLEEP nanosleep williamr@2: #endif williamr@2: williamr@2: template williamr@2: void _STLP_CALL williamr@2: _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) { williamr@2: # if defined(_STLP_WIN32THREADS) williamr@2: if (__log_nsec <= 20) { williamr@2: // Note from boost (www.boost.org): williamr@2: // Changed to Sleep(1) from Sleep(0). williamr@2: // According to MSDN, Sleep(0) will never yield williamr@2: // to a lower-priority thread, whereas Sleep(1) williamr@2: // will. Performance seems not to be affected. williamr@2: Sleep(1); williamr@2: } else { williamr@2: Sleep(1 << (__log_nsec - 20)); williamr@2: } williamr@2: # elif defined(_STLP_OS2THREADS) williamr@2: if (__log_nsec <= 20) { williamr@2: DosSleep(0); williamr@2: } else { williamr@2: DosSleep(1 << (__log_nsec - 20)); williamr@2: } williamr@2: # elif defined (_STLP_UNIX) williamr@2: timespec __ts; williamr@2: /* Max sleep is 2**27nsec ~ 60msec */ williamr@2: __ts.tv_sec = 0; williamr@2: __ts.tv_nsec = 1 << __log_nsec; williamr@2: _STLP_NANOSLEEP(&__ts, 0); williamr@2: # endif williamr@2: } williamr@2: williamr@2: williamr@2: template williamr@2: void _STLP_CALL williamr@2: _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) williamr@2: { williamr@2: #if defined(_STLP_ATOMIC_EXCHANGE) williamr@2: if (_Atomic_swap(__lock, 1)) { williamr@2: unsigned __my_spin_max = _STLP_mutex_spin<0>::__max; williamr@2: unsigned __my_last_spins = _STLP_mutex_spin<0>::__last; williamr@2: volatile unsigned __junk = 17; // Value doesn't matter. williamr@2: unsigned __i; williamr@2: williamr@2: for (__i = 0; __i < __my_spin_max; ++__i) { williamr@2: if (__i < __my_last_spins/2 || *__lock) { williamr@2: __junk *= __junk; __junk *= __junk; williamr@2: __junk *= __junk; __junk *= __junk; williamr@2: } else { williamr@2: if (!_Atomic_swap(__lock, 1)) { williamr@2: // got it! williamr@2: // Spinning worked. Thus we're probably not being scheduled williamr@2: // against the other process with which we were contending. williamr@2: // Thus it makes sense to spin longer the next time. williamr@2: _STLP_mutex_spin<0>::__last = __i; williamr@2: _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__high_max; williamr@2: return; williamr@2: } williamr@2: } williamr@2: } williamr@2: williamr@2: // We are probably being scheduled against the other process. Sleep. williamr@2: _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__low_max; williamr@2: williamr@2: for (__i = 0 ;; ++__i) { williamr@2: int __log_nsec = __i + 6; williamr@2: williamr@2: if (__log_nsec > 27) __log_nsec = 27; williamr@2: if (!_Atomic_swap(__lock, 1)) { williamr@2: break; williamr@2: } williamr@2: _S_nsec_sleep(__log_nsec); williamr@2: } williamr@2: williamr@2: } /* first _Atomic_swap */ williamr@2: # endif williamr@2: } williamr@2: #endif // _STLP_USE_PTHREAD_SPINLOCK williamr@2: williamr@2: _STLP_END_NAMESPACE williamr@2: williamr@2: # endif /* BUILDING_STLPORT */ williamr@2: #endif /* _STLP_THREADS_C */ williamr@2: williamr@2: // Local Variables: williamr@2: // mode:C++ williamr@2: // End: