#ifndef __SPINLOCK_H__ #define __SPINLOCK_H__ #pragma once #include "config.h" #include "dbgutil.h" #if _WIN32 #include #endif #include #include #ifdef __cplusplus extern "C" { #endif typedef volatile LONG lock_t[1]; #define FASTLOCK_INIT() {0} /* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */ #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) #define PAUSE_INSTRUCTION() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */ #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) #define PAUSE_INSTRUCTION() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */ #elif defined(__WATCOMC__) && defined(__386__) /* watcom assembler rejects PAUSE if CPU < i686, and it refuses REP NOP as an invalid combination. Hardcode the bytes. */ extern _inline void PAUSE_INSTRUCTION(void); #pragma aux PAUSE_INSTRUCTION = "db 0f3h,90h" #else #define PAUSE_INSTRUCTION() #endif // non-reentrance static __inline void fastlock_init(lock_t l) { l[0] = 0; } TOOLKIT_API void fastlock_enter(lock_t l); static __inline void fastlock_leave(lock_t l) { _ReadWriteBarrier(); InterlockedExchange(l, 0); } static __inline void fastlock_term(lock_t l) { TOOLKIT_ASSERT(l[0] == 0); } /* spin lock, note: reentrance!!! * 11 1111 1111 */ #define DEFAULT_SPIN_COUNT 0x3ff // because zero is invalid thread id, so when a thread retrieve the lock // _value is set to the thread's id. typedef struct spinlock_t { volatile DWORD _value; volatile DWORD _reentrance; }spinlock_t; static __inline void spinlock_init(spinlock_t *plock) { plock->_value = 0; plock->_reentrance = 0; } /** * enter lock * @param spin_count -1 use default */ TOOLKIT_API void spinlock_enter(volatile spinlock_t *sl, int spin_count); /** * leave lock */ TOOLKIT_API void spinlock_leave(volatile spinlock_t *sl); union rw_spinlock_barrier { struct { unsigned int readerCount : 32 / 2; unsigned int writerCount : 32 / 2 - 1; unsigned int writerActive : 1 ; }; unsigned int nAtomic ; }; typedef volatile struct rw_spinlock_s { union rw_spinlock_barrier barrier; }rw_spinlock_t; static __inline void rw_spinlock_init(rw_spinlock_t *rwlock) { rwlock->barrier.nAtomic = 0; } // John M. Mellor-Crummey, Michael L. Scott "Scalable Reader-Writer Synchronization for Shared-Memory Multiprocessors", 1991 TOOLKIT_API void rw_spinlock_read_lock(rw_spinlock_t *rwlock); TOOLKIT_API void rw_spinlock_read_unlock(rw_spinlock_t *rwlock); TOOLKIT_API void rw_spinlock_write_lock(rw_spinlock_t *rwlock); TOOLKIT_API void rw_spinlock_write_unlock(rw_spinlock_t *rwlock); static __inline int rw_spinlock_is_reading(rw_spinlock_t *rwlock) { return rwlock->barrier.readerCount != 0; } static __inline int rw_spinlock_is_writing(rw_spinlock_t *rwlock) { return rwlock->barrier.writerActive == 1 ; } #ifdef __cplusplus } // extern "C" { #endif #endif //__SPINLOCK_H__