「GCとPCLの和解」の編集履歴(バックアップ)一覧に戻る

GCとPCLの和解 - (2011/12/23 (金) 21:25:39) のソース

GCとPCLの和解
2011.12.23


*はじめに

toy-lang にコルーチンを実装するにあたって、BoehmGC と PCL(Portable Coroutine Library) の間で色々不都合があったのでこれに対応を行ったのでその際の方法をメモとして公開します。

現在の開発中の版ではこれらのライブラリを組み合わせた際の問題はわかっており、すでに解決していますが、解決に至る中でわかったことやプログラミング上のテクニックについて参考になればと思いメモを公開します。

*BoehmGCの動作について

toy-langを実装するにあたっては、できる限り汎用のライブラリを使用して実装することにしています。
toy-langにおいては、GC(ガベージコレクション)はBoehmGCを、コルーチンの実装には PCL を使用しています。

2年ほど前、コルーチンを実装していてどうしてもうまく動かなくて悩んでいました。

まず、GCの動作について非常に簡単ですが説明したいと思います。(Fig.1)

[[Fig.1最初の構成>http://www31.atwiki.jp/toy-lang?cmd=upload&act=open&pageid=22&file=gc_and_coroutine.fig1.jpg]]

この構成の場合、メモリが足りなくなりGCが発動すると、[[Fig.2GCの行われ方>http://www31.atwiki.jp/toy-lang?cmd=upload&act=open&pageid=22&file=gc_and_coroutine.fig2.jpg]]のように、

-①ヒープ領域のGC
-②スタック領域のGC

が実行され、ごみ(どこからも参照されない)と判断されたメモリ領域の回収プロセスが実行されます。
特に②のスタック領域のGCでは、スタックのトップ(現在のスタックポインタ)からボトムに向かってGCが実行されます。

*問題発生
 
上に書いたとおり、当初は各コルーチンのスタック領域はヒープ領域に確保していました。
そして、このようにすると、GCのタイミングでプロセスが確実に落ちます。
これでしばらくの間悩んでいました。2008年の冬から2009年の春ころまでです。
この間 BoehmGC のソースを眺めたり google を検索したりと原因を突き止めようとしていました。

*原因

最終的にたどりついた本現象の原因は[[Fig.3問題発生>http://www31.atwiki.jp/toy-lang?cmd=upload&act=open&pageid=22&file=gc_and_coroutine.fig3.jpg]]のようなことではないかと推測するに至りました。

コルーチンが起動されると、それまでのスタックからコルーチンのスタックに切り替わります。
この時点でGCが発動されると、コルーチンのスタックトップから、もともとのマシンスタックのボトムに向かってGCが行われます。
そうすると、コルーチンのスタックはヒープ領域にとられているため途中でプロセスがアクセスできない領域に対するアクセスが発生することになります。
これがプロセスが落ちる原因ということであると推測しました。2009年の春です。

その後しばらくプログラミングから遠ざかるわけですが。

*対策

で、今年よりまたプログラミングを再開し、上記問題に対応するようなコードを書きました。
それが[[Fig.4解決方法>http://www31.atwiki.jp/toy-lang?cmd=upload&act=open&pageid=22&file=gc_and_coroutine.fig4.jpg]]
に示す内容です。
つまり、GCがスタックのトップからボトムまでをスキャンするのであれば、これを妨げるものを排除するため、コルーチンのスタック領域をすべてマシンスタックの上に配置することにしました。

こうすることで、確かにコルーチンコールからGCが発動されても落ちることはなくなりました。推測は正しかったことになります。

あと、各コルーチンがスタックを壊さないよう、スタックの上部 4Kにバリア領域を設定しています。ここに書き込むとやはり落ちますので、今後はこのハンドルを実装しようとしています。


toy-langにコルーチンを実装しようと思い立ってからすでに三年が過ぎましたが、ようやく解決の出口がみつかりました。
次のバージョンではコルーチンをサポートしたものとなると思います。

































#eof