(57)【要約】      （修正有）【課題】実行キューを共有する複数のプロセッサでデッドロックを防ぐプロセスディスパッチ処理方法を提供する。【解決手段】実行キューを共有する複数のプロセッサの各々に、ディスパッチャ用スタックが割り当てられる。各プロセッサは、プロセスディスパッチ処理において、切替え元プロセス（実行中のプロセス）のコンテキストを切替え元プロセスのスタックに保存し、自プロセッサのディスパッチャ用スタックにディスパッチャ用コンテキストを保存し、切替え元プロセスを実行キューに挿入し、切替え先プロセスを実行キューから取り出し、且つ、切替え先プロセスのスタックから切替え先プロセスのコンテキストを復元する。【選択図】図１０
2014191468.tif 000002
【特許請求の範囲】
【請求項１】
プロセスの待ち行列である実行キューを共有する複数のプロセッサと、
プロセスのスタックが設定されるメモリと
を有し、
前記メモリに、前記複数のプロセッサにそれぞれ対応した複数のディスパッチャ用スタックが設定され、
各プロセッサは、保持しているスタックの解放前にどのプロセッサにも保持されていない別のスタックを獲得してから前記保持しているスタックを解放するようになっており、
前記各プロセッサは、実行中のプロセスを切り替えるディスパッチ処理において、
（Ａ）前記実行中のプロセスである切替え元プロセスのコンテキストを前記切替え元プロセスの保持しているスタックに保存し、
（Ｂ）自プロセッサのディスパッチャ用スタックを獲得し、前記切替え元プロセスのスタックを解放し、前記獲得したディスパッチャ用スタックにディスパッチャ用コンテキストを保存し、
（Ｃ）前記切替え元プロセスを前記実行キューに挿入し、
（Ｄ）切替え先プロセスを前記実行キューから取り出し、
（Ｅ）前記切替え先プロセスのスタックを獲得し、保持している前記ディスパッチャ用スタックを解放し、前記切替え先プロセスの前記獲得したスタックから前記切替え先プロセスのコンテキストを復元する、
計算機。
【請求項２】
前記ディスパッチ処理が、（Ａ）及び（Ｂ）の処理を含むディスパッチ入口処理、（Ｃ）及び（Ｄ）の処理を含むディスパッチ本体処理、及び、（Ｅ）の処理を含むディスパッチ出口処理で構成されており、
前記ディスパッチ入口処理は、前記ディスパッチ入口処理の呼び出し元情報の保存が必要な処理であり、前記ディスパッチ本体処理及び前記ディスパッチ出口処理は、それぞれの呼び出し元の情報の保存が不要な処理である、
請求項１記載の計算機。
【請求項３】
前記ディスパッチ入口処理が、前記ディスパッチ入口処理の呼び出し元情報を保存する処理と、（Ａ）の処理と、（Ｂ）の処理と、前記ディスパッチ本体処理の呼び出す処理とを含み、
前記ディスパッチ本体処理は、（Ｃ）の処理と、（Ｄ）の処理と、前記ディスパッチ出口処理の呼び出す処理とを含み、
前記ディスパッチ出口処理が、（Ｅ）の処理と、前記ディスパッチ入口処理で保存した前記呼び出し元情報が示す、前記ディスパッチ入口処理の呼び出し元、へ復帰する処理とを含む、
請求項２記載の計算機。
【請求項４】
前記ディスパッチャ用コンテキストは、前記ディスパッチ本体処理及び前記ディスパッチ出口処理を呼び出し使用される情報を含む、
請求項２記載の計算機。
【請求項５】
各プロセッサは、スタック内で最も後に参照された位置を示す情報であるスタックポインタを有しており、（Ａ）の処理から（Ｂ）の処理に遷移する場合には、前記自プロセッサのスタックポインタを、前記ディスパッチャ用スタックの所定位置を指す情報に更新する、
請求項１記載の計算機。
【請求項６】
保持しているスタックの解放前にどのプロセッサにも保持されていない別のスタックを獲得してから前記保持しているスタックを解放するようそれぞれがなっている複数のプロセッサが共有しプロセスの待ち行列である実行キューを使用して実行中のプロセスを切り替えるディスパッチ処理において、
（Ａ）実行中のプロセスである切替え元プロセスのコンテキストを、前記切替え元プロセスを実行中のプロセッサである対象プロセッサが保持しているスタックに保存し、
（Ｂ）前記対象プロセッサのディスパッチャ用スタックを獲得し、前記切替え元プロセスのスタックを前記対象プロセッサから解放し、前記獲得したディスパッチャ用スタックに前記対象プロセッサについてのディスパッチャ用コンテキストを保存し、
（Ｃ）前記切替え元プロセスを前記実行キューに挿入し、
（Ｄ）切替え先プロセスを前記実行キューから取り出し、
（Ｅ）前記切替え先プロセスのスタックを前記対象プロセッサについて獲得し、保持している前記ディスパッチャ用スタックを前記対象プロセッサから解放し、前記切替え先プロセスの前記獲得したスタックから前記切替え先プロセスのコンテキストを前記対象プロセッサに復元する、
プロセスディスパッチ処理方法。
【請求項７】
前記ディスパッチ処理が、（Ａ）及び（Ｂ）の処理を含むディスパッチ入口処理、（Ｃ）及び（Ｄ）の処理を含むディスパッチ本体処理、及び、（Ｅ）の処理を含むディスパッチ出口処理で構成されており、
前記ディスパッチ入口処理は、前記ディスパッチ入口処理の呼び出し元情報の保存が必要な処理であり、前記ディスパッチ本体処理及び前記ディスパッチ出口処理は、それぞれの呼び出し元の情報の保存が不要な処理である、
請求項６記載のプロセスディスパッチ処理方法。
【請求項８】
前記ディスパッチ入口処理が、前記ディスパッチ入口処理の呼び出し元情報を保存する処理と、（Ａ）の処理と、（Ｂ）の処理と、前記ディスパッチ本体処理の呼び出す処理とを含み、
前記ディスパッチ本体処理は、（Ｃ）の処理と、（Ｄ）の処理と、前記ディスパッチ出口処理の呼び出す処理とを含み、
前記ディスパッチ出口処理が、（Ｅ）の処理と、前記ディスパッチ入口処理で保存した前記呼び出し元情報が示す、前記ディスパッチ入口処理の呼び出し元、へ復帰する処理とを含む、
請求項７記載のプロセスディスパッチ処理方法。
【請求項９】
前記ディスパッチャ用コンテキストは、前記ディスパッチ本体処理及び前記ディスパッチ出口処理を呼び出し使用される情報を含む、
請求項７記載のプロセスディスパッチ処理方法。
【請求項１０】
各プロセッサは、スタック内で最も後に参照された位置を示す情報であるスタックポインタを有しており、
（Ａ）の処理から（Ｂ）の処理に遷移する場合には、前記実行中のプロセッサのスタックポインタを、前記ディスパッチャ用スタックの所定位置を指す情報に更新する、
請求項６記載のプロセスディスパッチ処理方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プロセスのディスパッチ処理に関する。
【背景技術】
【０００２】
計算機において、オペレーティングシステムのスケジューラは、プロセッサ資源を複数のプロセスの間で、時分割共有する役割を担う。オペレーティングシステムのスケジューラが有し、プロセスのスケジューリングで使用する基本的なデータ構造に、実行キューがある。実行キューは、プロセッサ上で実行可能なプロセスを格納する、待ち行列である。
【０００３】
スケジューラのスケジューリング処理のうち、特に、プロセッサ上で実行するプロセスを切り替える処理を、プロセスのディスパッチ処理と呼ぶ。プロセスのディスパッチ処理を担うオペレーティングシステムの構成要素を、特にディスパッチャと呼ぶ。
【０００４】
プロセッサ上で実行するプロセスを切り替えるときは、ディスパッチャが呼び出される。ディスパッチャが呼び出されると、ディスパッチ処理が実行される。ディスパッチャは、現在のプロセスを実行キューに挿入して、実行キューの中から最も優先度の高いプロセスを取り出して、取り出したプロセスをプロセッサ上で実行させる。
【０００５】
実行キューには、２つの形態がある。１つは、プロセッサごとに個別に実行キューを持たせる、ローカル実行キューである。もう１つは、複数のプロセッサで1つの実行キューを共有する、共有実行キューである。計算機の全てのプロセッサで共有される共有実行キューは、特に、グローバル実行キューと呼ばれる。
【０００６】
一般に、オペレーティングシステムは、主にローカル実行キューを用いる。ローカル実行キューを用いると、プロセスのスケジューリングが、複数プロセッサ間で、独立に動作する。そのため、複数プロセッサ間の競合がなく、プロセッサ数に関する高いスケーラビリティが得られる。また、プロセスが1つのプロセッサにとどまるので、各プロセッサが個別にキャッシュを持っていたときは、キャッシュの効率性の効果も大きい。
【０００７】
しかし、近年は、１つのソケットに複数のプロセッサコアが搭載されるマルチコアプロセッサが、標準になってきている。マルチコアプロセッサでは、一般に大容量キャッシュがソケット単位になり、ソケット内の複数プロセッサが大容量キャッシュを共有する構造が、とられている。そのため、キャッシュの効率性に関しては、１つのプロセスは１つのソケットにとどまれば十分である。
【０００８】
また、計算機では、プロセッサ間の負荷分散やプロセス間の資源配分の比率制御が、重要である。ローカル実行キューを用いる場合は、プロセスのスケジューリングは、プロセッサ間で独立に行われ、プロセッサ間で負荷を共有しない。従って、スケジューラは、自分でプロセッサ間の負荷の偏りや仮想計算機間の資源配分の不均衡を検出して、プロセスをプロセッサ間で明示的に移動させて動的に調整する必要がある。
【０００９】
しかし、この調整は複雑で難しく、処理コストも大きい。プロセッサ数の増加に伴い、複雑さやコストは増してきている。
【００１０】
これらの課題に対しては、共有実行キューをプロセッサのソケット単位に設け、ソケット内のプロセッサで共有すれば、キャッシュの効率性はローカル実行キューとほぼ同等を達成することができる。また、ソケット内のプロセッサで負荷を共有しているので、ソケットを１つの大きなプロセッサとみなすことができ、ソケット内では、プロセッサ間で明示的にプロセスを移動させることなく、プロセッサ間の負荷分散やプロセス間の資源配分の比率制御を自然に行うことができる。
【００１１】
共有実行キューを用いると、キャッシュの効率性に関しては、ローカル実行キューとほぼ同等で、負荷分散や比率制御が単純になる効果が期待できる。
【００１２】
しかし、非特許文献１に記載の通り、広く知られた従来のディスパッチ処理方法では、デッドロックに陥る可能性があり、その解決策も不十分のため、期待通りの効果が得られない。
【００１３】
共有実行キューを用いたときに、プロセスディスパッチ処理において共有実行キューへのアクセスの競合のオーバヘッドを削減する方法が、特許文献１に記載されている。特許文献１では、複数のプロセッサで共有する共有実行キューとプロセッサごとのローカル実行キューとが設けられ、プロセスディスパッチ処理では、できる限りローカル実行キューにアクセスすることが行われ、それにより、共有実行キューへのアクセスが減らされる。
【００１４】
しかしながら、この特許文献１には、共有実行キューを用いた場合のプロセスディスパッチ処理を直接的に改善する方法は提案されていない。
【先行技術文献】
【特許文献】
【００１５】
【特許文献１】ＵＳ６７２８９５９
【非特許文献】
【００１６】
【非特許文献１】Ｕ．Ｖａｈａｌｉａ，ＵＮＩＸ  Ｉｎｔｅｒｎａｌｓ  −  Ｔｈｅ  Ｎｅｗ  Ｆｒｏｎｔｉｅｒｓ，Ｐｒｅｎｔｉｃｅ  Ｈａｌｌ，１９９５  ５．４節、Ｔｒａｄｉｔｉｏｎａｌ  ＵＮＩＸＳｃｈｅｄｕｌｉｎｇ、１１７ページ〜１２１ページ
【発明の概要】
【発明が解決しようとする課題】
【００１７】
ディスパッチャは、それ自身のスタックを持たない。しかし、プログラムを実行するためにはスタックが不可欠である。それゆえ、ディスパッチャは、自身を呼び出した現在実行中のプロセスと次に実行するプロセスとスタックを共有して実行する。そして、ディスパッチャが実行しているときは、スタックを途切れさせないようにするために、現在実行中のプロセスのコンテキスト退避と、次に実行するプロセスのコンテキスト復元が、コンテキスト切り替えと呼ぶ一連の処理として実行される。
【００１８】
また、コンテキスト切り替えを実行するためには、次に実行するプロセスを決める必要がある。このため、現在走行中のプロセスの実行キューへの挿入と次に実行するプロセスの実行キューからの取り出しが、現在実行中のプロセスから次に実行するプロセスへのコンテキスト切り替えの前に行われる必要がある。
【００１９】
実行キューを共有実行キューとし、その共有実行キューを複数プロセッサで共有すると、ディスパッチ処理でデッドロックが発生する可能性がある。デッドロックとは、２つ以上のプロセッサが自分以外のプロセッサの処理の終了を待ち、結果としてそれら２つ以上のプロセッサのどのプロセッサも先に進めなくなる状態を言う。
【００２０】
具体的には、ディスパッチャは、あるプロセッサ上で、それ自身を呼び出した現在のプロセスのコンテキストを保存する前に、そのプロセスを共有実行キューに挿入する。このため、別のプロセッサ上で実行中のディスパッチャは、そのプロセスのコンテキスト保存が完了する前に、そのプロセスを次に実行するプロセスに選択することができる。故に、ディスパッチャが、あるプロセスを次に実行するプロセスに選択したときに、選択したプロセスのコンテキスト保存が完了していない場合がある。この場合、ディスパッチャは、選択したプロセスのコンテキスト保存が完了するまで、待たされる。ディスパッチャは、現在のプロセスのコンテキスト保存と次のプロセスのコンテキスト復元を、コンテキスト切り替えと呼ぶまとまった一つの処理として実行する。このため、ディスパッチャは、次に実行するプロセスのコンテキスト保存が完了するまで、次に実行するプロセスのコンテキスト復元と、現在実行中のプロセスのコンテキスト保存が待たされる。このプロセスのコンテキスト保存の待ちが複数プロセッサ間で循環すると、デッドロックが発生してしまう。
【課題を解決するための手段】
【００２１】
実行キューを共有する複数のプロセッサの各々に、ディスパッチャ用スタックが割り当てられる。各プロセッサは、プロセスディスパッチ処理において、切替え元プロセス（実行中のプロセス）のコンテキストを切替え元プロセスのスタックに保存し、自プロセッサのディスパッチャ用スタックにディスパッチャ用コンテキストを保存し、切替え元プロセスを実行キューに挿入し、切替え先プロセスを実行キューから取り出し、且つ、切替え先プロセスのスタックから切替え先プロセスのコンテキストを復元する。
【発明の効果】
【００２２】
各プロセッサが、保持しているスタックの解放前にどのプロセッサにも保持されていない別のスタックを獲得してから保持しているスタックを解放するようになっていても、切替え先プロセスの選択前に、それまで実行していた切替え元プロセスのコンテキストの切替えについて、切替え元プロセスのスタック内への保存が完了していることが保証される。このため、プロセッサが切替え元のプロセスのスタックを解放してから切替え先のプロセスのスタックを獲得することができるようになっており、故に、実行キューを共有する複数のプロセッサでのディスパッチ処理においてデッドロックが発生しない。
【図面の簡単な説明】
【００２３】
【図１】実施形態に係る計算機の概要を示す構成図。
【図２】実施形態に係るスケジューリングとディスパッチの説明図。
【図３】プロセスのコンテキストの保存と復元の処理の流れを示す概念図。
【図４】実施形態の比較例に係るディスパッチ処理の実行フロー。
【図５】実施形態の比較例に係るディスパッチ処理の流れの示す概念図の第１部分。
【図６】実施形態の比較例に係るディスパッチ処理の流れの示す概念図の第２部分。
【図７】実施形態の比較例に係るディスパッチ処理の流れの示す概念図の第３部分。
【図８】実施形態の比較例に係るディスパッチ処理の流れの示す概念図の残り部分。
【図９】実施形態の比較例に係るディスパッチ処理においてデッドロックが発生する可能性があることを示す概念図。
【図１０】実施形態に係るディスパッチ処理の実行フロー。
【図１１】実施形態に係るディスパッチ処理の流れの示す概念図の第１部分。
【図１２】実施形態に係るディスパッチ処理の流れの示す概念図の第２部分。
【図１３】実施形態に係るディスパッチ処理の流れの示す概念図の第３部分。
【図１４】実施形態に係るディスパッチ処理の流れの示す概念図の残り部分。
【図１５】実施形態に係るディスパッチ処理においてデッドロックが発生しないことを示す概念図。
【発明を実施するための形態】
【００２４】
本発明の一実施形態を、図面を用いて詳細に説明する。
【００２５】
なお、以下の実施形態では、実行キュー（共有実行キュー）を共有するプロセッサの数は２であるが、実行キューを共有するプロセッサの数は２より多くてよい。
【００２６】
また、以下の説明では、同種の要素を区別して説明する場合には、親符号と子符号の組合せとしての参照符号を使用し（例えばプロセッサ０（０１０ａ）、同種の要素を区別しないで説明する場合には、親符号のみ（例えばプロセッサ０１０）を使用する。
【００２７】
また、以下の説明では、プログラム、プロセス或いは関数等を主語に処理を説明する場合があるが、プログラム、プロセス或いは関数等は実際にはプロセッサによって行われるので、その処理の主語をプロセッサとすることができる。
【００２８】
図１は、本発明の一実施形態に係る計算機の概要を示す構成図である。
【００２９】
計算機１０００のハードウェア資源００１は、実行キューを共有する２つのプロセッサ０（０１０ａ）とプロセッサ１（０１０ｂ）を含む。また、ハードウェア資源００１は、メモリ０２０、ディスク０３０、及び様々な他のデバイス０４０を含む。プロセッサ０（０１０ａ）及びプロセッサ１（０１０ｂ）が、メモリ０２０、ディスク０３０及びデバイス０４０に通信可能に接続される。
【００３０】
プロセッサ０１０は、プログラムを実行するためのハードウェア資源を有する。具体的には、例えば、プロセッサ０（０１０ａ）は、ハードウェア資源として、プログラムカウンタ（ＰＣ）０１１ａ、汎用レジスタ（ＧＲ）０１２ａ、及びスタックポインタ（ＳＰ）０１３ａを有する。プロセッサ１（０１０ｂ）も同様のハードウェア資源０１１ｂ、０１２ｂ及び０１３ｂを有する。プログラムカウンタ０１１は、次に実行する命令が格納されているメモリ上のアドレスを示すレジスタである。汎用レジスタ０１２は、特定の機能に限定せずに多目的に使用されるレジスタであり、例えばデータ、命令やデータを格納したメモリのアドレス、及び演算結果を一時的に記憶するために使用される。スタックポインタ０１３は、スタック内で最も後に参照された位置を示すレジスタ（情報）であり、スタックにデータを保存したり、スタックからデータを取り出したりするために使用される。ここで、スタックは、後入れ先出しのメモリ上のデータ構造であり、関数呼び出しでの引数渡し、関数の呼び出し元アドレスの保存、及び、関数を実行するための変数の一時保存等に使用される。プロセッサ０１０は、その他のハードウェア資源（例えば複数レベルのキャッシュ等）を有してよい。
【００３１】
メモリ０２０は、プログラム及びデータを記憶する揮発性メモリであるが、他種のメモリでもよい。
【００３２】
ディスク０３０は、プログラム及びデータを記憶する不揮発性のディスク型記憶デバイス（例えばハードディスクドライブ）であるが、他種の記憶デバイスでもよい。
【００３３】
デバイス０４０は、計算機１０００の外部の通信ネットワークを通して外部の計算機と通信するための通信インタフェースデバイス、外部のディスクと接続するため拡張カード、指定した時刻にプロセッサ０（０１０ａ）とプロセッサ１（０１０ｂ）に割り込みを発生させるタイマなどを含むが、本実施形態ではその詳細は問わないので、まとめて単にデバイス０４０と言う。
【００３４】
メモリ０２０にオペレーティングシステム（ＯＳ）１００が記憶され、プロセッサ０１０によってＯＳ１００が実行されることで、プロセス２００が実行される。具体的には、ＯＳ１００は、ハードウェア資源００１を管理し、プロセス０（２００ａ）からプロセス６（２００ｆ）に共通のサービスを提供する。ＯＳ１００は、ハードウェア資源００１とプロセス０（２００ａ）からプロセス６（２００ｆ）の間の仲介の役割を果たす。ＯＳ１００は、カーネル１１０、ブートローダ１６０、及びデバイスドライバ１７０を有する。
【００３５】
カーネル１１０は、ＯＳ１００の中核となる部分であり、プロセス２００や周辺機器の監視、プロセッサ０１０やメモリ０２０などのハードウェア資源００１の管理、割り込み処理、プロセス間通信等、オペレーティングシステムとしての基本機能を提供する。
【００３６】
ブートローダ１６０は、計算機の起動直後に動作し、ＯＳ１００をディスク０３０からメモリ０２０に読み込んで起動する機能を提供する。
【００３７】
デバイスドライバ１７０は、拡張カードや周辺機器等の入出力デバイスを制御する機能を提供する。
【００３８】
カーネル１１０は、スケジューラ１２０、ディスパッチャ１３０、仮想記憶１４０、及びファイルシステム１５０を有する。
【００３９】
スケジューラ１２０は、プロセッサ０１０を複数のプロセス２００で時分割共有するためにプロセス２００の実行順序を決める役割を担い、定期的に呼び出されて複数プロセス２００の中で次にどのプロセス２００をプロセッサ０１０に割り当てるかを決定する。この機能を特に「スケジューリング」と呼ぶ。
【００４０】
ディスパッチャ１３０は、プロセッサ０１０を複数のプロセス２００で時分割共有するためにプロセッサ０１０上で実行するプロセス２００を切り替える。この機能を特に「ディスパッチ」と呼ぶ。スケジューラとディスパッチャをまとめて「スケジューラ」と呼ぶことがある。具体的には、スケジューラ１２０がディスパッチャ１３０としての機能を含んでいてもよい。
【００４１】
仮想記憶１４０は、プロセス２００の要求に応じてメモリ０２０の一部を割り当てたり、そのメモリ０２０が割り当てたプロセス２００にとって不要になったときに再利用のために解放したりするメモリ管理と、不連続なメモリ領域をプロセス０２０に連続であるように見せかける仮想アドレス管理とを用いて、メモリ０２０の容量よりも大きなメモリ容量を仮想的に利用可能にする機能を提供する。
【００４２】
ファイルシステム１５０は、主にディスク０３０等に記録された様々なデータをファイルとして管理する機能を提供する。プロセス０２０は、ファイルシステム１５０を介して、統一した方式で様々なデータにアクセスすることができる。
【００４３】
プロセス２００（２００ａ〜２００ｆ）は、アプリケーション等のプログラムのための実行環境であり、カーネル１１０によって提供される。
【００４４】
図２は、本実施形態に係るケジューリングとディスパッチの説明図である。
【００４５】
プロセス３（２００ｃ）は、プロセス構造体２１０ｃとスタック２２０ｃを、メモリ０２０上に持つ。プロセス構造体２１０ｃは、カーネル１１０にとって必要なプロセスの情報を保持するデータ構造であり、プロセス識別情報２１１ｃ、プロセス管理情報２１２ｃ、及びスタックポインタ値２１３ｃで構成される。スタック２２０ｃは、関数の呼び出し元アドレスの保存、関数のローカル変数の保持、及びプロセス切り替え時に汎用レジスタの内容を保存したりするために使われる。プロセス１（２００ａ）、プロセス２（２００ｂ）、プロセス４（２００ｄ）、プロセス５（２００ｅ）、及びプロセス６（２００ｆ）も同様である。
【００４６】
プロセス０（２００ａ）とプロセス２（２００ｂ）が、それぞれプロセッサ０（０１０ａ）とプロセッサ１（０１０ｂ）上で実行中のときは、プロセス３（２００ｃ）、プロセス４（２００ｄ）、プロセス５（２００ｅ）、及びプロセス６（２００ｆ）は、待ち状態になる。スケジューラ１２０は、これらの実行待ち状態のプロセスを実行キュー１２１で管理する。実行キュー１２１が、プロセッサ０（０１０ａ）とプロセッサ１（０１０ｂ）で共有される。つまり、実行キュー１２１は、ローカル実行キューと共有実行キューの２つの形態のうち、共有実行キューである。実行キュー１２１は、例えば、メモリ０２０を使用して管理される。
【００４７】
実行キュー１２１は、待ち行列であり、実行キューの中のプロセス２００をどのような順に並べるかは、スケジューラ１２０が制御する。実行キュー１２１におけるプロセス２００の並べ方の方式として後入れ先出しや優先度順など様々なものがあるが、本実施形態ではその詳細を問わない。
【００４８】
本実施形態では、プロセッサ０（０１０ａ）とプロセッサ１（０１０ｂ）それぞれに、ディスパッチャ１３０用のスタック１３１ａとディスパッチャ用スタック１３１ｂが割り当てられる。このようなスタック１３１を用いてディスパッチ処理を変更し、共有実行キュー１２１を用いるときのデッドロックの問題を、複数プロセッサ０１０間のロック競合を引き起こすことなく解決し、共有実行キュー１２１の効果を期待通りに得られるようにすることができる。
【００４９】
まず、スタック１３１ａとスタック１３１ｂの必要性を示す。プロセス２００がプロセッサ０１０上で実行しているときの、そのプロセッサ０１０のレジスタの内容（そのレジスタに記録されている情報）のことを、本実施形態において「コンテキスト」と呼ぶ。本実施形態では、プロセス２００のコンテキストは、汎用レジスタとスタックポインタを含む。複数のプロセス２００でプロセッサ０１０を時分割共有するためには、あるプロセス２００がプロセッサ０１０上で実行を一時停止するときに、そのプロセス２００のコンテキストを保存し、そのプロセス２００が実行を再開するときにそのプロセス２００のコンテキストを復元する必要がある。プロセス２００のコンテキストの保存と復元には、そのプロセス２００のプロセス構造体とスタックを用いて行う。
【００５０】
図３は、プロセスのコンテキストの保存と復元の処理の流れを示す概念図である。以下、プロセッサ０（０１０ａ）上で実行中であったプロセス１（２００ａ）が、プロセッサ０（０１０ａ）上での実行を一時停止し、プロセッサ１上（０１０ｂ）で実行を再開する場合を例に取り上げ、プロセスのコンテキストの保存と復元を説明する。
【００５１】
Ｓ３０１：コンテキスト保存を開始する前の状態である。
【００５２】
Ｓ３０２：プロセス１（２００ａ）のコンテキストの保存では、まず、プロセッサ０（０１０ａ）が、プロセッサ０（０１０ａ）の汎用レジスタ０１２の内容を、プロセス１（２００ａ）のスタック２２０ａに保存する。
【００５３】
Ｓ３０３：次に、プロセッサ０（０１０ａ）は、プロセッサ０（０１０ａ）のスタックポインタ０１３ａの内容を、プロセス１（２００ａ）のプロセス構造体２１０ａに保存する。
【００５４】
Ｓ３０４：プロセス１（２００ａ）のコンテキストの復元では、まず、プロセッサ１（０１０ｂ）が、スタックポインタ０１３ａの内容を、プロセス１（２００ａ）のプロセス構造体２１０ａからプロセッサ１（０１０ｂ）のスタックポインタに復元する。
【００５５】
Ｓ３０５：次に、プロセッサ１（０１０ｂ）が、汎用レジスタの内容を、プロセス１（２００ｂ）のスタック２２０ｂからプロセッサ１（０１０ｂ）の汎用レジスタ０１２ｂに復元する。
【００５６】
前述の通り、プロセッサ上で実行するプロセスを切り替える処理を「ディスパッチ処理」と呼ぶ。ディスパッチ処理は、プロセスがディスパッチ処理を呼び出すことで、ディスパッチャ１３０によって実行される。ディスパッチャ１３０は、次に実行するプロセスを選択する必要があるが、これは、ディスパッチャ１３０が、スケジューラ１２０がプロセスの並び順を制御する共有実行キュー１２１から先頭のプロセスを取り出すことによって、行う。ディスパッチャ１３０は、この次に実行するプロセスの候補に現在実行中のプロセスも含めるために、まず現在実行中のプロセスを共有実行キュー１２１に挿入してから次に実行するプロセスを共有実行キュー１２１から取り出す。
【００５７】
ディスパッチャ１３０は、それ自身のスタックを持たない。しかし、プログラムを実行するためには、スタックが不可欠である。それゆえ、ディスパッチャ１３０は、自身を呼び出した現在実行中のプロセスと、次に実行するプロセスとスタックを、共有して実行する。そして、ディスパッチャ１３０が実行しているときは、スタックを途切れさせないようにするために、現在実行中のプロセスのコンテキスト退避と、次に実行するプロセスのコンテキスト復元を、コンテキスト切り替えと呼ぶ一連の処理として実行する。
【００５８】
コンテキスト切り替えを実行するためには、次に実行するプロセスを決める必要がある。そこで、現在実行中のプロセス２００の実行キュー１２１への挿入と、次に実行するプロセス２００の共有実行キュー１２１からの取り出しを、現在実行中のプロセス２００から次に実行するプロセス２００へのコンテキスト切り替えの前に行うと、前述のようにデッドロックが発生する可能性がある。
【００５９】
以下、その考察（実施形態の比較例）を、図４〜図９を参照して説明する。
【００６０】
図４は、比較例に係るディスパッチ処理の実行フローを表す。図５〜図８は、比較例に係るディスパッチ処理の流れを示す。
【００６１】
図５のＳ５０１：プロセッサ０１０ａ上で現在実行中のプロセス２００ａがディスパッチ関数を呼び出す前の状態を表す。
【００６２】
図５のＳ５０２：プロセス２００ａがディスパッチ関数３０１を呼び出すと（図４の３００）、ディスパッチ関数３０１の呼び出し元アドレスが、そのプロセス２００ａのスタックに保存される。ディスパッチ関数３０１は、呼び出されると、まず現在のプロセス２００ａを実行キュー１２１に挿入する（図４の３０２）。この挿入位置は、スケジューラ１２０によって決定される。ディスパッチ関数３０１は、続けて、次に実行するプロセスを実行キュー１２１から取り出す。そして、ディスパッチ関数３０１は、コンテキスト切り替え関数３０５を呼び出す（図４の３０４）。
【００６３】
図６のＳ５０３：コンテキスト切り替え関数３０５が呼び出されると、コンテキスト切り替え関数３０５の呼び出し元アドレスが、現在のプロセス２００ａのスタック２２０ａに保存される。
【００６４】
図６のＳ５０４：コンテキスト切り替え関数３０５は、上述の通りコンテキスト保存を行う。
【００６５】
続けて、次に実行するプロセスのコンテキスト復元が行われる。
【００６６】
図７のＳ５０５：すなわち、プロセス２００ａが、次に実行するプロセスとなり、コンテキスト切り替え関数３０５が、そのプロセス２００ａのコンテキスト復元を開始する。コンテキスト復元（図４の３０７）では、コンテキスト切り替え関数３０５が、プロセス２００ａのプロセス構造体２１０ａに保存したスタックポインタの内容２１３ａをプロセッサ０１０ａのスタックポインタ０１３ａに復元することで、プロセッサ０１０ａの使用するスタックを次のプロセス２００ａのスタック２２０ａに切り替える。
【００６７】
図７のＳ５０６：続けて、上述の通り、コンテキスト切り替え関数３０５が、プロセス２００ａのコンテキストをプロセッサ０１０ａに復元する。
【００６８】
図８のＳ５０７：プロセッサ０１０ａは、コンテキスト切り替え関数３０５を終了して（図４の３０８）、次のプロセス２００ａのスタック２２０ａに保存されたコンテキスト切り替え関数３０５の呼び出し元に戻る。
【００６９】
図８のＳ５０８：更に、プロセッサ０１０ａは、次のプロセス２００ａのスタック２２０ａに保存されたディスパッチ関数３０１の呼び出し元に戻り（図４の３０９）、次のプロセスの実行を再開する。
【００７０】
このような比較例によれば、ディスパッチ処理においてデッドロックが発生する可能性がある。
【００７１】
すなわち、図９の上側に示すように、プロセッサ０（０１０ａ）上で実行中のプロセス１（２００ａ）がディスパッチャ１３０を呼び出すと、ディスパッチャ１３０はプロセス１（２００ａ）を共有実行キュー１２１に挿入する。一方、プロセッサ１（０１０ｂ）上で実行中のプロセス２（２００ｂ）がディスパッチャ１３０を呼び出すと、ディスパッチャ１３０はプロセス２（２００ｂ）を共有実行キュー１３０に挿入する。
【００７２】
スケジューラ１２０が、共有実行キュー１２１にプロセス１（２００ａ）とプロセス２（２００ｂ）が挿入されると、プロセス２（２００ｂ）を先頭にプロセス１（２００ａ）をその次に並べたとする。
【００７３】
プロセッサ０（０１０ａ）上でディスパッチャ１３０が共有実行キュー１２１の先頭のプロセスを取り出すと、プロセス２（２００ｂ）が取り出される。次にプロセッサ１（０１０ａ）上でディスパッチャ１３０が共有実行キュー１２１の先頭のプロセスを取り出すと、プロセス１（２００ａ）が取り出される。プロセッサ０（０１０ａ）上では、プロセス１（２００ａ）からプロセス２（２００ｂ）にコンテキストを切り替えるために、プロセス２（２００ｂ）のコンテキスト保存の完了を待つ。プロセッサ１（０１０ｂ）上では、プロセス２（２００ｂ）からプロセス１（２００ａ）にコンテキストを切り替えるためにプロセス１（２００ａ）のコンテキスト保存の完了を待つ。
【００７４】
プロセス１（２００ａ）のコンテキスト保存は、プロセス１（２００ａ）からプロセス２（２００ｂ）へのコンテキスト切り替えの中で行い、プロセス２（２００ｂ）のコンテキスト保存は、プロセス２（２００ｂ）からプロセス１（２００ａ）へのコンテキスト切り替えの中で行う。そのため、プロセッサ０（０１０ａ）はプロセス２（２００ｂ）のコンテキスト保存の完了を待って、プロセス１（２００ａ）のコンテキスト保存を開始できず、プロセッサ１（０１０ｂ）はプロセス１（２００ａ）のコンテキスト保存完了を待ってプロセス２（２００ｂ）のコンテキスト保存を開始できず、デッドロックが発生する。
【００７５】
デッドロックが発生する理由を更に詳細に説明する。比較例では、ディスパッチャ１３０は、プロセッサ０（０１０ａ）上で、それ自身を呼び出した現在のプロセス１（２００ａ）のコンテキストを保存する前に、プロセス１（２００ａ）を共有実行キュー１２１に挿入する。このため、プロセッサ１（０１０ｂ）上で実行中のディスパッチャ１３９は、プロセス１（２００ａ）のコンテキスト保存が完了する前に、プロセス１（２００ａ）を次に実行するプロセスに選択することができる。故に、ディスパッチャ１３０があるプロセスを次に実行するプロセスに選択したときに、選択したプロセスのコンテキスト保存が完了していない場合がある。この場合、ディスパッチャ１３０は、選択したプロセスのコンテキスト保存が完了するまで待たされる。更に、ディスパッチャ１３０は、現在のプロセスのコンテキスト保存と次のプロセスのコンテキスト復元を、コンテキスト切り替えと呼ぶまとまった一つの処理として実行する。そのため、次に実行するプロセスのコンテキスト保存が完了するまで、次に実行するプロセスのコンテキスト復元と現在実行中のプロセスのコンテキスト保存が待たされる。このプロセスのコンテキスト保存の待ちが複数プロセッサ間で循環すると、デッドロックが発生してしまう。
【００７６】
プロセスのコンテキストを複数プロセッサで共有する資源と考え、プロセスのコンテキスト復元をプロセッサによるプロセスのコンテキスト獲得とみなし、プロセスのコンテキスト保存をプロセッサによるプロセスのコンテキスト解放とみなすと、デッドロックを次のように説明することができる。すなわち、図９の下側に示すように、プロセッサ０（０１０ａ）がプロセス１（２００ａ）のコンテキストを保持したままプロセス２（２００ｂ）のコンテキストを獲得しようとし、プロセッサ１（０１０ｂ）がプロセス２（２００ｂ）のコンテキストを保持したままプロセス１（２００ａ）のコンテキストを獲得しようとして、デッドロックが発生する。
【００７７】
このようなデッドロックを回避するための方法として、ディスパッチ処理全体をロックで保護する方法が考えられるが、その方法では、プロセスのコンテキストの保存と復元の競合によるオーバヘッドが大きく、不十分である。
【００７８】
そこで、本実施形態では、共有実行キュー１２１を共有するプロセッサ０１０ごとにディスパッチャ用のスタック１３１が設けられ、各プロセッサ０１０は、自分に割り当てられたディスパッチャ用のスタック１３１を使用してプロセスのコンテキストの保存と復元を行うことで、プロセッサ間の競合によるオーバヘッドを発生させずにデッドロックを回避することができる。そして、ディスパッチャ１３０はディスパッチ処理のみを実行するので、ディスパッチャ用スタックに必要な容量は小さくて済む（例えば、ＯＳ１００やプロセス２００ａ〜２００ｆが使うメモリ容量に比べればメモリ０２０への影響はかなり小さいと考えられる）。
【００７９】
以下、詳述する。
【００８０】
プロセッサ０（０１０ａ）のディスパッチャ用スタック１３１ａとプロセッサ１（０１０ｂ）のディスパッチャ用スタック１３１ｂを用いると、現在のプロセスから次のプロセスへのコンテキスト切り替えを、現在のプロセスのコンテキスト保存と次のプロセスのコンテキスト復元の２つの処理に分けることができる。これは、現在のプロセスのコンテキストを保存してから、次のプロセスのコンテキストを復元するまでの間は、ディスパッチャ１３０が現在のプロセッサのディスパッチャ用スタックを用いて処理を実行できるからである。
【００８１】
また、ディスパッチャ１３０は、ディスパッチ処理を毎回完了するまで実行し、途中で中断して別のプロセスを実行することもないので、ディスパッチャ用スタックへのディスパッチャ１３０のコンテキストの保存も不要である。ディスパッチャ１３０は自身のスタックを毎回スタックの所定位置（典型的には先頭）から使い始める。
【００８２】
図１０は、実施形態に係るディスパッチ処理の実行フローを表す。図１１〜図１４は、実施形態に係るディスパッチ処理の流れを示す。
【００８３】
本実施形態では、ディスパッチャ１３０のディスパッチ処理が、ディスパッチ入口関数４０１、ディスパッチ関数４０５、及びディスパッチ出口関数４０９の３つの関数により実現される。
【００８４】
図１１のＳ１１０１：プロセッサ０１０ａ上で現在実行中のプロセス２００ａがディスパッチ入力関数４０１を呼び出す前の状態を表す。
【００８５】
図１１のＳ１１０２：プロセッサ０１０ａ上で現在実行中のプロセス２００ａが、ディスパッチ入口関数４０１を呼び出すと（図１０の４００）、ディスパッチ入口関数４０１の呼び出し元アドレスが現在のプロセス２００ａのスタック２２０ａに保存される。ディスパッチ入口関数４０１は、現在のプロセス２００ａのコンテキストを保存する（図１０の４０２）。
【００８６】
図１２のＳ１１０３：コンテキスト保存では、まず、ディスパッチ入口関数４０１が、現在のプロセッサ０１０ａの汎用レジスタ０１２ａの内容を、現在のプロセス２００ａのスタック２２０ａに保存する。そして、ディスパッチ入口関数４０１は、現在のプロセッサ０１０ａのスタックポインタ０１３ａの内容を、現在のプロセス２００ａのプロセス構造体２１０ａのＳＰ保存値２１３ａに保存する。
【００８７】
図１２のＳ１１０４：続けて、ディスパッチ入口関数４０１は、現在のプロセッサ０１０ａのディスパチャ用スタック１３１ａの先頭を、現在のプロセッサ０１０ａのスタックポインタ０１３ａに設定し、スタックを、現在のプロセッサ０１０ａのディスパッチャ用スタック１３１ａに切り替える。更に、ディスパッチ入口関数４０１は、汎用レジスタ０１２ａもディスパッチ関数４０５を呼び出すための適切な内容に変更して、ディスパッチ関数とディスパッチ出口関数のアドレスやこれらを呼び出す際の引数等のディスパッチャ用コンテキストをディスパッチャ用スタック１３１ａに保存する（図１０の４０３）。そして、ディスパッチ入口関数４０１は、ディスパッチャ用コンテキストを用いて、ディスパッチ関数４０５を呼び出す（図１０の４０４）。
【００８８】
図１３のＳ１１０５：ディスパッチ関数４０５の呼び出し元アドレスのディスパッチャ用スタックへの保存は、ディスパッチ関数４０５が自身の呼び出し元関数に戻ることがないので不要である。ディスパッチ関数４０５は、呼び出されると、現在のプロセス２００ａを共有実行キュー１２１に挿入する（図１０の４０６）。このプロセスの挿入位置はスケジューラ１２０によって決定される。ディスパッチ関数４０５は、次に実行するプロセスを共有実行キュー１２１の先頭から取り出す（図１０の４０７）。ディスパッチ関数４０５は、ディスパッチ出口関数４０９を呼び出して（図１０の４０８）、次に実行するプロセスのコンテキストを復元する。ディスパッチ出口関数４０９を呼び出しは、ディスパッチャ用スタック１３１ａに保存したディスパッチャ用コンテキストを用いて行われる。
【００８９】
以降は、上述の現在のプロセス２００ａが、共有実行キュー１２１の先頭から取り出されて次に実行するプロセスとなり、ディスパッチ出口関数４０９が呼び出される。
【００９０】
図１３のＳ１１０６：ディスパッチ出口関数４０９の、呼び出し元アドレスのディスパッチャ用スタックへの保存も、ディスパッチ出口関数が自身の呼び出し元に戻ることがないので不要である。
【００９１】
図１４のＳ１１０７：ディスパッチ出口関数４０９は、呼び出されると、次に実行するプロセス２００ａのコンテキストを復元する（図１０の４１０）。コンテキスト復元では、まず、ディスパッチ出口関数４０９は、プロセス構造体２１０ａに保存したスタックポインタの内容２１３ａを現在のプロセッサ０１０ａのスタックポインタ０１３ａに復元する。続けて、ディスパッチ出口関数４０９は、次のプロセス２００ａのスタック２２０ａに保存した汎用レジスタの内容を、現在のプロセッサ０１０ａの汎用レジスタ０１２ａに復元する。そして、ディスパッチ出口関数４０９は、次に実行するプロセスのスタックに保存されたディスパッチ入口関数の呼び出し元に戻る（図１０の４１１）。
【００９２】
図１４のＳ１１０８：次に実行するプロセスは、ディスパッチ入口関数の呼び出し元に戻ると、実行を再開する。
【００９３】
図１５を参照して、本実施形態ではデッドロックが発生しないことを説明する。
【００９４】
図１５の上側に示すように、プロセッサ０（０１０ａ）上でプロセス１（２００ａ）が実行中で、プロセッサ１（０１０ｂ）上でプロセス２（２００ｂ）が実行中であるとする。
【００９５】
プロセッサ０（０１０ａ）上で実行中のプロセス１（２００ａ）がディスパッチャ１３０を呼び出すと、ディスパッチャ１３０は、プロセス１（２００ａ）のコンテキストを保存してからプロセス１（２００ａ）を共有実行キュー１２１に挿入する。
【００９６】
プロセッサ１（０１０ａ）上でプロセス２（２００ｂ）がディスパッチャ１３０を呼び出すと、ディスパッチャ１３０は、プロセス２（２００ｂ）のコンテキストを保存してからプロセス２（２００ｂ）を共有実行キュー１２１に挿入する。
【００９７】
スケジューラ１２０が、プロセス２（２００ｂ）を共有実行キュー１２１の先頭に挿入し、プロセス１（２００ａ）をその次に挿入したとする。
【００９８】
プロセッサ０（０１０ａ）上でディスパッチャ１３０が、プロセス２（２００ｂ）を共有実行キュー１２１の先頭から取り出すと、直ちにプロセス２（２００ｂ）のコンテキストを復元してプロセス２（２００ｂ）の実行を再開する。
【００９９】
次に、プロセッサ１（０１０ａ）上でディスパッチャ１３０が、プロセス１（０１０ａ）を共有実行キュー１２１の先頭から取り出すと、直ちにプロセス１（０１０ａ）のコンテキストを復元してプロセス１（０１０ａ）の実行を再開する。
【０１００】
以上の通り、本実施形態によればデッドロックが発生しない。
【０１０１】
デッドロックが発生しない理由を更に詳細に説明する。
【０１０２】
プロセッサ０（０１０ａ）上で、ディスパッチャ１３０は、自身を呼び出したプロセス１（０１０ａ）のコンテキストを保存してから、プロセス１（２００ａ）を共有実行キュー１２１に挿入する。したがって、プロセッサ１（０１０ｂ）上で実行中のディスパッチャ１３０が、プロセス１（０１０ａ）を共有実行キュー１２１から取り出して次に実行するプロセスに選択したときは、プロセス１（２００ａ）のコンテキスト保存が完了していることが、保証される。
【０１０３】
それゆえ、ディスパッチャ１３０が、プロセス１（２００ａ）のコンテキスト復元を開始するときに、そのプロセス１（２００ａ）のコンテキスト保存の完了を待つことはない。ディスパッチ処理の中のプロセスのコンテキスト保存と復元において、プロセス１（２００ａ）のコンテキスト保存の完了を待つことがないので、複数プロセッサによる待ち状態の循環が発生することもない。よってデッドロックが発生しない。
【０１０４】
前述と同様に、プロセスのコンテキストとディスパッチャのコンテキストを、複数プロセッサで共有する資源と考え、コンテキスト復元をプロセッサによるコンテキストの獲得とみなし、プロセスまたはディスパッチャのプロセッサ上での実行をプロセッサによるコンテキストの保持とみなし、コンテキスト保存をプロセッサによるコンテキスト解放とみなすと、デッドロックが発生しない理由を次のように説明することができる。
【０１０５】
すなわち、図９の下側に示すように、本実施形態では、プロセッサ０（０１０ａ）は、自身のディスパッチャ用コンテキストを保持した状態で、解放されているプロセス２（２００ｂ）のコンテキストを獲得しようとし、プロセッサ１（０１０ｂ）は、自身のディスパッチャ用コンテキストを保持した状態で、解放されているプロセス１（２００ａ）のコンテキストを獲得しようとする。このように、待ちの循環がないので、デッドロックは発生しない。
【０１０６】
本実施形態によれば、プロセッサごとのディスパッチャ用スタックが設定され、ディスパッチャ用スタックを用いることによって、現在実行中のプロセスから次に実行するプロセスへのコンテキスト切り替えを、現在実行中のプロセスのコンテキスト保存処理と、次に実行するプロセスのコンテキスト復元処理に分けることができる。そして、現在実行中のプロセスのコンテキストを保存し、そのプロセスを共有実行キューに挿入し、次に実行するプロセスを共有実行キューから取り出し、そのプロセスのコンテキストを復元する手順でディスパッチ処理を行うことができる。本実施形態では、プロセスのコンテキスト保存と復元の複数プロセッサ間の競合によるオーバヘッドを引き起こさずにデッドロックを回避することができる。
【０１０７】
以上、一実施形態を説明したが、本発明は、その実施形態に限定されない。例えば、上記実施形態を、ハイパバイザのような仮想化機構が実行される計算機に適用することができる。この場合、上記ＯＳ１００の機能がハイパバイザのような仮想化機構に適用され、プロセスが、仮想計算機が有する仮想プロセッサ（１以上のプロセッサ０１０に基づく仮想的なプロセッサ）に適用されてよい。
【符号の説明】
【０１０８】
０１０：プロセッサ、  ０１１：プログラムカウンタ、  ０１２：汎用レジスタ、  ０１３：スタックポインタ、  ０２０：メモリ、  １００：オペレーティングシステム、  １２０：スケジューラ、  １２１：（共有）実行キュー、  １３０：ディスパッチャ、  １３１：ディスパッチャ用スタック、  ２００：プロセス
【図１】
2014191468.tif 000003
【図２】
2014191468.tif 000004
【図３】
2014191468.tif 000005
【図４】
2014191468.tif 000006
【図５】
2014191468.tif 000007
【図６】
2014191468.tif 000008
【図７】
2014191468.tif 000009
【図８】
2014191468.tif 000010
【図９】
2014191468.tif 000011
【図１０】
2014191468.tif 000012
【図１１】
2014191468.tif 000013
【図１２】
2014191468.tif 000014
【図１３】
2014191468.tif 000015
【図１４】
2014191468.tif 000016
【図１５】
2014191468.tif 000017