10周年のSPコンテンツ!

QEMUのpthread実装デバッグ

「NetBSD上でQEMUを動かした場合にディスクの負荷をかけるとハングアップすることがある」という問題のデバッグ作業で、QEMU内部のpthreadを使用したセマフォ実装周辺のソースについて@n_sodaさんに助言をもらいながら問題を特定してpkgsrcに修正パッチをコミットしました、というツイートの記録です。 またの名を「実録:@n_sodaさんに仕事をさせようプロジェクト」というまとめ?
プログラミング NetBSD pthread QEMU
10
Izumi Tsutsui @tsutsuii
pkgsrc の qemu-1.4.2 on NetBSD/evbarm 6.1 もビルドできた。
Izumi Tsutsui @tsutsuii
NetBSD/i386 6.1 on QEMU-1.4.2 on NetBSD/hpcarm on Advanced/W-ZERO3[es] http://t.co/S2ImYQrg6k
拡大
Izumi Tsutsui @tsutsuii
QEMU-1.3.1 や 1.4.2 が NetBSD上でなんか変というのは qemu-thread-posix.c で NetBSDには sem_timedwait(3) がないので代わりに pthread_timedwait(3) で実装してあるけどそれがバグってるという説
Izumi Tsutsui @tsutsuii
マルチスレッドのプログラミング セマフォ http://t.co/4bG5k3OJYJ この文章は翻訳された文なのだろうか。だとしたらとてもそうとは思えないほど翻訳の質が高い
Izumi Tsutsui @tsutsuii
ちなみに sem_timedwait(3) は netbsd-6 ブランチ直後の -current で追加されているので 6.99.18 くらいならそっち使うようにすべきという説もある
がたろう TTLでCPUを作る爺(コンパイラやOSも手作りです) @duo6750
機械翻訳文を修正する方法で人間が日本語化した感じがします RT  @tsutsuii マルチスレッドのプログラミング セマフォ http://t.co/VCkZtOe4B7 … この文章は翻訳された文なのだろうか。だとしたらとてもそうとは思えないほど翻訳の質が高い
Izumi Tsutsui @tsutsuii
@duo6750 create や init と対になる命令の destroy を「破壊」と訳すマニュアルがほとんどの中で、ちゃんと「削除」になってるところがわかってる人でないと書けない感じです。アトミック操作が原子的操作なのは意図的なのか妥協なのかわかりませんが
がたろう TTLでCPUを作る爺(コンパイラやOSも手作りです) @duo6750
@tsutsuii この分野では「destroy=破壊」ではないと判る方が翻訳に関与しているのは確かですね。 atomicは迷ったけど「原始的」にしたのでしょう。「この関数にシグナルが割り込みを行いました」も不自然ですが、この種の資料の訳としては珍しく高品質だと思います。
Izumi Tsutsui @tsutsuii
で、 sem_post() と sem_wait() (もしくは sem_timedwait()でTIMEOUTしなかった場合)とは 1:1 であるという前提であれば、これ http://t.co/ocRl06F8EV の while は if であるべきという気がする。どうだろ
SODA Noriyuki @n_soda
@tsutsuii いやwhileが正しいっす。pthread_cond_{,timed}wait()から起きた時の条件チェックはwhileにすべき。
Izumi Tsutsui @tsutsuii
@n_soda その理由は何でしょう。ここでは sem_timedout(3) の代わりの実装なので一般的な話が成り立つのかどうかがよーわからんです。
SODA Noriyuki @n_soda
@tsutsuii 理由は、pthread_cond_signal()は、(ふつうは1つのスレッドのみを起こすんだけど)複数のスレッドを起こしてしまうことがある(これを許すと性能が向上する場合もあるので、規格上許されている)からです。このため、whileで検査しないと、まずい。
Izumi Tsutsui @tsutsuii
@n_soda while で何をチェックするのでしょう?
SODA Noriyuki @n_soda
@tsutsuii (理由は直前のツイートで書いたけど)、whileだと問題が起きて、ifだと動くという理由が逆に思いつきません。ifで問題なく動く環境ならwhileに変えても動くはず(逆は真ならず)。見る限り、すごく素直な計数セマフォの実装に見えます。
SODA Noriyuki @n_soda
@tsutsuii (pthread_cancelを使うような環境でちゃんと動くかは考えてないけど。ふだんcancel使わないようにしてるので、どういうルールでコーディングするか忘れてる...)
SODA Noriyuki @n_soda
@tsutsuii sem_post()でもし複数のスレッドが起きた場合(cond_broadcast()ではなくcond_signal()なので、1つしか起きないライブラリも存在します)、最初に起きたsem_wait()スレッドがsem->count < 0にしてしまうので、
SODA Noriyuki @n_soda
@tsutsuii whileでもう一度sem->count>=0になっていることを検査しとかないと、2番目に動いたスレッドが、誤ってループを抜けてしまいます。
Izumi Tsutsui @tsutsuii
@n_soda 一つの sem_post() で複数の sem_wait() スレッドが起きるのならば起きた数だけカウンタ動かさないと計数セマフォとしてズレませんかね
SODA Noriyuki @n_soda
@tsutsuii 複数起きるんだけど、sem->count<0の場合はまた寝ちゃうので、結局、起きてループを抜ける数は、sem_postでインクリメントした数と同一になるはず。
Izumi Tsutsui @tsutsuii
@n_soda 呼んでるのは これ http://t.co/ocRl06F8EVhttp://t.co/crNMjPVwsE なんですがなんか count が変な値になって永遠の待ちになるんですよね。ロックが足りない?
SODA Noriyuki @n_soda
@tsutsuii あ、もう一つ理由あった。スレッドA:sem_wait()で休眠。スレッドB:sem_post()で起こす。スレッドC:このタイミングでsem_wait()に突入して、実行権をかっさらう。スレッドA:Bに起こされたので起床。という順序で動くと、whileが必要。
SODA Noriyuki @n_soda
@tsutsuii 永遠の待ちになってる時、sem->countの値はいくつなんでしょ?
Izumi Tsutsui @tsutsuii
@n_soda また見てみますが qemu_sem_timedwait()から返ってきた時点では1だったような。I/Oが激しくなるとおかしくなるのでなんか抜けててズレてる感
Izumi Tsutsui @tsutsuii
http://t.co/pCJeBZ89um 1.3.0→1.3.1でこんな修正入ってる(このせいで1.3.0は全然動かなかった)のでほかにもポカミスがあるという根拠レスな予想
残りを読む(247)

コメント

Izumi Tsutsui @tsutsuii 2013年8月6日
というわけでパッチがコミットされたのでまとめを更新しました。pkgsrc的には自前でパッチ当てるのであまり気にしてませんでした……
ログインして広告を非表示にする
ログインして広告を非表示にする