这段代码仍然处于 lock1 的临界区,如果此时硬件中断也需要申请 lock1 锁会导致死锁,这是因为 spin_unlock_irq 在解锁时一定会将本地 CPU 的中断打开,从而导致硬件中断可以重新强制抢占 CPU,所以最好的方式就是 lock2 在锁之前保存当前的中断状态,在解锁时恢复当前的中断状态,这也就是 spin_lock_irqsave 需要...
#define spin_lock(lock) _spin_lock(lock) linux-src/kernel/spinlock.c void __lockfunc _spin_lock(spinlock_t *lock) { preempt_disable(); LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock); } linux-src/include/linux/spinlock.h # define _raw_spin_lock(lock) __raw_spin_lock(&(...
static inline void __raw_spin_lock_irq(raw_spinlock_t *lock) { local_irq_disable(); preempt_disable(); spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); } 可以看出来他们两者只有一个差别:是否调用local_irq_disable()函数,...
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); } 可以看出来他们两者只有一个差别:是否调用local_irq_disable()函数, 即是否禁止本地中断。 在任何情况下使用spin_lock_irq都是安全的。因为它既禁止本地中断,又禁止内核抢占。 spin_lock比spin_lock_irq速度快,但是它并不是任何情况下都是安...
do_raw_spin_unlock(lock); local_irq_enable(); preempt_enable(); } 为何preempt_enable()比local_irq_enable()后发生呢?如果代码顺序是这样的: preempt_enable() local_irq_enable() 第一句preempt_enable()想执行抢占调度的话,即便调用了preempt_schedule(),但是由于IRQ还是关门的,preempt_schedule()函数会...
raw_spin_lock_nest_lock(spinlock_check(lock), nest_lock); \\ }while(0)static__always_inlinevoidspin_lock_irq(spinlock_t *lock){ raw_spin_lock_irq(&lock- >rlock); }#definespin_lock_irqsave(lock, flags) \\do{ \\ raw_spin_lock_irqsave(spinlock_check(lock), flags); \\ ...
raw_spin_lock_bh(&lock->rlock); } // 判断有没有上锁 staticinlineintspin_trylock(spinlock_t*lock) { returnraw_spin_trylock(&lock->rlock); } // 既禁止本地中断,又禁止内核抢占 staticinlinevoidspin_lock_irq(spinlock_t*lock) { raw_spin_lock_irq(&lock->rlock); ...
自旋锁 spin_lock Linux内核中最常见的锁是自旋锁,自旋锁最多只能被一个可执行线程持有。如果一个线程试图获取一个已被持有的自旋锁,这个线程会进行忙循环——旋转等待(会浪费处理器时间)锁重新可用。自旋锁持有期间不可被抢占。 另一种处理锁争用的方式:让等待线程睡眠,直到锁重新可用时再唤醒它,这样处理器不必...
*/#define___LOCK(lock) \do{__acquire(lock);(void)(lock);}while(0)#define__LOCK(lock) \do{preempt_disable();___LOCK(lock);}while(0) 对于多核 /* * 定义在include/linux/spinlock_api_smp.h中 * 多核比较复杂, */staticinlineunsignedlong__raw_spin_lock_irqsave(raw_spinlock_t*lock)...
*/ raw_spin_lock_irqsave(&desc-》lock, flags); old_ptr = &desc-》action; old = *old_ptr; if (old) { /* * Can‘t share interrupts unless both agree to and are * the same type (level, edge, polarity)。 So both flag * fields must have IRQF_SHARED set and the bits which *...