mutex lock inside spin lock?
글쓴이: totohero / 작성시간: 화, 2009/08/11 - 2:20오후
linux kernel 2.6.30.4 기준으로 drivers/net/ppp_asyn.c의 ppp_async_push() 함수를 보면 아래처럼 spin_lock_bh를 잡고 tty->ops->write(); 를 호출하는데 커널에 등록된 대부분의 tty 장치들의 write() 함수를 보면 안에서 mutex lock을 잡게 되어 있습니다. spin lock을 잡은 상태에서 mutex lock을 잡으려다 잡지 못해 schedule이 발생하는 경우에는 무조건 "BUG: scheduling while atomic" 패닉이 발생하는것 아닌가요? 제가 어떤 부분을 분명 잘못 이해하고 있는 것 같은데 그게 뭘까요? ^^;
static int ppp_async_push(struct asyncppp *ap) { int avail, sent, done = 0; struct tty_struct *tty = ap->tty; int tty_stuffed = 0; <!--break--> /* * We can get called recursively here if the tty write * function calls our wakeup function. This can happen * for example on a pty with both the master and slave * set to PPP line discipline. * We use the XMIT_BUSY bit to detect this and get out, * leaving the XMIT_WAKEUP bit set to tell the other * instance that it may now be able to write more now. */ if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags)) return 0; spin_lock_bh(&ap->xmit_lock); for (;;) { if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags)) tty_stuffed = 0; if (!tty_stuffed && ap->optr < ap->olim) { avail = ap->olim - ap->optr; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); sent = tty->ops->write(tty, ap->optr, avail); if (sent < 0) goto flush; /* error, e.g. loss of CD */ ap->optr += sent; if (sent < avail) tty_stuffed = 1; continue; }
Forums:
2.6.30.4 에서
2.6.30.4 에서 tty_set_operations() 을 사용하는 것들은 다음의 링크에서 보실 수 있습니다.
http://lxr.linux.no/linux+v2.6.30.4/+ident=19332676
구체적으로, 이것들 중 어느 것이 .write() 콜백에서 mutex lock 등 스케쥴러에 접근하고 있는지요 ?
(tty_driver.ops 는 initialize_tty_struct() 안에서 tty_struct.ops 와 연결이 됩니다)
OTL
실은
실은 drivers/char/tty_io.c에서 tty_write -> do_tty_write -> tty_write_lock -> mutex_lock_interruptible 이부분을 보고 질문을 드리고 있습니다.
그곳은 spin lock 후가
그곳은 spin lock 후가 아니라 전입니다.
OTL
죄송합니다만 잘
죄송합니다만 잘 이해가 안되네요. 위의 코드를 보면
spin_lock_bh(&ap->xmit_lock);
가 있고 그 다음sent = tty->ops->write(tty, ap->optr, avail);
에서 tty_write -> do_tty_write -> tty_write_lock -> mutex_lock_interruptible로 호출되는 것 아닌가요?tty_write() 는 /dev/ttyS
tty_write() 는 /dev/ttyS 따위의 장치노드에 대한 file operation 을 수행합니다.
단순 절차상으론
tty_write() -> do_tty_write() -> ldisc.ops.write() -> tty_struct.ops.write()
OTL
아, tty_write는
아, tty_write는 tty_operations의 write 메소드가 아니라 file_operations의 write 메소드였군요! 게다가 대부분 mutex를 쓴다는 것도 저의 착각이었습니다. 하지만 rp_write라는 함수는 mutex를 사용하는 듯 합니다. 버그일까요? 여튼 감사합니다.
쓸데없는
쓸데없는 짓입니다.
보셨다시피, 항상 그 이전에 이미 다른 곳에서 spin lock 이 걸리거나 mutex lock 이 걸린 상태에서 진입합니다.
그곳에서 lock 이 걸리는 바람에 스케쥴러에 간섭해 들어갈 일이 없습니다.
DEBUG 옵션을 켜면 mutex lock 쪽에서 엄청 투덜대긴 하겠지만,
원칙적인 면을 따져서 투덜거리는 것일 뿐 실제로 사건이 발생해서 커널이 패닉 상태로 빠질 가능성이 0 입니다.
OTL
뭐가 쓸데 없다는
뭐가 쓸데 없다는 것인지요? spin lock을 걸고 mutex lock을 거는 것이 문제 없다는 것인가요? 모든 thread가 spin lock을 걸고 mutex lock을 거는 식이라면 해당 mutex는 필요 없는데 잘못 사용하는 경우겠지요. tty_operations의 write 함수의 경우, ppp에서는 spin lock을 걸고 호출하는데 누군가 spin lock없이 write 함수를 호출할 수도 있고 그 경우 ppp에서 spin lock걸고 진입했는데 mutex lock를 얻지못하여 "BUG: scheduling while atomic" 커널 패닉이 발생할 수 있는 상황이라 보입니다만.
그 누군가의
그 누군가의 버그입니다.
라고 썼었는데 전체를 다 보지 않고 단정적으로 말하는게 무책임한 것 같아서,
제 의견이 이렇다는 정도로 그치겠습니다.
OTL
네, 제 의견은, spin
네, 제 의견은, spin lock을 걸지 않고 tty write 함수를 호출하는 누군가에게 버그가 있다기 보단, reschedule될 가능성이 있는 함수를 포함하여 많은 코드를 spin lock안에 집어넣은 ppp의 디자인이 좀 문제가 있고 ppp를 그대로 둔다고 한다면 tty write 함수안에 reschedule될 수 있는 함수를 호출하는 것이 버그라는 것입니다.
댓글 달기