epoc32/include/tools/stlport/stl/_threads.c
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 /*
     2  *
     3  *
     4  * Copyright (c) 1994
     5  * Hewlett-Packard Company
     6  *
     7  * Copyright (c) 1996,1997
     8  * Silicon Graphics Computer Systems, Inc.
     9  *
    10  * Copyright (c) 1997
    11  * Moscow Center for SPARC Technology
    12  *
    13  * Copyright (c) 1999
    14  * Boris Fomitchev
    15  *
    16  * This material is provided "as is", with absolutely no warranty expressed
    17  * or implied. Any use is at your own risk.
    18  *
    19  * Permission to use or copy this software for any purpose is hereby granted
    20  * without fee, provided the above notices are retained on all copies.
    21  * Permission to modify the code and to distribute modified code is granted,
    22  * provided the above notices are retained, and a notice that the code was
    23  * modified is included with the above copyright notice.
    24  *
    25  */
    26 #ifndef _STLP_THREADS_C
    27 #define _STLP_THREADS_C
    28 
    29 #ifndef _STLP_INTERNAL_THREADS_H
    30 #  include <stl/_threads.h>
    31 #endif
    32 
    33 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
    34 
    35 #if defined (_STLP_SGI_THREADS)
    36 #  include <time.h>
    37 #elif defined (_STLP_UNIX)
    38 #  ifndef _STLP_INTERNAL_CTIME
    39 #    include <stl/_ctime.h>
    40 #  endif
    41 #  if defined (_STLP_USE_NAMESPACES) && !defined (_STLP_VENDOR_GLOBAL_CSTD)
    42 using _STLP_VENDOR_CSTD::time_t;
    43 #  endif
    44 #  include <sys/time.h>
    45 #endif
    46 
    47 _STLP_BEGIN_NAMESPACE
    48 
    49 #if (_STLP_STATIC_TEMPLATE_DATA > 0)
    50 
    51 #  if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
    52 template<int __32bits>
    53 _STLP_STATIC_MUTEX
    54 _Atomic_swap_struct<__32bits>::_S_swap_lock _STLP_MUTEX_INITIALIZER;
    55 #    undef _STLP_USE_ATOMIC_SWAP_MUTEX
    56 #  endif
    57 
    58 #  if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
    59 template <int __inst>
    60 unsigned _STLP_mutex_spin<__inst>::__max = _STLP_mutex_spin<__inst>::__low_max;
    61 
    62 template <int __inst>
    63 unsigned _STLP_mutex_spin<__inst>::__last = 0;
    64 #  endif // _STLP_USE_PTHREAD_SPINLOCK
    65 
    66 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
    67 
    68 #  if defined (_STLP_USE_ATOMIC_SWAP_MUTEX)
    69 __DECLARE_INSTANCE(_STLP_STATIC_MUTEX, _Atomic_swap_struct<sizeof(__stl_atomic_t) == sizeof(void*)>::_S_swap_lock,
    70                    _STLP_MUTEX_INITIALIZER  );
    71 #    undef _STLP_USE_ATOMIC_SWAP_MUTEX
    72 #  endif /* _STLP_PTHREADS */
    73 
    74 #  if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
    75 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__max,  =30);
    76 __DECLARE_INSTANCE(unsigned, _STLP_mutex_spin<0>::__last, =0);
    77 #  endif // _STLP_USE_PTHREAD_SPINLOCK
    78 
    79 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
    80 
    81 #if defined (_STLP_THREADS) && !defined (_STLP_USE_PTHREAD_SPINLOCK)
    82 
    83 #  if defined (_STLP_SPARC_SOLARIS_THREADS)
    84 // underground function in libc.so; we do not want dependance on librt
    85 extern "C" int __nanosleep(const struct timespec*, struct timespec*);
    86 #    define _STLP_NANOSLEEP __nanosleep
    87 #  else
    88 #    define _STLP_NANOSLEEP nanosleep
    89 #  endif
    90 
    91 template <int __inst>
    92 void _STLP_CALL
    93 _STLP_mutex_spin<__inst>::_S_nsec_sleep(int __log_nsec) {
    94 #  if defined (_STLP_WIN32THREADS)
    95   if (__log_nsec <= 20) {
    96     // Note from boost (www.boost.org):
    97     // Changed to Sleep(1) from Sleep(0).
    98     // According to MSDN, Sleep(0) will never yield
    99     // to a lower-priority thread, whereas Sleep(1)
   100     // will. Performance seems not to be affected.
   101     Sleep(1);
   102   } else {
   103     Sleep(1 << (__log_nsec - 20));
   104   }
   105 #  elif defined(_STLP_OS2THREADS)
   106   if (__log_nsec <= 20) {
   107     DosSleep(0);
   108   } else {
   109     DosSleep(1 << (__log_nsec - 20));
   110   }
   111 #  elif defined (_STLP_UNIX)
   112   timespec __ts;
   113   /* Max sleep is 2**27nsec ~ 60msec      */
   114   __ts.tv_sec = 0;
   115   __ts.tv_nsec = 1 << __log_nsec;
   116   _STLP_NANOSLEEP(&__ts, 0);
   117 #  endif
   118 }
   119 
   120 template <int __inst>
   121 void  _STLP_CALL
   122 _STLP_mutex_spin<__inst>::_M_do_lock(volatile __stl_atomic_t* __lock) {
   123 #  if defined(_STLP_ATOMIC_EXCHANGE)
   124   if (_Atomic_swap(__lock, 1)) {
   125     unsigned __my_spin_max = _STLP_mutex_spin<0>::__max;
   126     unsigned __my_last_spins = _STLP_mutex_spin<0>::__last;
   127     volatile unsigned __junk = 17;   // Value doesn't matter.
   128     unsigned  __i;
   129 
   130     for (__i = 0; __i < __my_spin_max; ++__i) {
   131       if (__i < __my_last_spins/2 || *__lock) {
   132         __junk *= __junk; __junk *= __junk;
   133         __junk *= __junk; __junk *= __junk;
   134       } else {
   135         if (!_Atomic_swap(__lock, 1)) {
   136           // got it!
   137           // Spinning worked.  Thus we're probably not being scheduled
   138           // against the other process with which we were contending.
   139           // Thus it makes sense to spin longer the next time.
   140           _STLP_mutex_spin<0>::__last = __i;
   141           _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__high_max;
   142           return;
   143         }
   144       }
   145     }
   146 
   147     // We are probably being scheduled against the other process.  Sleep.
   148     _STLP_mutex_spin<0>::__max = _STLP_mutex_spin<0>::__low_max;
   149 
   150     for (__i = 0 ;; ++__i) {
   151       int __log_nsec = __i + 6;
   152 
   153       if (__log_nsec > 27) __log_nsec = 27;
   154       if (!_Atomic_swap(__lock, 1)) {
   155         break;
   156       }
   157       _S_nsec_sleep(__log_nsec);
   158     }
   159   } /* first _Atomic_swap */
   160 #  endif
   161 }
   162 #endif // _STLP_USE_PTHREAD_SPINLOCK
   163 
   164 _STLP_END_NAMESPACE
   165 
   166 #endif /* _STLP_EXPOSE_GLOBALS_IMPLEMENTATION */
   167 #endif /*  _STLP_THREADS_C */
   168 
   169 // Local Variables:
   170 // mode:C++
   171 // End: