kernel lib/kfifo.c中有两段代码如下:
#define kfifo_in_spinlocked(fifo, buf, n, lock) \
({ \
unsigned long __flags; \
unsigned int __ret; \
spin_lock_irqsave(lock, __flags); \
__ret = kfifo_in(fifo, buf, n); \
spin_unlock_irqrestore(lock, __flags); \
__ret; \
})
static void kfifo_copy_in(struct __kfifo *fifo, const void *src,
unsigned int len, unsigned int off) {
unsigned int size = fifo->mask + 1;
unsigned int esize = fifo->esize;
unsigned int l;
off &= fifo->mask;
if (esize != 1) {
off *= esize;
size *= esize;
len *= esize;
}
l = min(len, size - off);
memcpy(fifo->data + off, src, l);
memcpy(fifo->data, src + l, len - l);
/*
* make sure that the data in the fifo is up to date before
* incrementing the fifo->in index counter
*/
smp_wmb();
}
kfifo_in
中的函数
kfifo_in_spinlocked
最终会调用
kfifo_copy_in
函数,我的问题是为什么即使有了
spin_lock_irqsave
,还需要
smp_wmb
? cpu获得自旋锁会使其他cpu停顿,因此它可以独占修改变量和数据地址,当它解锁时,其他cpu可以获取最新的数据和数据地址吗?为什么需要
smp_wmb
?
Single Producer Single Consumer)。内存屏障适用于来自 reader 和 writer 的并发访问。
如果有多个生产者(编写者),则需要额外的编写者之间的同步,因此一次只有一个编写者处于活动状态。
函数kfifo_in_spinlocked
提供了一种在编写器之间进行同步的方法:自旋锁。实际上,锁定方面在
kfifo.h 标头的最顶部进行了描述:
/*
* Note about locking: There is no locking required until only one reader
* and one writer is using the fifo and no kfifo_reset() will be called.
* kfifo_reset_out() can be safely used, until it will be only called
* in the reader thread.
* For multiple writer and one reader there is only a need to lock the writer.
* And vice versa for only one writer and multiple reader there is only a need
* to lock the reader.
*/