spin | 您所在的位置:网站首页 › 多核性能和单核性能的区别 › spin |
spinlock_t lock1; spin_lock(&lock1); … 临界区代码 … spin_unlock(&lock1); 还有其他一些自旋锁操作: spin_lock_irqsave不仅获得自旋锁,还停用本地CPU的中断,而spin_lock_bh则停用softIRQ(软中断)。用这两个操作获得的自旋锁必须用对应的接口释放,分别是spin_unlock_irqsave和spin_unlock_bh。 spin_lock的初始化 kernel/include/linux/spinlock.h 自旋锁在Linux内核源代码里的定义如下: kernel/include/linux/spinlock_types.h里面定义了 spinlock_t与raw_spinlock_t只是arch_spinlock_t的包装,这样子提高了扩展性,架构相关的内嵌在最里面一层。 在RT-linux的patch中修改了spinlock_t,允许自旋锁睡眠。标准Linux kernel在spinlock、irq上下文方面无法抢占,因此高优先级任务被唤醒到得以执行的时间并不能完全确定。同时,Linux kernel本身也不处理优先级反转。
** 单核CPU的情况:kernel/include/linux/spinlock_api_up.h ** 由此可见:在启用了内核抢占的单处理器内核中, spin_lock(基本上)等价于preempt_disable,而spin_unlock则等价于preempt_enable 在某个线程里添加如下语句: preempt_disable(); while(1); 然后过会就会打印如下log: [ 28.548865] BUG: soft lockup - CPU#1 stuck for 22s! [us kthread:1106] [ 28.555378] Modules linked in: [ 28.558566] [ 28.560173] Pid: 1106, comm: us kthread [ 28.564951] CPU: 1 Not tainted (3.0.35-00007-g60f7071-dirty #153) [ 28.571528] PC is at ks103_ultrasonic_thread+0x18/0x1c [ 28.576750] LR is at kthread+0x80/0x88 [ 28.580566] pc : [] lr : [] psr: 60000013 [ 28.580571] sp : d441bfc8 ip : c08ba7d0 fp : 00000000 [ 28.592249] r10: 00000000 r9 : 00000000 r8 : 00000000 [ 28.597599] r7 : 00000013 r6 : c035706c r5 : 00000000 r4 : d402fe94 [ 28.604202] r3 : d441a000 r2 : 00000001 r1 : d4044560 r0 : 00000000 [ 28.610854] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [ 28.618287] Control: 10c53c7d Table: 1000404a DAC: 00000015 [ 28.624095] [ 28.624098] PC: 0xc0357004: [ 28.628502] 7004 ebffffaa e58d0004 eaffffd7 e59f1034 e59f0040 eb0c4e8a e3a00003 ebffffa3 [ 28.637449] 7024 e59f2034 e59f101c e1a03000 e59f002c e3530000 e58d3004 01a02000 e59f0020 [ 28.646433] 7044 eb0c4e7f eaffffc8 c06a73cc c07e9fdc c07e9ffc c07ea018 c07ea038 c07e9fc4 [ 28.655417] 7064 c07e9fd4 c07ea058 e1a0200d e3c23d7f e3c3303f e5932004 e2822001 e5832004 [ 28.664414] 7084 eafffffe e92d4008 e3a00000 e59f1008 ebfe1658 e3a00000 e8bd8008 c0972128 [ 28.673356] 70a4 e92d4008 e3a00000 e59f100c ebfe2136 e3500000 13e0000f e8bd8008 c0972128 [ 28.682303] 70c4 e3a03001 e3443004 e1510003 e92d4010 e1a04002 0a000007 e3a03002 e3443004 [ 28.691325] 70e4 e1510003 0a000012 e59f00b4 eb0c4e54 e3e00015 e8bd8010 e59f00a8 eb0c6694 ** 多核CPU的情况:** kernel/include/linux/spinlock_api_smp.h kernel/arch/arm/include/asm/spinlock.h %0是lockval %1是newval %2是tmp %3是lock->slock 4%是1slock没有被其他处理器独占,则标记当前执行处理器对lock->slock地址的独占访问;否则不影响) newval = lockval + (1 slock] (如果当前执行处理器没有独占lock->slock地址的访问,不进行存储,返回1给temp;如果当前处理器已经独占lock->slock内存访问,则对内存进行写,返回0给temp,清除独占标记) lock->tickets.next = lock->tickets.next + 15.检查是否写入成功 lockval.tickets.next 6.初始化时lock->tickets.owner、lock->tickets.next都为0,假设第一次执行arch_spin_lock,lockval = *lock,lock->tickets.next++,lockval.tickets.next 等于 lockval.tickets.owner,获取到自旋锁;自旋锁未释放,第二次执行的时候,lock->tickets.owner = 0, lock->tickets.next = 1,拷贝到lockval后,lockval.tickets.next != lockval.tickets.owner,会执行wfe等待被自旋锁释放被唤醒,自旋锁释放时会执行 lock->tickets.owner++,lockval.tickets.owner重新赋值 7.暂时中断挂起执行。如果当前spin lock的状态是locked,那么调用wfe进入等待状态。 8.其他的CPU唤醒了本cpu的执行,说明owner发生了变化,该新的own赋给lockval,然后继续判断spin lock的状态,也就是回到step 6 9.memory barrier的操作 |
CopyRight 2018-2019 实验室设备网 版权所有 |