stl_threads.h
来自「ARM Linux Tool 各种代码包括MTD」· C头文件 代码 · 共 513 行 · 第 1/2 页
H
513 行
}# else static inline unsigned long _Atomic_swap(unsigned long * __p, unsigned long __q) { unsigned long __result = *__p; *__p = __q; return __result; }# endif// GCC extension begin#endif// GCC extension end// Locking class. Note that this class *does not have a constructor*.// It must be initialized either statically, with __STL_MUTEX_INITIALIZER,// or dynamically, by explicitly calling the _M_initialize member function.// (This is similar to the ways that a pthreads mutex can be initialized.)// There are explicit member functions for acquiring and releasing the lock.// There is no constructor because static initialization is essential for// some uses, and only a class aggregate (see section 8.5.1 of the C++// standard) can be initialized that way. That means we must have no// constructors, no base classes, no virtual functions, and no private or// protected members.// Helper struct. This is a workaround for various compilers that don't// handle static variables in inline functions properly.template <int __inst>struct _STL_mutex_spin { enum { __low_max = 30, __high_max = 1000 }; // Low if we suspect uniprocessor, high for multiprocessor. static unsigned __max; static unsigned __last;};template <int __inst>unsigned _STL_mutex_spin<__inst>::__max = _STL_mutex_spin<__inst>::__low_max;template <int __inst>unsigned _STL_mutex_spin<__inst>::__last = 0;// GCC extension begin#if defined(__STL_GTHREADS)#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)extern __gthread_mutex_t _GLIBCPP_mutex;extern __gthread_mutex_t *_GLIBCPP_mutex_address;extern __gthread_once_t _GLIBCPP_once;extern void _GLIBCPP_mutex_init (void);extern void _GLIBCPP_mutex_address_init (void);#endif#endif// GCC extension endstruct _STL_mutex_lock{// GCC extension begin#if defined(__STL_GTHREADS) // The class must be statically initialized with __STL_MUTEX_INITIALIZER.#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) volatile int _M_init_flag; __gthread_once_t _M_once;#endif __gthread_mutex_t _M_lock; void _M_initialize() {#ifdef __GTHREAD_MUTEX_INIT // There should be no code in this path given the usage rules above.#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) if (_M_init_flag) return; if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0 && __gthread_active_p ()) abort (); __gthread_mutex_lock (&_GLIBCPP_mutex); if (!_M_init_flag) { // Even though we have a global lock, we use __gthread_once to be // absolutely certain the _M_lock mutex is only initialized once on // multiprocessor systems. _GLIBCPP_mutex_address = &_M_lock; if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0 && __gthread_active_p ()) abort (); _M_init_flag = 1; } __gthread_mutex_unlock (&_GLIBCPP_mutex);#endif } void _M_acquire_lock() {#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) if (!_M_init_flag) _M_initialize();#endif __gthread_mutex_lock(&_M_lock); } void _M_release_lock() {#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) if (!_M_init_flag) _M_initialize();#endif __gthread_mutex_unlock(&_M_lock); }#else// GCC extension end#if defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS) // It should be relatively easy to get this to work on any modern Unix. volatile unsigned long _M_lock; void _M_initialize() { _M_lock = 0; } static void _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 = 1L << __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 } void _M_acquire_lock() { volatile unsigned long* __lock = &this->_M_lock; if (!_Atomic_swap((unsigned long*)__lock, 1)) { return; } 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; continue; } 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)) { return; } _S_nsec_sleep(__log_nsec); } } void _M_release_lock() { volatile unsigned long* __lock = &_M_lock;# if defined(__STL_SGI_THREADS) && defined(__GNUC__) && __mips >= 3 asm("sync"); *__lock = 0;# elif defined(__STL_SGI_THREADS) && __mips >= 3 \ && (defined (_ABIN32) || defined(_ABI64)) __lock_release(__lock);# else *__lock = 0; // This is not sufficient on many multiprocessors, since // writes to protected variables and the lock may be reordered.# endif }// We no longer use win32 critical sections.// They appear to be slower in the contention-free case,// and they appear difficult to initialize without introducing a race.#elif defined(__STL_PTHREADS) pthread_mutex_t _M_lock; void _M_initialize() { pthread_mutex_init(&_M_lock, NULL); } void _M_acquire_lock() { pthread_mutex_lock(&_M_lock); } void _M_release_lock() { pthread_mutex_unlock(&_M_lock); }#elif defined(__STL_UITHREADS) mutex_t _M_lock; void _M_initialize() { mutex_init(&_M_lock, USYNC_THREAD, 0); } void _M_acquire_lock() { mutex_lock(&_M_lock); } void _M_release_lock() { mutex_unlock(&_M_lock); }#else /* No threads */ void _M_initialize() {} void _M_acquire_lock() {} void _M_release_lock() {}#endif// GCC extension begin#endif// GCC extension end};// GCC extension begin#if defined(__STL_GTHREADS)#ifdef __GTHREAD_MUTEX_INIT#define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT }#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)#ifdef __GTHREAD_MUTEX_INIT_DEFAULT#define __STL_MUTEX_INITIALIZER \ = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT }#else#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT }#endif#endif#else// GCC extension end#ifdef __STL_PTHREADS// Pthreads locks must be statically initialized to something other than// the default value of zero.# define __STL_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER }#elif defined(__STL_UITHREADS)// UIthreads locks must be statically initialized to something other than// the default value of zero.# define __STL_MUTEX_INITIALIZER = { DEFAULTMUTEX }#elif defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS)# define __STL_MUTEX_INITIALIZER = { 0 }#else# define __STL_MUTEX_INITIALIZER#endif// GCC extension begin#endif// GCC extension end// A locking class that uses _STL_mutex_lock. The constructor takes a// reference to an _STL_mutex_lock, and acquires a lock. The// destructor releases the lock. It's not clear that this is exactly// the right functionality. It will probably change in the future.struct _STL_auto_lock{ _STL_mutex_lock& _M_lock; _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock) { _M_lock._M_acquire_lock(); } ~_STL_auto_lock() { _M_lock._M_release_lock(); }private: void operator=(const _STL_auto_lock&); _STL_auto_lock(const _STL_auto_lock&);};} // namespace std#endif /* __SGI_STL_INTERNAL_THREADS_H */// Local Variables:// mode:C++// End:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?