/* * * * Copyright (c) 1994 * Hewlett-Packard Company * * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * * Copyright (c) 1997 * Moscow Center for SPARC Technology * * Copyright (c) 1999 * Boris Fomitchev * * This material is provided "as is", with absolutely no warranty expressed * or implied. Any use is at your own risk. * * Permission to use or copy this software for any purpose is hereby granted * without fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * */ #ifndef __STL_THREADS_C #define __STL_THREADS_C # if defined (__BUILDING_STLPORT) || ! defined (__SGI_STL_OWN_IOSTREAMS) __STL_BEGIN_NAMESPACE # if ( __STL_STATIC_TEMPLATE_DATA > 0 ) # if defined (__STL_PTHREADS) || defined (__STL_UITHREADS) template _STL_STATIC_MUTEX _Swap_lock_struct<__dummy>::_S_swap_lock __STL_MUTEX_INITIALIZER; # endif template unsigned _STL_mutex_spin<__inst>::__max = _STL_mutex_spin<__inst>::__low_max; template unsigned _STL_mutex_spin<__inst>::__last = 0; # else /* ( __STL_STATIC_TEMPLATE_DATA > 0 ) */ # if defined (__STL_PTHREADS) || defined (__STL_UITHREADS) __DECLARE_INSTANCE(_STL_STATIC_MUTEX, _Swap_lock_struct<0>::_S_swap_lock, __STL_MUTEX_INITIALIZER ); # endif /* __STL_PTHREADS */ __DECLARE_INSTANCE(unsigned, _STL_mutex_spin<0>::__max, =30); __DECLARE_INSTANCE(unsigned, _STL_mutex_spin<0>::__last, =0); # endif /* ( __STL_STATIC_TEMPLATE_DATA > 0 ) */ #if defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS) template void __STL_CALL _STL_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) { # ifdef __STL_SGI_THREADS struct timespec __ts; /* Max sleep is 2**27nsec ~ 60msec */ __ts.tv_sec = 0; __ts.tv_nsec = 1 << __log_nsec; nanosleep(&__ts, 0); # elif defined(__STL_WIN32THREADS) if (__log_nsec <= 20) { Sleep(0); } else { Sleep(1 << (__log_nsec - 20)); } # else # error unimplemented # endif } template void __STL_CALL _STL_mutex_spin<__inst>::_M_do_lock(volatile unsigned long* __lock) { #if defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS) if (_Atomic_swap((unsigned long*)__lock, 1)) { unsigned __my_spin_max = _STL_mutex_spin<0>::__max; unsigned __my_last_spins = _STL_mutex_spin<0>::__last; volatile unsigned __junk = 17; // Value doesn't matter. unsigned __i; for (__i = 0; __i < __my_spin_max; ++__i) { if (__i < __my_last_spins/2 || *__lock) { __junk *= __junk; __junk *= __junk; __junk *= __junk; __junk *= __junk; } else { if (!_Atomic_swap((unsigned long*)__lock, 1)) { // got it! // Spinning worked. Thus we're probably not being scheduled // against the other process with which we were contending. // Thus it makes sense to spin longer the next time. _STL_mutex_spin<0>::__last = __i; _STL_mutex_spin<0>::__max = _STL_mutex_spin<0>::__high_max; return; } } } // We are probably being scheduled against the other process. Sleep. _STL_mutex_spin<0>::__max = _STL_mutex_spin<0>::__low_max; for (__i = 0 ;; ++__i) { int __log_nsec = __i + 6; if (__log_nsec > 27) __log_nsec = 27; if (!_Atomic_swap((unsigned long *)__lock, 1)) { break; } _S_nsec_sleep(__log_nsec); } } /* first _Atomic_swap */ # endif } # endif /* if SGI or WIN */ __STL_END_NAMESPACE # endif /* BUILDING_STLPORT */ #endif /* __STL_THREADS_C */ // Local Variables: // mode:C++ // End: