#ifdef PROXYSQL_USE_SPINLOCK
// PROXYSQL_USE_SPINLOCK is NOT define
// spinlock have been removed in 1.4.1 due to issue #977 , to compile in ARM
// this file is kept for reference, and will be completely removed in future
#ifndef PROXYSQL_ATOMIC
#define PROXYSQL_ATOMIC 
/*
typedef unsigned spinlock;
typedef struct _rwlock_t rwlock_t;
struct _rwlock_t {
    spinlock lock;
    unsigned readers;
};
*/
#define atomic_inc(P) __sync_add_and_fetch((P), 1)
#define atomic_dec(P) __sync_add_and_fetch((P), -1)

/* Compile read-write barrier */
#define barrier() asm volatile("": : :"memory")

/* Pause instruction to prevent excess processor bus usage */
#define cpu_relax_pa() asm volatile("pause\n": : :"memory")
#define cpu_relax_us() usleep(1)

#define RELAX_TRIES	100

static inline unsigned xchg_32(void *ptr, unsigned x) {
    __asm__ __volatile__("xchgl %0,%1"
                :"=r" (x)
                :"m" (*(volatile unsigned *)ptr), "0" (x)
                :"memory");
    return x;
}

static inline void spinlock_rwlock_init(rwlock_t *l) {
	memset(l,0,sizeof(rwlock_t));
}

static inline void spinlock_init(spinlock *l) {
	memset(l,0,sizeof(spinlock));
}

static inline void spin_lock(spinlock *lock) {
		int i=RELAX_TRIES;
    while (1) {
        if (!xchg_32(lock, 1)) return;
        while (*lock) { if (i) { i--; cpu_relax_pa(); } else { i=RELAX_TRIES; cpu_relax_us(); } }
    }
}

static inline void spin_unlock(spinlock *lock) {
    barrier();
    *lock = 0;
}

static inline void spin_wrlock(rwlock_t *l) {
    spin_lock(&l->lock);
		int i=RELAX_TRIES;
    while (l->readers) { if (i) { i--; cpu_relax_pa(); } else { i=RELAX_TRIES; cpu_relax_us(); } }
}

static inline void spin_wrunlock(rwlock_t *l) {
    spin_unlock(&l->lock);
}

static inline void spin_rdlock(rwlock_t *l) {
		int i=RELAX_TRIES;
    while (1) {
        atomic_inc(&l->readers);
        if (!l->lock) return;
        atomic_dec(&l->readers); 
        while (l->lock) { if (i) { i--; cpu_relax_pa(); } else { i=RELAX_TRIES; cpu_relax_us(); } }
    }
}

static inline void spin_rdunlock(rwlock_t *l) {
    atomic_dec(&l->readers);
}


#endif /* PROXYSQL_ATOMIC */
#endif // PROXYSQL_USE_SPINLOCK
