123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- #include "precompile.h"
- #include "spinlock.h"
- static void tkspause()
- {
- #if defined __x86_64__ || defined __i386__
- #ifdef __SSE2__
- __asm__ __volatile__ ("pause");
- #else
- __asm__ __volatile__ ("rep; nop");
- #endif
- #elif defined __arm__
- #if __ARM_ARCH == 7
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- #endif
- #elif defined __OCTEON__
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- __asm__ __volatile__ ("nop");
- #elif defined __powerpc__
- __asm__ __volatile__ ("ori 27, 27, 27");
- #endif
- }
- // please refer http://book.opensourceproject.org.cn/kernel/kernel3rd/opensource/0596005652/understandlk-chp-5-sect-2.html
- static __inline void backoff(unsigned int nloop)
- {
- //and d, s d <- d & s
- //if ZF d, s
- #if defined _WIN32 // __x86_64__ || defined __i386__
- __asm {
- and ecx, nloop;
- cmovz ecx, nloop;
- rep nop;
- }
- #elif defined(__linux__)
- #if defined(__arm__) || defined(__aarch64__)
- //TODO:
- #else
- //TODO: need to confirm its correctness.
- __asm__ __volatile__ ("and %edi, %ecx;"
- "cmovz %edi, %ecx;"
- "rep;"
- "nop");
- #endif
- #endif
- }
- TOOLKIT_API void spinlock_enter(volatile spinlock_t *sl, int spin_count)
- {
- DWORD tid = GetCurrentThreadId();
- if (sl->_value == tid) {
- sl->_reentrance++;
- } else {
- int i = 0;
- if (spin_count <= 0)
- spin_count = DEFAULT_SPIN_COUNT;
- while (InterlockedCompareExchange((LONG*)&sl->_value, (LONG)tid, 0) != 0) {
- for (; i < spin_count; ++i)
- if (sl->_value == 0)
- break;
- if (i >= spin_count)
- Sleep(1); /* yield cpu */
- }
- sl->_reentrance++;
- }
- }
- TOOLKIT_API void spinlock_leave(volatile spinlock_t *sl)
- {
- _ReadWriteBarrier();
- if (--sl->_reentrance == 0)
- InterlockedExchange((LONG*)&sl->_value, 0);
- }
- TOOLKIT_API void rw_spinlock_read_lock(rw_spinlock_t *rwlock)
- {
- union rw_spinlock_barrier bnew, b;
- for (;;) {
- bnew.nAtomic = b.nAtomic = rwlock->barrier.nAtomic ;
- bnew.readerCount++ ;
- bnew.writerActive = b.writerActive = 0 ;
- bnew.writerCount = b.writerCount = 0 ;
- if (InterlockedCompareExchange(&rwlock->barrier.nAtomic, bnew.nAtomic, b.nAtomic) == b.nAtomic)
- break;
- backoff(DEFAULT_SPIN_COUNT) ;
- }
- }
- TOOLKIT_API void rw_spinlock_read_unlock(rw_spinlock_t *rwlock)
- {
- union rw_spinlock_barrier bnew, b ;
- _ReadWriteBarrier();
- for (;;) {
- bnew.nAtomic = b.nAtomic = rwlock->barrier.nAtomic ;
- bnew.readerCount-- ;
- TOOLKIT_ASSERT( b.writerActive == 0 ) ;
- if (InterlockedCompareExchange(&rwlock->barrier.nAtomic, bnew.nAtomic, b.nAtomic) == b.nAtomic)
- break;
- backoff(DEFAULT_SPIN_COUNT) ;
- }
- }
- TOOLKIT_API void rw_spinlock_write_lock(rw_spinlock_t *rwlock)
- {
- union rw_spinlock_barrier bnew, b ;
- for (;;) {
- bnew.nAtomic = b.nAtomic = rwlock->barrier.nAtomic ;
- bnew.writerCount++ ;
- if (InterlockedCompareExchange(&rwlock->barrier.nAtomic, bnew.nAtomic, b.nAtomic) == b.nAtomic)
- break;
- backoff(DEFAULT_SPIN_COUNT) ;
- }
- for (;;) {
- bnew.nAtomic = b.nAtomic = rwlock->barrier.nAtomic ;
- bnew.readerCount =
- b.readerCount = 0 ;
- b.writerActive = 0 ;
- bnew.writerActive = 1 ;
- if (InterlockedCompareExchange(&rwlock->barrier.nAtomic, bnew.nAtomic, b.nAtomic) == b.nAtomic)
- break;
- backoff(DEFAULT_SPIN_COUNT) ;
- }
- }
- TOOLKIT_API void rw_spinlock_write_unlock(rw_spinlock_t *rwlock)
- {
- union rw_spinlock_barrier bnew, b ;
- _ReadWriteBarrier();
- for (;;) {
- bnew.nAtomic = b.nAtomic = rwlock->barrier.nAtomic ;
- TOOLKIT_ASSERT( b.writerActive == 1 ) ;
- TOOLKIT_ASSERT( b.readerCount == 0 ) ;
- bnew.writerActive = 0 ;
- --bnew.writerCount ;
- if (InterlockedCompareExchange(&rwlock->barrier.nAtomic, bnew.nAtomic, b.nAtomic) == b.nAtomic)
- break;
- backoff(DEFAULT_SPIN_COUNT) ;
- }
- }
- #define BACKOFF_LIMIT 1000
- TOOLKIT_API void fastlock_enter( lock_t l )
- {
- int i = 0;
- int spin_count = 0;
- int backoffs = 0;
- while (InterlockedCompareExchange(l, 1, 0) == 1) {
- for (spin_count = i + 10000; i < spin_count; ++i) {
- if (*l == 0)
- break;
- #if defined(_MSC_VER)
- #if _MSC_VER < 1400
- __asm { rep nop }
- #else
- YieldProcessor(); //关闭sphost时,调试在这里停止,且无法通过taskkill关闭sphost
- #endif
- #else
- tkspause();
- #endif //_MSC_VER
- }
- backoffs++;
- if (backoffs % BACKOFF_LIMIT == 0) {
- Sleep(500);
- }
- SwitchToThread();
- }
- }
- int fastlock_tryenter(lock_t l)
- {
- int i = 0;
- int spin_count = 0;
- int backoffs = 0;
- while (InterlockedCompareExchange(l, 1, 0) == 1) {
- for (spin_count = i + 10000; i < spin_count; ++i) {
- if (*l == 0)
- break;
- #if defined(_MSC_VER)
- #if _MSC_VER < 1400
- __asm { rep nop }
- #else
- YieldProcessor(); //关闭sphost时,调试在这里停止,且无法通过taskkill关闭sphost
- #endif
- #else
- tkspause();
- #endif //_MSC_VER
- }
- backoffs++;
- if (backoffs % BACKOFF_LIMIT == 0) {
- Sleep(500);
- if (*l == 0)
- break;
- else
- return 0;
- }
- SwitchToThread();
- }
- return 1;
- }
|