이 질문에 대한 답변이 linux-serial on Fri, 19 Aug 2011입니다.
아니요, 낮은 대기 시간은 일반적으로 안전하지 않습니다.
그러나 특별한 경우 3.10.5 low_latency
은 안전합니다. tty_flip_buffer_push
읽기 위
주석은 :
"포트 -> low_latency가 설정되어있는 경우이 기능은 IRQ 컨텍스트에서 호출 할 수 없습니다."
그러나 코드 (3.10.5, 드라이버/청각/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의 원본 e0495736
커밋 tty_buffer.c
에있는 것처럼 보입니다. 이 커밋은 이전 코드를 다시 작성한 것이므로 한 번에 테스트가 없었던 것으로 보입니다. 테스트를 추가하고 flush_to_ldisc
을 인터럽트 방지로 고정한 사람은 누구나 코멘트를 고칠 필요가 없습니다.
그래서 코드는 항상 주석이 아닌 믿습니다.
그러나, flush_to_ldisc에서 spin_lock_irqsave 년대를 제거하고 mutex_locks가 추가 될 때 문제가 다시 열린 것 같습니다 3.12-RC의 *에서 동일한 코드 (년 10 월 (23), 2013). 즉, serial_struct 플래그에서 UPF_LOW_LATENCY를 설정하고 TIOCSSERIAL ioctl을 호출하면 다시 "원자 단위로 일정 잡기"가 발생합니다.
메인테이너의 최신 업데이트입니다 : 당신은 당신이 결코 그것을 지원하는 버전의 커널을 변경 않을 것을 확신하지 않는 한 low_latency
에 의존해서는 안처럼
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
그래서, 그것은 보인다.
업데이트 : 2004 년 3 월 (18) 2014 커널 3.13.2
는 스타니 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
꽤 오래된 커널 2.6.28을 사용하고있었습니다. 새로운 커널에서는 low_latency 플래그가 필요 없습니다. 드라이버는 저레벨 드라이버에서 라인 규율 드라이버로 데이터를 전송할 때 delayed_work 사용을 중지했습니다. https://github.com/torvalds/linux/commit/f23eb2b2b28547fc70df82dd5049eb39bec5ba12 – joshuanapoli
low_latency 플래그는 최신 Linux 커널에 여전히 존재하지만 불필요한 것처럼 보입니다. 많은 저수준 드라이버와 함께 사용하는 것은 여전히 위험 해 보입니다. – joshuanapoli