TOKUNAGA Hiroyuki
tkng****@xem*****
2005年 9月 24日 (土) 23:07:54 JST
On Sat, 24 Sep 2005 14:16:32 +0900 YamaKen <yamak****@bp*****> wrote: > ヤマケンです。 > > しばらく前から徳永さんがuimをthread safeにするための作業を行って > らっしゃいますが、r1558のコードには疑問があったので一時的に > revertさせてもらいました。 > > 問題を感じているのはuimを単にthread safeにするだけでなく > reentrantにするという方針です。 私はthread safeとreentrantに関して、あまり深く考えずに使っています。 Thread safeであればそれで十分です。 > r1558のcommit logには"to make uim reentrant"とあり、 > UIM_EVAL_FSTRINGn_WITH_MUTEX()というmutex付きevalマクロが導入さ > れています。しかし、uimの中核であるSchemeインタプリタは現在trunk > で使用されているSIODにしても近く導入予定のSigSchemeにしても > reentrantではありません。よって、これを変えない限りはuimのC部分 > がいくらmutex lockの粒度を小さくしても肝心のScheme部分ですぐに待 > たされる事になり無意味です。 libuimの関数は全て短時間で返ることが期待されるので、Thread safeにさえ なれば、これ以上mutexの粒度を下げても大してメリットは無いと思っていま す。というわけで、mutexの粒度を下げる予定はありません。というか、これで うまくいったら、mutex回りはもういじりたくないです。 > このような事情から現在のuimではAPI関数毎にgiant lockをかけるのが > 現実的な落としどころだと思いますし、徳永さんの日記でもそういった > 意図でアドバイスをさせてもらいました。表現が悪くて伝わらなかった > かもしれませんが。 ThreadまわりはAPI関数毎にgiant lockをかける、というのはひとつのmutexを libuim内部で共有する、という事でいいのでしょうか?そういう仮定で話を進め ます。 この場合、uim_switch_imで問題が出てきます。uim_switch_imは uim_reset_contextを呼びますが、uim_reset_contextは外部から呼ばれる可能性 があるので、API毎にロックをかけると、二重でロックしてしまうことになりま す。 これを解決するには a. 再帰的なロックを使う b. staticなuim_reset_context_internalという関数を作り、uim_reset_context はロックをかけてからuim_reset_context_internalを呼ぶだけの関数にする の2つの解決法が考えられますが、aは移植性に疑問を持ったので断念しました。 (LinuxではPTHREAD_MUTEX_RECURSIVEは#ifdef __USE_UNIX98でないと使えない が、#define __USE_UNIX98するとコンパイルできなかった。かといって FreeBSDではPTHREAD_MUTEX_RECURSIVE_NPは使えない。)実際にやってみたら、 Linux以外はFreeBSDのやりかたでいけるのかもしれませんが…。 他のソフトウェアはどうなっているのかも調べてみましたが、glibは再帰的な ロックは自分でロックカウントを計算して実装していました。gaucheも PTHREAD_MUTEX_RECURSIVEは使わず、ポートの再帰的なロックは自力での実装 になっていました。身近なアプリケーションではPTHREAD_MUTEX_RECURSIVEを 使っているものはみつけられなかったわけで、これも移植性に問題があるので は、と私に疑わせている一因です。 b. は個人的に気に入らないやり方なのでやりません。やるなら全ての関数で やるべきだと思いますがそれはあまりに手間だし、uim_reset_contextだけ 別途非ロック版を用意するのは面白くない。 > [Anthy-dev 2337]のようにthread safeにする責任をlibuimより上の層 > に委ねるというのも一つの手ですが、私は上述のようなgiant lockぐら > いならlibuimで提供してもよいと思います。ただしconfigure時の指定 > でthread safe版と通常版の両方をビルドできるようにし、ブリッジや > プラットフォーム毎にどちらをリンクするか選択できるようにする必要 > はありますが(pthreadの存在検出だけでは不十分)。 [Anthy-dev 2337] は「単純なポインターの読み書きにロックをかける必要は無 い」という話で、thread safeにする責任については扱ってないと思うのです が、「thread safeにする責任をlibuimより上の層に委ねる」というのはどうい う事でしょうか?Bridge側でロックをかけるようにするとか? それと、pthreadの存在検出だけでは不十分、というのは、どういう場合に問題 が起こるのでしょう?pthreadが存在する場合はそれをリンクするようにすれば それで動作上は問題ない(シングルスレッドなアプリケーションでパフォーマン スが少し無駄に落ちるだけ)ように思えます。 -- 徳永拓之 tkng at xem jp