2011-09-08
(続)Haskell(GHC)での軽量ユーザスレッドの実装方法
Haskell(GHC)での軽量ユーザスレッドの実装方法で、Cmm が軽量スレッドのポイントと書きました。しかし、GHC の実装者 Simon Marlow 先生から「Cmm は関係ないよ」と教えて頂きました。
StgCall
StgCall がいくつかのレジスタを保存するのは、採用しているCの関数呼び出し規約がそうなっているから。スレッドとはまったく無関係。
GHC のランタイムは C で書かれている。よって、スケジューラからスレッドを呼び出すと、C から Haskell を呼び出すことになる。C では、呼び出された関数がレジスタを保存しなければならない。Haskell の関数には、こういった制約はない。なので、C から Haskell の関数を呼び出す際は、C の規約を肩代わりしてやる必要がある。それが StgCall。
スタック
Haskell のスタックは C のスタックと同様、特定のレジスタが指す場所。(Cの場合はスタックレジスタだろうが、Haskell の場合はそうではない。しかし本質的には同じこと。)
ただし、Haskell のスタックは、自由に領域を拡張したり、動かしたりできる。GC は、スタックを正しく扱えるように作られている。だから、スレッドのスタックは小さい領域で始められる。
コンテキストスイッチ
安全なポイントのみでコンテキストスイッチする。(コードを見る限り、タイムアウトやスタック溢れのなどが対象。スタック溢れの場合は、スタックを拡張してキューに入れる。これは安全そう。しかし、タイムアップの場合は安全なのか僕には判断できない。)
よって、保存しなければならないコンテキストは、CPU に依存しない。だから、真のプリエンプティブだとは言えないが、十分に頻繁なのでプログラマーには認識できない。
外部言語の関数呼び出し
ユーザスレッドの実装は、外部言語の関数呼び出しをサポートする際に行き詰まることが多い。つまり、呼び出した外部言語の関数でブロックされ、他のユーザスレッドが動かなくなる。
Haskell では、外部言語の関数呼び出し専用のカーネルスレッドを用意していて、ユーザスレッドがブロックされないようになっている。この手法は素晴らしいが、他の言語コミュニティは、素晴らしさに気付いていないようだ。
あわせて読みたい
- 93 http://reader.livedoor.com/reader/
- 92 http://pipes.yahoo.com/pipes/pipe.info?_id=04913f684f1141e0b48179f97811ce12
- 77 http://www.kt.rim.or.jp/~kbk/zakkicho/
- 62 http://www.google.co.jp/url?sa=t&source=web&cd=1&ved=0CBkQFjAA&url=http://d.hatena.ne.jp/kazu-yamamoto/20080827/1219820703&rct=j&q=動的型言語 デザインパタ?%
- 60 http://www.reddit.com/r/haskell/comments/k8nu6/continued_haskell_ghc_in_a_lightweight/
- 58 http://t.co/sWjhQPI
- 44 http://www.kt.rim.or.jp/~kbk/zakkicho/index.html
- 40 http://www.mew.org/~kazu/doc/book/haskell.html
- 37 http://www.reddit.com/r/haskell/
- 30 http://www.reddit.com/r/haskell

