williamr@2: /* williamr@4: * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 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@4: * 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@4: * 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@4: # include williamr@2: #endif williamr@2: williamr@4: #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) williamr@2: williamr@4: #if defined (_STLP_SGI_THREADS) williamr@2: # include williamr@4: #elif defined (_STLP_UNIX) williamr@4: # ifndef _STLP_INTERNAL_CTIME williamr@4: # include williamr@4: # endif williamr@4: # if defined (_STLP_USE_NAMESPACES) && !defined (_STLP_VENDOR_GLOBAL_CSTD) williamr@2: using _STLP_VENDOR_CSTD::time_t; williamr@4: # endif williamr@2: # include williamr@4: #endif williamr@2: williamr@2: _STLP_BEGIN_NAMESPACE williamr@2: williamr@4: #if (_STLP_STATIC_TEMPLATE_DATA > 0) williamr@2: williamr@4: # if defined (_STLP_USE_ATOMIC_SWAP_MUTEX) williamr@4: #if !defined(__SYMBIAN32__WSD__) williamr@4: template williamr@2: _STLP_STATIC_MUTEX williamr@4: _Atomic_swap_struct<__32bits>::_S_swap_lock _STLP_MUTEX_INITIALIZER; williamr@4: #endif williamr@4: # undef _STLP_USE_ATOMIC_SWAP_MUTEX williamr@2: # endif williamr@2: williamr@4: # if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK) williamr@4: //Note: For SYMBIAN Emulator, these entries are to be considered WSD. williamr@4: //Still, EWSD solution can't be applied since it's templated. 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@4: williamr@2: # endif // _STLP_USE_PTHREAD_SPINLOCK williamr@2: williamr@4: #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ williamr@2: williamr@4: # if defined (_STLP_USE_ATOMIC_SWAP_MUTEX) williamr@4: __DECLARE_INSTANCE(_STLP_STATIC_MUTEX, _Atomic_swap_struct::_S_swap_lock, williamr@2: _STLP_MUTEX_INITIALIZER ); williamr@4: # undef _STLP_USE_ATOMIC_SWAP_MUTEX williamr@2: # endif /* _STLP_PTHREADS */ williamr@2: williamr@4: # if defined (_STLP_THREADS) && !defined (_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@4: #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */ williamr@2: williamr@4: #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK) williamr@2: williamr@4: # if defined (_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@4: # define _STLP_NANOSLEEP __nanosleep williamr@4: # else williamr@4: # define _STLP_NANOSLEEP nanosleep williamr@4: # endif williamr@2: williamr@2: template williamr@2: void _STLP_CALL williamr@2: _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) { williamr@4: # if defined (_STLP_WIN32THREADS) williamr@4: if (__log_nsec <= 20) { williamr@4: // Note from boost (www.boost.org): williamr@4: // Changed to Sleep(1) from Sleep(0). williamr@4: // According to MSDN, Sleep(0) will never yield williamr@4: // to a lower-priority thread, whereas Sleep(1) williamr@4: // will. Performance seems not to be affected. williamr@4: Sleep(1); williamr@4: } else { williamr@4: Sleep(1 << (__log_nsec - 20)); williamr@2: } williamr@4: # elif defined(_STLP_OS2THREADS) williamr@4: if (__log_nsec <= 20) { williamr@4: DosSleep(0); williamr@4: } else { williamr@4: DosSleep(1 << (__log_nsec - 20)); williamr@4: } williamr@4: # elif defined (_STLP_UNIX) williamr@4: timespec __ts; williamr@4: /* Max sleep is 2**27nsec ~ 60msec */ williamr@4: __ts.tv_sec = 0; williamr@4: __ts.tv_nsec = 1 << __log_nsec; williamr@4: _STLP_NANOSLEEP(&__ts, 0); williamr@4: # endif williamr@4: } williamr@2: williamr@2: template williamr@2: void _STLP_CALL williamr@4: _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) { williamr@4: # 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@4: volatile unsigned __junk = 17; // Value doesn't matter. williamr@2: unsigned __i; williamr@4: 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@4: return; williamr@2: } williamr@2: } williamr@2: } williamr@4: 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@4: williamr@2: for (__i = 0 ;; ++__i) { williamr@2: int __log_nsec = __i + 6; williamr@4: williamr@2: if (__log_nsec > 27) __log_nsec = 27; williamr@2: if (!_Atomic_swap(__lock, 1)) { williamr@4: break; williamr@2: } williamr@2: _S_nsec_sleep(__log_nsec); williamr@2: } williamr@2: } /* first _Atomic_swap */ williamr@4: # endif williamr@2: } williamr@2: #endif // _STLP_USE_PTHREAD_SPINLOCK williamr@2: williamr@2: _STLP_END_NAMESPACE williamr@2: williamr@4: #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */ williamr@2: #endif /* _STLP_THREADS_C */ williamr@2: williamr@2: // Local Variables: williamr@2: // mode:C++ williamr@2: // End: