2013-03-19 2 views
4

Linux 직렬 포트에서 low_latency tty 모드를 사용하는 것이 안전합니까? tty_flip_buffer_push 함수는 "port-> low_latency가 설정된 경우 IRQ 컨텍스트에서 호출하면 안됩니다." 그럼에도 불구하고 많은 저수준 직렬 포트 드라이버는 플래그가 설정되었는지 여부에 관계없이 ISR에서이를 호출합니다. 예를 들어, mpc52xx driver calls flip buffer은 FIFO에서 각각 읽은 후 무조건적으로 읽습니다.Linux 직렬 포트에서 대기 시간이 적은 모드를 사용할 수 있습니까?

ISR에서 지연 시간이 짧은 플립 버퍼의 결과는 라인 규정 드라이버가 IRQ 컨텍스트 내에서 입력된다는 것입니다. 필자의 목표는 고속 mpc52xx 직렬 포트에서 읽는 1 밀리 초 이하의 대기 시간을 얻는 것입니다. low_latency 설정은 대기 시간 목표를 달성하지만 tty_flip_buffer_push에 대한 문서화 된 전제 조건에도 위배됩니다.

+0

꽤 오래된 커널 2.6.28을 사용하고있었습니다. 새로운 커널에서는 low_latency 플래그가 필요 없습니다. 드라이버는 저레벨 드라이버에서 라인 규율 드라이버로 데이터를 전송할 때 delayed_work 사용을 중지했습니다. https://github.com/torvalds/linux/commit/f23eb2b2b28547fc70df82dd5049eb39bec5ba12 – joshuanapoli

+0

low_latency 플래그는 최신 Linux 커널에 여전히 존재하지만 불필요한 것처럼 보입니다. 많은 저수준 드라이버와 함께 사용하는 것은 여전히 ​​위험 해 보입니다. – joshuanapoli

답변

3

이 질문에 대한 답변이 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 
1

패치는 문제를 해결하기 위해 LKML에 게시되어 있습니다. low_latency 처리를위한 일반 코드를 제거하지만 하위 수준 드라이버에 대한 매개 변수를 유지합니다.

http://www.kernelhub.org/?p=2&msg=419071

나는 시리얼 콘솔 리눅스 3.12에 low_latency을 강요했습니다. 커널은 매우 불안정했습니다. 선매가 활성화 된 경우 몇 분 후에 사용 중단됩니다.

이제 답을 찾으십시오.

관련 문제