zoukankan      html  css  js  c++  java
  • Spin Lock

    昨天写了一下interrupt和exception的不同,在弄清以后,可以来研究linux kernel中的各种同步机制,各种锁了。 先写一下Spin Lock,其余的有时间再写。 Spin Locks 这个是很常见的,好多地方翻译成“自旋锁”,在临界区只允许一个进程进入(且该进程不允许休眠,例如中断处理程序)时经常使用。 spin lock使用spinlock_t结构体来实现,其定义在/include/linux/spinlock_types.h文件中
    typedef struct spinlock {
    union {
    struct raw_spinlock rlock;
    
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
    # define LOCK_PADSIZE (offsetof(struct  raw_spinlock, dep_map))
    struct {
    u8 __padding[LOCK_PADSIZE];
    struct lockdep_map dep_map;
    };
    #endif
    };
    } spinlock_t;
    如果不处于调试时,spinlock_t就是一个raw_spinlock结构体,raw_spinlock的定义也在这个文件中,如下
    typedef struct raw_spinlock {
    arch_spinlock_t raw_lock;
    #ifdef CONFIG_GENERIC_LOCKBREAK
    unsigned int break_lock;
    #endif
    #ifdef CONFIG_DEBUG_SPINLOCK
    unsigned int magic, owner_cpu;
    void *owner;
    #endif
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lockdep_map dep_map;
    #endif
    } raw_spinlock_t;
    如果去除调试信息的话,只剩arch_spinlock_t和break_lock了,break_lock只在preemption enable状态下被编译,再来看arch_spinlock_t的定义,这个结构体的定义根据不同的体系结构而不同,在i386上如下
    typedef struct arch_spinlock {
    unsigned int slock;
    } arch_spinlock_t;
    可见,其实它就是一个整数。 再来看它的使用。 下面有的文字来自于ULK。 当without kernel preemption时,加锁的代码如下
    1: lock; decb slp->slock
    jns 3f
    2: pause
    cmpb $0,slp->slock
    jle 2b
    jmp 1b
    3:
    也就是说,将slock值减1,然后判断是否小于零,如果小于零,则继续尝试,直到其大于零,然后再返回1尝试进行加锁。如是减之后不小于零,则证明加锁成功,继续执行下面代码。 当with kernel preemption时,加锁就有些不同了,代码我没仔细看,只把ULK中的描述记下来: 1.先关掉kernel preemption 2.调用_raw_spin_trylock(),这个函数大体如下
    movb $0, %al
    xchgb %al, slp->slock
    也就是将slock置零,然后通过判断al的值来判断加锁是否成功。如果成功应该返回1,否则返回零(这个代码如此高效) 3.如果经判断,加锁已经成功,进程得以继续执行。 如果经判断,加锁失败,那么,会调用preempt_enable(),这时,有可能当前进程被调度出去。 4.将break_lock值设为1,这样,说明有别的进程在等待获得锁,如果占有锁的进程发现有进程在等待而且自己已经占有了较长时间,这可能会自愿将该锁让给别的进程。 5.执行如下代码
    while (spin_is_locked(slp) && slp->break_lock)
    cpu_relax();
    cpu_relax()是从Pentium 4以后新增的指令,专为spin_lock而优化。相比rep;nop;来说,它执行的更快,更省电。 再来看解锁的代码
    movb $1,slp->slock
    直接将slock置1 毛老师书上说,使用movb而不用inc的原因是movb能节省指令周期,而且,ULK上讲,这个操作是原子的,而inc或者dec不是,所以,在加锁的代码中,dec指令前面加了lock,锁住总线。
  • 相关阅读:
    Java数据库——CallableStatement接口
    Java数据库——处理大数据对象
    Java数据库——PreparedStatement接口
    Java数据库——ResultSet接口
    Java数据库——连接关闭、增删改查
    Ubuntu下的MySQL安装
    JDBC
    注释(Annotation)
    类的生命周期
    Java反射机制<2>
  • 原文地址:https://www.cnblogs.com/yangce/p/2910086.html
Copyright © 2011-2022 走看看