#ifndef SYS_SPINLOCK_H
#define SYS_SPINLOCK_H

#include "typedef.h"
#include "cpu.h"
#include "irq.h"


struct __spinlock {
	volatile u32 rwlock;
};

typedef struct __spinlock spinlock_t;

#if CPU_CORE_NUM > 1

#define preempt_disable() \
    __local_irq_disable()

#define preempt_enable() \
    __local_irq_enable()

#else

#define preempt_disable() \
    local_irq_disable()

#define preempt_enable() \
    local_irq_enable()




#endif


#if CPU_CORE_NUM > 1

#define spin_acquire(lock)  \
    do { \
        arch_spin_lock(lock); \
    }while(0)

#define spin_release(lock) \
    do { \
        arch_spin_unlock(lock); \
    }while(0)

#else

#define spin_acquire(lock)  \
    do { \
    }while(0)


#define spin_release(lock) \
    do { \
    }while(0)

#endif


#define DEFINE_SPINLOCK(x) \
    spinlock_t x = { .rwlock = 0 }


static inline void spin_lock_init(spinlock_t *lock)
{
	lock->rwlock = 0;
}
extern u32 spin_lock_cnt[];

#if 1
static inline void spin_lock(spinlock_t *lock)
{
	preempt_disable();
	/*ASSERT(spin_lock_cnt[current_cpu_id()] == 0);
	spin_lock_cnt[current_cpu_id()] = 1;*/
	spin_acquire(lock);
}


static inline void spin_unlock(spinlock_t *lock)
{
	/*spin_lock_cnt[current_cpu_id()] = 0;*/
	spin_release(lock);
	preempt_enable();
}

#else


#define spin_lock(lock) \
    do { \
        preempt_disable(); \
        if (!(T2_CON & (1<<0))) { \
            T2_CNT = 0; \
            T2_PRD = 120000000 / 10; \
            T2_CON = 1; \
        } \
        spin_lock_cnt[current_cpu_id()] = T2_CNT; \
        spin_acquire(lock); \
    } while (0)


#define spin_unlock(lock) \
    do { \
        u32 t = T2_CNT;\
        if(t < spin_lock_cnt[current_cpu_id()]) \
            t += T2_PRD - spin_lock_cnt[current_cpu_id()]; \
        else \
            t -= spin_lock_cnt[current_cpu_id()]; \
        spin_release(lock); \
        preempt_enable(); \
        if (t > 100000) { /*120000 == 1ms*/ \
            printf("???????spinlock: %d, %s\n", t, __func__); \
        } \
    } while(0)

#endif

/*#define spin_lock_irqsave(lock, flags) \
    do { \
        local_irq_save(flags); \
        spin_acquire((lock)); \
    }while(0)

#define spin_unlock_irqrestore(lock, flags) \
    do { \
        spin_release((lock)); \
        local_irq_restore(flags); \
    }while(0) */











#endif

