| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- #include "precompile.h"
- #include "spinlock.h"
- // please refer http://book.opensourceproject.org.cn/kernel/kernel3rd/opensource/0596005652/understandlk-chp-5-sect-2.html
- static __inline void backoff(unsigned int nloop)
- {
- __asm {
- and ecx, nloop ;
- cmovz ecx, nloop ;
- rep nop ;
- }
- }
- 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-- ;
- 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 ;
- assert( b.writerActive == 1 ) ;
- 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 _MSC_VER < 1400
- __asm { rep nop }
- #else
- YieldProcessor(); //关闭sphost时,调试在这里停止,且无法通过taskkill关闭sphost
- #endif
- }
- backoffs++;
- if (backoffs % BACKOFF_LIMIT == 0) {
- Sleep(500);
- }
- SwitchToThread();
- }
- }
|