Chinaunix首页 | 论坛 | 博客
  • 博客访问: 45012
  • 博文数量: 17
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 173
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-27 20:25
文章分类

全部博文(17)

文章存档

2016年(2)

2015年(2)

2014年(13)

我的朋友

分类: LINUX

2014-06-24 09:44:46

    2.6.32中
    #define spin_lock_irqsave(lock, flags) \
        do { \
            typecheck(unsigned long, flags); \
            flags = _spin_lock_irqsave(lock); \
        } while (0)
   最终走到流程
    static inline unsigned long __spin_lock_irqsave(spinlock_t *lock)
    {
        unsigned long flags;

        local_irq_save(flags);//保存调用之前的中断状态,然后关闭中断
        preempt_disable();//禁止抢占
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);//获取一个spinlock锁的访问权限
        #ifdef CONFIG_LOCKDEP
        LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
        #else
        _raw_spin_lock_flags(lock, &flags);//自旋部分
        #endif
        return flags;
    }
    自旋部分最终走到流程__ticket_spin_lock。
    首先,自旋锁将整数拆为一个16位数,结构如下:
      next  | owner  
  其中的owner表示当前可以占用锁的序号,next表示想要占有锁所分配的序号,从小到大代表着一种顺序关系。next和owner的初始为0,代表 着锁处于空闲状态。

    static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
   {

        short inc = 0x0100;
               asm volatile (

LOCK_PREFIX "xaddw %w0, %1\n" //这里锁住总线,获取当前锁的值,并将锁的next字段加1
"1:\t"
"cmpb %h0, %b0\n\t" //比较获取的值next和owner是否相等,高位与低位是否相等,
"je 2f\n\t" //相等,则加锁成功
"rep ; nop\n\t" //随机延时
"movb %1, %b0\n\t" //继续等待,会将锁的低位字段再赋值给保留值
/* don't need lfence here, because loads are in-order */
"jmp 1b\n" //向后跳转到标签1处
"2:"
: "+Q" (inc), "+m" (lock->slock)
:
: "memory", "cc");

}
我的疑问是,如果一直在自旋的话,顺序拿锁的方式,保证一定按加锁的顺序,获得锁,那由于中断长时间关闭,会导致NMI。



此外,在linux 实现的读写锁是读优先的,但是读者 no writer-consious, no order like spin-lock
因此,可能会让写者忙等。

static inline void __raw_write_lock(raw_rwlock_t *rw)

{

asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t"

    "jz 1f\n"

    "call __write_lock_failed\n\t" //here is  a loop

    "1:\n"

    ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory");

}

.align    4  
.globl    __write_lock_failed  
__write_lock_failed:  
        " LOCK "addl    $" RW_LOCK_BIAS_STR ",(%eax)  
1:     cmpl    $" RW_LOCK_BIAS_STR ",(%eax)  
        jne    1b  
  
        " LOCK "subl    $" RW_LOCK_BIAS_STR ",(%eax)  
        jnz    __write_lock_failed  
        ret 


那么,在write_lock_irq和write_lock_irqsave的实现中,关闭中断,会不会导致NMI,不知道这是不是个问题


    参考:
    google __ticket_spin_lock 分析   


阅读(973) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~