linux-device-driver – 低延迟模式是否可以安全地与Linux串行端
在
Linux串行端口上使用low_latency tty模式是否安全?
tty_flip_buffer_push函数被记录为“如果设置了port-> low_latency,则不能从IRQ上下文调用它”.然而,无论标志是否设置,许多低级串行端口驱动程序都会从??ISR调用它.例如,mpc52xx driver calls flip buffer无条件地从其FIFO读取之后.
ISR中低延迟翻转缓冲区的结果是线路规则驱动程序在IRQ上下文中输入.我的目标是从高速mpc52xx串口读取延迟一毫秒或更短.设置low_latency可以实现延迟目标,但它也违反了tty_flip_buffer_push记录的前提条件. 解决方法
这个问题在
linux-serial on Fri,19 Aug 2011被问到.
不,低延迟通常不安全. 但是,在3.10.5的特定情况下,low_latency是安全的. 上面的评论tty_flip_buffer_push读取:
但是,代码(3.10.5,drivers / tty / tty_buffer.c)与此相矛盾: void tty_flip_buffer_push(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; unsigned long flags; spin_lock_irqsave(&buf->lock,flags); if (buf->tail != NULL) buf->tail->commit = buf->tail->used; spin_unlock_irqrestore(&buf->lock,flags); if (port->low_latency) flush_to_ldisc(&buf->work); else schedule_work(&buf->work); } EXPORT_SYMBOL(tty_flip_buffer_push); 使用spin_lock_irqsave / spin_unlock_irqrestore可以安全地从中断上下文调用此代码. 对low_latency进行了测试,如果设置了,则直接调用flush_to_ldisc.这会立即将翻转缓冲区刷新到线路规则,代价是中断处理时间更长. flush_to_ldisc例程也被编码为在中断上下文中使用是安全的.我想早期版本不安全. 如果未设置low_latency,则调用schedule_work.调用schedule_work是在中断上下文中从“上半部分”调用“下半部分”处理程序的经典方法.这导致在下一个时钟周期从“下半部”处理程序调用flush_to_ldisc. 更深入一点,评论和测试似乎都在Alan Cox的tty_buffer.c的原始e0495736提交中.这个提交是对早期代码的重写,所以似乎有一次没有测试.无论谁添加测试并修复flush_to_ldisc是中断安全的,都没有费心去修复评论. 所以,始终相信代码,而不是评论. 但是,在3.12-rc *(截至2013年10月23日)的相同代码中,当flush_to_ldisc中的spin_lock_irqsave被删除并添加了mutex_locks时,看起来问题再次被打开.也就是说,在serial_struct标志中设置UPF_LOW_LATENCY并调用TIOCSSERIAL ioctl将再次导致“原子调度”. 维护者的最新更新是: On 10/19/2013 07:16 PM,Jonathan Ben Avraham wrote: > Hi Peter,> "tty_flip_buffer_push" is called from IRQ handlers in most drivers/tty/serial UART drivers. > > "tty_flip_buffer_push" calls "flush_to_ldisc" if low_latency is set. > "flush_to_ldisc" calls "mutex_lock" in 3.12-rc5,which cannot be used in interrupt context. > > Does this mean that setting "low_latency" cannot be used safely in 3.12-rc5? Yes,I broke low_latency. Part of the problem is that the 3.11- use of low_latency was unsafe; too many shared data areas were simply accessed without appropriate safeguards. I'm working on fixing it but probably won't make it for 3.12 final. Regards,Peter Hurley 因此,看起来您不应该依赖low_latency,除非您确定永远不会从支持它的版本更改内核. 更新:2014年2月18日,内核3.13.2 Stanislaw Gruszka写道: Hi,setserial has low_latency option which should minimize receive latency (scheduler delay). AFAICT it is used if someone talk to external device via RS-485/RS-232 and need to have quick requests and responses . On kernel this feature was implemented by direct tty processing from interrupt context: void tty_flip_buffer_push(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; buf->tail->commit = buf->tail->used; if (port->low_latency) flush_to_ldisc(&buf->work); else schedule_work(&buf->work); } But after 3.12 tty locking changes,calling flush_to_ldisc() from interrupt context is a bug (we got scheduling while atomic bug report here: https://bugzilla.redhat.com/show_bug.cgi?id=1065087 ) I'm not sure how this should be solved. After Peter get rid all of those race condition in tty layer,we probably don't want go back to use spin_lock's there. Maybe we can create WQ_HIGHPRI workqueue and schedule flush_to_ldisc() work there. Or perhaps users that need to low latency,should switch to thread irq and prioritize serial irq to meat retirements. Anyway setserial low_latency is now broken and all who use this feature in the past can not do this any longer on 3.12+ kernels. Thoughts ? Stanislaw (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |