您的位置:首页 > 编程语言

(ARM v7)自旋锁、读写锁、顺序锁代码追踪

2015-12-24 16:41 537 查看
//自选锁
static inline void spin_lock(spinlock_t *lock)
{
raw_spin_lock(&lock->rlock);
}
#define raw_spin_lock(lock)    _raw_spin_lock(lock)
void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
{
__raw_spin_lock(lock);
}
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
#define preempt_disable() \
do { \
inc_preempt_count(); \
barrier(); \
} while (0)
#define inc_preempt_count() add_preempt_count(1)
# define add_preempt_count(val)    do { preempt_count() += (val); } while (0)
#define preempt_count()    (current_thread_info()->preempt_count)
#define barrier() __asm__ __volatile__("": : :"memory")

# define spin_acquire(l, s, t, i)        do { } while (0)
#define LOCK_CONTENDED(_lock, try, lock) \
lock(_lock)
static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock)
{
__acquire(lock);
arch_spin_lock(&lock->raw_lock);
}
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp;

__asm__ __volatile__(
"1:    ldrex    %0, [%1]\n"
"    teq    %0, #0\n"
#ifdef CONFIG_CPU_32v6K
"    wfene\n"
#endif
"    strexeq    %0, %2, [%1]\n"
"    teqeq    %0, #0\n"
"    bne    1b"                //yuan di xuan zhuan
: "=&r" (tmp)
: "r" (&lock->lock), "r" (1)
: "cc");

smp_mb();
}
#define smp_mb()    mb()
#define smp_rmb()    rmb()
#define smp_wmb()    wmb()
#define mb()        do { dsb(); outer_sync(); } while (0)
#define rmb()        dsb()
#define wmb()        do { dsb(st); outer_sync(); } while (0)
#define dma_rmb()    dmb(osh)
#define dma_wmb()    dmb(oshst)
#define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory")
#define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory")
#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory")

//读写锁
#define write_lock(lock)    _raw_write_lock(lock)
#define _raw_write_lock(lock) __raw_write_lock(lock)
static inline void __raw_write_lock(rwlock_t *lock)
{
preempt_disable();
rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
}
# define do_raw_write_lock(rwlock)    do {__acquire(lock); arch_write_lock(&(rwlock)->raw_lock); } while (0)
static inline void arch_write_lock(arch_rwlock_t *rw)
{
unsigned long tmp;

prefetchw(&rw->lock);
__asm__ __volatile__(
"1:    ldrex    %0, [%1]\n"
"    teq    %0, #0\n"
WFE("ne")
"    strexeq    %0, %2, [%1]\n"
"    teq    %0, #0\n"
"    bne    1b"
: "=&r" (tmp)
: "r" (&rw->lock), "r" (0x80000000)
: "cc");

smp_mb();
}

#define read_lock(lock)        _raw_read_lock(lock)
void __lockfunc _raw_read_lock(rwlock_t *lock)
{
__raw_read_lock(lock);
}
static inline void __raw_read_lock(rwlock_t *lock)
{
preempt_disable();
rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
}
void do_raw_read_lock(rwlock_t *lock)
{
RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
arch_read_lock(&lock->raw_lock);
}
static inline void arch_read_lock(arch_rwlock_t *rw)
{
unsigned long tmp, tmp2;

prefetchw(&rw->lock);
__asm__ __volatile__(
"1:    ldrex    %0, [%2]\n"
"    adds    %0, %0, #1\n"
"    strexpl    %1, %0, [%2]\n"
WFE("mi")
"    rsbpls    %0, %1, #0\n"
"    bmi    1b"
: "=&r" (tmp), "=&r" (tmp2)
: "r" (&rw->lock)
: "cc");

smp_mb();
}

//顺序锁
static inline void write_seqlock(seqlock_t *sl)
{
spin_lock(&sl->lock);
write_seqcount_begin(&sl->seqcount);
}
static inline void write_seqcount_begin(seqcount_t *s)
{
write_seqcount_begin_nested(s, 0);
}
static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
{
raw_write_seqcount_begin(s);
seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
}
static inline void raw_write_seqcount_begin(seqcount_t *s)
{
s->sequence++;
smp_wmb();
}

static inline unsigned read_seqbegin(const seqlock_t *sl)
{
return read_seqcount_begin(&sl->seqcount);
}
static inline unsigned read_seqcount_begin(const seqcount_t *s)
{
seqcount_lockdep_reader_access(s);
return raw_read_seqcount_begin(s);
}
# define seqcount_lockdep_reader_access(x)
static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
{
unsigned ret = __read_seqcount_begin(s);
smp_rmb();
return ret;
}
static inline unsigned __read_seqcount_begin(const seqcount_t *s)
{
unsigned ret;

repeat:
ret = ACCESS_ONCE(s->sequence);
if (unlikely(ret & 1)) {
cpu_relax();
goto repeat;
}
return ret;
}
#define cpu_relax()            barrier()

static inline unsigned read_seqretry(const seqlock_t *sl, unsigned start)
{
return read_seqcount_retry(&sl->seqcount, start);
}
static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
{
smp_rmb();
return __read_seqcount_retry(s, start);
}
static inline int __read_seqcount_retry(const seqcount_t *s, unsigned start)
{
return unlikely(s->sequence != start);
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: