mutex lock inside spin lock?

totohero의 이미지

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;
		}
bushi의 이미지

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

totohero의 이미지

실은 drivers/char/tty_io.c에서 tty_write -> do_tty_write -> tty_write_lock -> mutex_lock_interruptible 이부분을 보고 질문을 드리고 있습니다.

bushi의 이미지

그곳은 spin lock 후가 아니라 전입니다.

OTL

totohero의 이미지

죄송합니다만 잘 이해가 안되네요. 위의 코드를 보면 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로 호출되는 것 아닌가요?

bushi의 이미지

tty_write() 는 /dev/ttyS 따위의 장치노드에 대한 file operation 을 수행합니다.
단순 절차상으론
tty_write() -> do_tty_write() -> ldisc.ops.write() -> tty_struct.ops.write()

OTL

totohero의 이미지

아, tty_write는 tty_operations의 write 메소드가 아니라 file_operations의 write 메소드였군요! 게다가 대부분 mutex를 쓴다는 것도 저의 착각이었습니다. 하지만 rp_write라는 함수는 mutex를 사용하는 듯 합니다. 버그일까요? 여튼 감사합니다.

bushi의 이미지

쓸데없는 짓입니다.
보셨다시피, 항상 그 이전에 이미 다른 곳에서 spin lock 이 걸리거나 mutex lock 이 걸린 상태에서 진입합니다.
그곳에서 lock 이 걸리는 바람에 스케쥴러에 간섭해 들어갈 일이 없습니다.
DEBUG 옵션을 켜면 mutex lock 쪽에서 엄청 투덜대긴 하겠지만,
원칙적인 면을 따져서 투덜거리는 것일 뿐 실제로 사건이 발생해서 커널이 패닉 상태로 빠질 가능성이 0 입니다.

OTL

totohero의 이미지

뭐가 쓸데 없다는 것인지요? 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" 커널 패닉이 발생할 수 있는 상황이라 보입니다만.

bushi의 이미지

누군가의 버그입니다.

라고 썼었는데 전체를 다 보지 않고 단정적으로 말하는게 무책임한 것 같아서,
제 의견이 이렇다는 정도로 그치겠습니다.

OTL

totohero의 이미지

네, 제 의견은, spin lock을 걸지 않고 tty write 함수를 호출하는 누군가에게 버그가 있다기 보단, reschedule될 가능성이 있는 함수를 포함하여 많은 코드를 spin lock안에 집어넣은 ppp의 디자인이 좀 문제가 있고 ppp를 그대로 둔다고 한다면 tty write 함수안에 reschedule될 수 있는 함수를 호출하는 것이 버그라는 것입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.