另一种边界情况是当len很大时(因为len是无符号的,负数对它来说也是一个很大的正数),这一句也能保证len取到一个较小的值,因为fifo->in总是大于等于fifo->out,所以后面的那个表达式l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));的值不会超过fifo->size的大小。 smp_mb(); smp_wm...
smp_wmb(); \ __kfifo->out++; \ } \ } \ __ret; \}) \) 2022-07-28 回复1 江海寄余生 DECLARE_KFIFO的第三个参数应该是元素个数而不是总大小。kfifo_put的第一个参数应该是fifo队列的地址,kfifo_get的两个参数都应该是地址。下面这段代码在5.15版本的内核上可以编译并运行。 //定义fif...
wmb() 适用于多处理器和单处理器的写内存屏障。 smp_mb() 适用于多处理器的内存屏障。 smp_rmb() 适用于多处理器的读内存屏障。 smp_wmb() 适用于多处理器的写内存屏障。 内存屏障(Memory barrier)可用于多处理器和单处理器系统,如果仅用于多处理器系统,就使用smp_xxx函数,在单处理器系统上,它们什么都不...
buffer, l);45/*then put the rest (if any) at the beginning of the buffer*/46 memcpy(fifo->buffer, buffer + l, len -l);4748/*49* Ensure that we add the bytes to the kfifo -before-50* we update the fifo->in index.51*/53smp_wmb();55 fifo...
*/ smp_wmb(); fifo->in += len; //每次累加,到达最大值后溢出,自动转为0 return len; } unsigned int __kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len) { unsigned int l; //有数据的缓冲区的长度 len = min(len, fifo->in - fifo->out); /* * Ensure that ...
2. W(buffer)和W(in):这个顺序是必须要保证的,否则可能我们更新了in之后,这个时候buffer的内容其实并没有copy进去,但是这时候来了一个__kfifo_get,就把内容拷贝出去了,这个是不允许的。所以这里我们需要用smp_wmb。
// smp_wmb(); } unsigned int __kfifo_out_peek(struct __kfifo *fifo, void *buf, unsigned int len) { unsigned int l; l = fifo->in - fifo->out; if (len > l) len = l; kfifo_copy_out(fifo, buf, len, fifo->out);
那么如何保证1必须在2之前完成,秘密就是使用内存屏障:smp_mb(),smp_rmb(), smp_wmb(),来保证对方观察到的内存操作顺序。 总结 读完kfifo代码,令我想起那首诗“众里寻他千百度,默然回首,那人正在灯火阑珊处”。不知你是否和我一样,总想追求简洁,高质量和可读性的代码,当用尽各种方法,江郞才尽之时,才发现...
smp_wmb(); fifo->in += len; //每次累加,到达最大值后溢出,自动转为0 return len; } unsigned int __kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len) { unsigned int l; //有数据的缓冲区的长度 len = min(len, fifo->in - fifo->out); ...
smp_wmb(); fifo->in += len; return len; } unsigned int __kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len) { unsigned int l; len = min(len, fifo->in - fifo->out); /* * Ensure that we sample the fifo->in index -before- we ...