linux 读串口低延迟,linux-device-driver – 低延迟模式是否可以安全地与Linux串行端口一起使用?...

这个问题在

linux-serial on Fri, 19 Aug 2011被问到.

不,低延迟通常不安全.

但是,在3.10.5的特定情况下,low_latency是安全的.

上面的评论tty_flip_buffer_push读取:

“This function must not be called from IRQ context if port->low_latency is set.”

但是,代码(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值