今天看了一下linux-2.4.20的spinlock。以i386为平台。linux实现的非常简洁。
spinlock_t的类型定义如下,只是一个整数。
-
typedef struct {
-
volatile unsigned int lock;
-
} spinlock_t;
初始化如下,就是把lock赋值为1,lock等于1时表示这个spinlock现在是可以用的。
-
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
-
#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
获得spinlock的函数展开如下(去掉了非关键代码)。检查lock的值是不是1,如果是1表示没上锁,然后lock减1表示获得这个锁继续往后执行;如果不是1表示已经上锁,然后一直在这循环检查,直到lock变为1,然后获得这个锁往后执行。
-
__asm__ __volatile__(
-
"\n1:\t" \
-
"lock ; decb %0\n\t" \
-
"js 2f\n" \
-
"2:\t" \
-
"cmpb $0,%0\n\t" \
-
"rep;nop\n\t" \
-
"jle 2b\n\t" \
-
"jmp 1b\n" \
-
:"=m" (lock->lock) : : "memory");
不懂gnu汇编的可以去看一下Richard Blum的《Professional Assembly Language》。lock指令在intel手册中是这么写的Causes the processor's LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal insures that the processor has exclusive use of any shared memory while the signal is asserted. 大概意思是多核的情况是lock能保证后面的那条指令是互斥执行的。
如果在中断处理程序中使用spinlick应该使用
spin_lock_irqsave,否则会造成死锁。
阅读(806) | 评论(0) | 转发(0) |