/home/ntakagi/work/STLport-5.1.5/stlport/stl/_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 (_STLP_STATIC_TEMPLATE_DATA > 0)
00050 
00051 #  if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
00052 template<int __32bits>
00053 _STLP_STATIC_MUTEX
00054 _Atomic_swap_struct<__32bits>::_S_swap_lock _STLP_MUTEX_INITIALIZER;
00055 #    undef _STLP_USE_ATOMIC_SWAP_MUTEX
00056 #  endif
00057 
00058 #  if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
00059 template <int __inst>
00060 unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max;
00061 
00062 template <int __inst>
00063 unsigned _STLP_mutex_spin<__inst>::__last = 0;
00064 #  endif // _STLP_USE_PTHREAD_SPINLOCK
00065 
00066 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
00067 
00068 #  if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
00069 __DECLARE_INSTANCE(_STLP_STATIC_MUTEX, _Atomic_swap_struct<sizeof(__stl_atomic_t) == sizeof(void*)>::_S_swap_lock,
00070                    _STLP_MUTEX_INITIALIZER  );
00071 #    undef _STLP_USE_ATOMIC_SWAP_MUTEX
00072 #  endif /* _STLP_PTHREADS */
00073 
00074 #  if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
00075 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__max,  =30);
00076 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__last, =0);
00077 #  endif // _STLP_USE_PTHREAD_SPINLOCK
00078 
00079 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
00080 
00081 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
00082 
00083 #  if defined (_STLP_SPARC_SOLARIS_THREADS)
00084 // underground function in libc.so; we do not want dependance on librt
00085 extern "C" int __nanosleep(const struct timespec*, struct timespec*);
00086 #    define _STLP_NANOSLEEP __nanosleep
00087 #  else
00088 #    define _STLP_NANOSLEEP nanosleep
00089 #  endif
00090 
00091 template <int __inst>
00092 void _STLP_CALL
00093 _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) {
00094 #  if defined (_STLP_WIN32THREADS)
00095   if (__log_nsec <= 20) {
00096     // Note from boost (www.boost.org):
00097     // Changed to Sleep(1) from Sleep(0).
00098     // According to MSDN, Sleep(0) will never yield
00099     // to a lower-priority thread, whereas Sleep(1)
00100     // will. Performance seems not to be affected.
00101     Sleep(1);
00102   } else {
00103     Sleep(1 << (__log_nsec - 20));
00104   }
00105 #  elif defined(_STLP_OS2THREADS)
00106   if (__log_nsec <= 20) {
00107     DosSleep(0);
00108   } else {
00109     DosSleep(1 << (__log_nsec - 20));
00110   }
00111 #  elif defined (_STLP_UNIX)
00112   timespec __ts;
00113   /* Max sleep is 2**27nsec ~ 60msec      */
00114   __ts.tv_sec = 0;
00115   __ts.tv_nsec = 1 << __log_nsec;
00116   _STLP_NANOSLEEP(&__ts, 0);
00117 #  endif
00118 }
00119 
00120 template <int __inst>
00121 void  _STLP_CALL
00122 _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) {
00123 #  if defined(_STLP_ATOMIC_EXCHANGE)
00124   if (_Atomic_swap(__lock, 1)) {
00125     unsigned __my_spin_max = _STLP_mutex_spin<0>::__max;
00126     unsigned __my_last_spins = _STLP_mutex_spin<0>::__last;
00127     volatile unsigned __junk = 17;   // Value doesn't matter.
00128     unsigned  __i;
00129 
00130     for (__i = 0; __i < __my_spin_max; ++__i) {
00131       if (__i < __my_last_spins/2 || *__lock) {
00132         __junk *= __junk; __junk *= __junk;
00133         __junk *= __junk; __junk *= __junk;
00134       } else {
00135         if (!_Atomic_swap(__lock, 1)) {
00136           // got it!
00137           // Spinning worked.  Thus we're probably not being scheduled
00138           // against the other process with which we were contending.
00139           // Thus it makes sense to spin longer the next time.
00140           _STLP_mutex_spin<0>::__last = __i;
00141           _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__high_max;
00142           return;
00143         }
00144       }
00145     }
00146 
00147     // We are probably being scheduled against the other process.  Sleep.
00148     _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__low_max;
00149 
00150     for (__i = 0 ;; ++__i) {
00151       int __log_nsec = __i + 6;
00152 
00153       if (__log_nsec > 27) __log_nsec = 27;
00154       if (!_Atomic_swap(__lock, 1)) {
00155         break;
00156       }
00157       _S_nsec_sleep(__log_nsec);
00158     }
00159   } /* first _Atomic_swap */
00160 #  endif
00161 }
00162 #endif // _STLP_USE_PTHREAD_SPINLOCK
00163 
00164 _STLP_END_NAMESPACE
00165 
00166 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */
00167 #endif /*  _STLP_THREADS_C */
00168 
00169 // Local Variables:
00170 // mode:C++
00171 // End:



Generated on Mon Mar 10 15:32:41 2008 by  doxygen 1.5.1