(57)【要約】【課題】データの受信が完了したかの確認処理負荷を軽減する。【解決手段】制御部１ｂは、スレッド１１の実行により、情報処理装置２からのデータの受信要求を通信インタフェース１ａに発行した後、受信要求に対応する受信データを受信したことを示す完了通知がキュー１ｃに格納されたかを確認し、完了通知が格納されていない場合には、スレッド１１をサスペンド状態に遷移させる。また、制御部１ｂは、スレッド１１〜１３のうち起床状態のスレッド１２，１３の中から次に実行させるスレッドを選択する選択処理と、キュー１ｃを確認する確認処理とを交互に実行する処理を実行し、確認処理によってキュー１ｃに完了通知が格納されたことを検知した場合、受信データをスレッド１１に受け渡してスレッド１１をサスペンド状態から復帰させる。【選択図】図１
2018181134.tif 000002
【特許請求の範囲】
【請求項１】
他の情報処理装置と通信するための通信インタフェースと、
複数のスレッドのうち一のスレッドの実行により、前記他の情報処理装置からのデータの受信要求を前記通信インタフェースに発行した後、前記受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、前記完了通知が格納されていない場合には、前記一のスレッドをサスペンド状態に遷移させる第１の処理と、
前記複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理と、前記キューを確認する確認処理とを交互に実行する第２の処理であって、前記確認処理によって前記キューに前記完了通知が格納されたことを検知した場合、前記受信データを前記一のスレッドに受け渡して前記一のスレッドをサスペンド状態から復帰させる、前記第２の処理と、
を実行する制御部と、
を有する情報処理装置。
【請求項２】
前記複数のスレッドをそれぞれ識別する第１の識別子を記憶する記憶部をさらに有し、
前記他の情報処理装置から送信されるデータには、前記複数のスレッドのうち宛先のスレッドを示す第２の識別子が付加されており、
前記第１の処理では、前記キューを確認したとき、前記複数のスレッドのうち他のスレッドの実行によって受信が要求された他の受信データの受信が完了したことを示す他の完了通知が格納されていることを検知した場合、前記他の受信データに付加された前記第２の識別子を取得し、前記記憶部を参照して、取得した前記第２の識別子に対応する前記他のスレッドを特定し、前記他のスレッドに対して前記他の受信データを受け渡して前記他のスレッドをサスペンド状態から復帰させ、その後に前記一のスレッドをサスペンド状態に遷移させる、
請求項１記載の情報処理装置。
【請求項３】
前記確認処理では、前記キューに前記完了通知が格納されたことを検知したとき、前記受信データに付加された前記第２の識別子を取得し、取得した前記第２の識別子と、前記記憶部に記憶された前記第１の識別子との比較結果に基づいて、前記受信データの受け渡し先を前記一のスレッドと判定する、
請求項２記載の情報処理装置。
【請求項４】
前記確認処理では、前記キューを確認したとき、前記他の完了通知が格納されていることを検知した場合、前記他の受信データに付加された前記第２の識別子を取得し、前記記憶部を参照して、取得した前記第２の識別子に対応する前記他のスレッドを特定し、前記他のスレッドに対して前記他の受信データを受け渡して前記他のスレッドをサスペンド状態から復帰させる、
請求項２または３記載の情報処理装置。
【請求項５】
記憶部をさらに有し、
前記第１の処理では、前記一のスレッドによって参照される記憶領域を示す領域情報を前記記憶部に登録した後、前記一のスレッドをサスペンド状態に遷移させ、
前記第２の処理では、前記領域情報に基づいて前記記憶領域を特定し、前記受信データを前記記憶領域に格納することによって前記受信データを前記一のスレッドに受け渡す、
請求項１記載の情報処理装置。
【請求項６】
コンピュータが、
複数のスレッドのうち一のスレッドの実行により、他のコンピュータからのデータの受信要求を前記コンピュータが備える通信インタフェースに発行した後、前記受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、前記完了通知が格納されていない場合には、前記一のスレッドをサスペンド状態に遷移させる第１の処理と、
前記複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理と、前記キューを確認する確認処理とを交互に実行する第２の処理であって、前記確認処理によって前記キューに前記完了通知が格納されたことを検知した場合、前記受信データを前記一のスレッドに受け渡して前記一のスレッドをサスペンド状態から復帰させる、前記第２の処理と、
を実行する情報処理方法。
【請求項７】
コンピュータに、
複数のスレッドのうち一のスレッドの実行により、他のコンピュータからのデータの受信要求を前記コンピュータが備える通信インタフェースに発行した後、前記受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、前記完了通知が格納されていない場合には、前記一のスレッドをサスペンド状態に遷移させる第１の処理と、
前記複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理と、前記キューを確認する確認処理とを交互に実行する第２の処理であって、前記確認処理によって前記キューに前記完了通知が格納されたことを検知した場合、前記受信データを前記一のスレッドに受け渡して前記一のスレッドをサスペンド状態から復帰させる、前記第２の処理と、
を実行させる情報処理プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、情報処理装置、情報処理方法および情報処理プログラムに関する。
【背景技術】
【０００２】
装置間で通信するためのバスの規格として、ＩｎｆｉｎｉＢａｎｄ（登録商標）が知られている。ＩｎｆｉｎｉＢａｎｄを用いた通信では、送信側装置と受信側装置のそれぞれにおいて、要求された通信処理が完了したことを示す完了通知が格納されるキューが用いられる。このキューは、ＣＱ（Completion Queue）と呼ばれる。例えば、受信側装置で実行されるスレッドは、データの受信が完了したかを確認するために、ＣＱのポーリングを行う。受信側装置がデータを受信すると、完了通知がＣＱに格納される。スレッドは、ポーリングによってＣＱから完了通知を取得できたとき、データの受信が完了したことを認識する。
【０００３】
また、ＩｎｆｉｎｉＢａｎｄに関する技術の例として、受信メッセージにＱＰ（Queue Pair）番号が付加されているかを判定し、付加されている場合だけＱＰ番号のチェックを行うことで、チェック効率を高めた情報処理装置が提案されている。
【０００４】
また、ネットワークインタフェースに関する技術の例として、それぞれＲＤＭＡ（Remote Direct Memory Access）に対応する主要なＮＩＣ（Network Interface Controller）と代替のＮＩＣとが共有する待ち行列ペアを作成し、スイッチオーバイベントの検出に応答して、待ち行列ペアの扱いを主要なＮＩＣから代替のＮＩＣに切り替える方法が提案されている。
【先行技術文献】
【特許文献】
【０００５】
【特許文献１】特開２０１５−２１６４５０号公報
【特許文献２】特表２００５−５３８５８８号公報
【発明の概要】
【発明が解決しようとする課題】
【０００６】
ところで、ＩｎｆｉｎｉＢａｎｄの受信側装置では、装置の処理負荷や伝送路の負荷によって、スレッドがＣＱのポーリングを開始してからＣＱに完了通知が格納されるまでの遅延時間が長くなる場合がある。その場合、スレッドは、ＣＱのポーリングを一定回数行った後にサスペンドし、その後にスレッドスケジューラによって起床され、ＣＱのポーリングを再度行う。遅延時間が長くなるほど、ポーリングを行うためのスレッドの起床とサスペンドとが繰り返し実行されるようになる。スレッドの起床やサスペンドの際には、処理負荷の高いコンテキストスイッチが発生するので、遅延時間が長くなるほど、受信が完了したかを確認するための処理負荷が増大してしまう。
【０００７】
１つの側面では、本発明は、データの受信が完了したかの確認処理負荷を軽減することが可能な情報処理装置、情報処理方法および情報処理プログラムを提供することを目的とする。
【課題を解決するための手段】
【０００８】
１つの案では、情報処理装置が提供される。この情報処理装置は、他の情報処理装置と通信するための通信インタフェースと、次のような処理を実行する制御部とを有する。制御部は、複数のスレッドのうち一のスレッドの実行により、他の情報処理装置からのデータの受信要求を通信インタフェースに発行した後、受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、完了通知が格納されていない場合には、一のスレッドをサスペンド状態に遷移させる第１の処理を実行する。また、制御部は、複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理と、キューを確認する確認処理とを交互に実行する第２の処理を実行する。ここで、制御部は、確認処理によってキューに完了通知が格納されたことを検知した場合、受信データを一のスレッドに受け渡して一のスレッドをサスペンド状態から復帰させる。
【０００９】
また、１つの案では、上記の情報処理装置と同様の処理をコンピュータが実行する情報処理方法が提供される。
さらに、１つの案では、上記の情報処理装置と同様の処理をコンピュータに実行させる情報処理プログラムが提供される。
【発明の効果】
【００１０】
１つの側面では、データの受信が完了したかの確認処理負荷を軽減できる。
【図面の簡単な説明】
【００１１】
【図１】第１の実施の形態に係る情報処理システムの構成例および処理例を示す図である。
【図２】第２の実施の形態に係るストレージシステムの構成例を示す図である。
【図３】ノードのハードウェア構成例を示す図である。
【図４】送信側ノードと受信側ノードとの間の基本的な通信処理手順について説明するための図である。
【図５】複数スレッド同士での通信処理の比較例を示す図である。
【図６】本実施の形態におけるＱＰ／ＣＱの配置を示す図である。
【図７】複数スレッド同士の通信について説明するための図である。
【図８】ノードが備える処理機能の構成例を示すブロック図である。
【図９】スレッドスケジューリングの第１の比較例を示す図である。
【図１０】スレッドスケジューリングの第２の比較例を示す図である。
【図１１】本実施の形態でのスレッドスケジューリングの例を示す図である。
【図１２】スレッドスケジューリングで使用されるデータ構造の例を示す図である。
【図１３】キュー間のエントリ移動によるサスペンドおよび起床動作について説明するための図である。
【図１４】スレッドの状態遷移についての第１の例を示す図である。
【図１５】スレッドの状態遷移についての第２の例を示す図である。
【図１６】スレッド間のコネクション確立を要求する処理手順の例を示すフローチャートである。
【図１７】メッセージの送信を要求する処理手順の例を示すフローチャートである。
【図１８】メッセージの受信を要求する処理手順の例を示すフローチャート（その１）である。
【図１９】メッセージの受信を要求する処理手順の例を示すフローチャート（その２）である。
【図２０】メッセージの受信を要求する処理手順の例を示すフローチャート（その３）である。
【図２１】スレッドスケジューラの処理手順の例を示すフローチャート（その１）である。
【図２２】スレッドスケジューラの処理手順の例を示すフローチャート（その２）である。
【図２３】スレッドの処理例を示す図である。
【発明を実施するための形態】
【００１２】
以下、本発明の実施の形態について図面を参照して説明する。
〔第１の実施の形態〕
図１は、第１の実施の形態に係る情報処理システムの構成例および処理例を示す図である。図１に示す情報処理システムは、情報処理装置１，２を有する。情報処理装置１と情報処理装置２とは、例えばＩｎｆｉｎｉＢａｎｄによって接続され、互いに通信することが可能になっている。
【００１３】
情報処理装置１は、通信インタフェース１ａと制御部１ｂを有する。通信インタフェース１ａは、情報処理装置２との間で通信を行う。制御部１ｂは、例えば、情報処理装置１が備えるプロセッサとして実現される。
【００１４】
制御部１ｂは、スレッド１１〜１３を実行する。スレッド１１〜１３のそれぞれの処理は、情報処理装置２からのデータ受信処理を含む。ここで、情報処理装置１でのデータ受信処理は、基本的に次のような手順で行われる。
【００１５】
制御部１ｂは、通信インタフェース１ａに対してデータの受信要求を発行し、受信待ち状態になる。通信インタフェース１ａが情報処理装置２からのデータを受信すると、発行された受信要求に対応する受信処理が完了したことを示す完了通知が、キュー１ｃに登録される。キュー１ｃは、ＦＩＦＯ（First In First Out）方式で完了通知を保持する。なお、受信されたデータは、例えば、バッファ１ｄに一時的に格納される。
【００１６】
制御部１ｂは、受信要求の発行後、受信要求に対応する完了通知がキュー１ｃに格納されたかを確認する。そして、制御部１ｂは、完了通知がキュー１ｃに格納されたことを検知した場合、すなわち、完了通知をキュー１ｃから取得できた場合に、受信処理が完了したことを認識し、バッファ１ｄに格納された受信データを取得する。
【００１７】
このような処理手順によれば、受信要求の発行から完了通知がキュー１ｃに格納されるまでの遅延時間が長い場合、制御部１ｂは、完了通知を取得できるまで何回もキュー１ｃを確認する。ここで、例えば、制御部１ｂが、スレッド１１の実行によって受信要求を発行した場合に、スレッド１１の処理によって、対応する完了通知がキュー１ｃから取得できるまでキュー１ｃの確認を繰り返すケースを仮定する。１つのスレッド１１が制御部１ｂを長時間独占することはできないため、上記のケースでは、スレッド１１の実行により何回かキュー１ｃを確認しても完了通知を取得できない場合、制御部１ｂは、スレッド１１をサスペンドさせて、他のスレッドの実行を開始する。その後、制御部１ｂは、スレッド１１をサスペンド状態から復帰させて実行することで、キュー１ｃの確認を再度実行する。しかし、完了通知を取得できない場合、制御部１ｂは、スレッド１１を再度サスペンドさせて他のスレッドの実行を開始する。
【００１８】
このように、上記ケースでスレッド１１の処理だけによってキュー１ｃの確認を行うものとすると、スレッド１１による受信要求の発行から完了通知がキュー１ｃに格納されるまでの遅延時間が長い場合、スレッド１１がサスペンドと復帰とを何度も繰り返す。スレッド１１のサスペンドや復帰の際には、処理負荷の高いコンテキストスイッチが発生する。このため、上記の遅延時間が長くなるほど、受信が完了したかを確認するための制御部１ｂの処理負荷が増大してしまう。
【００１９】
このような問題に対して、本実施の形態では、制御部１ｂは、スレッドをサスペンドさせたままキュー１ｃの確認を実行できるようにすることで、スレッドのサスペンドや復帰の回数を低減し、処理負荷を抑制する。以下、制御部１ｂの具体的な処理について説明する。
【００２０】
制御部１ｂは、次のような第１の処理を実行する（ステップＳ１）。ここでは例として、スレッド１１の実行によって受信要求が発行されるものとする。制御部１ｂは、スレッド１１の実行により、受信要求を通信インタフェース１ａに発行する。その後、制御部１ｂは、発行した受信要求に応じた受信処理の完了を示す完了通知がキュー１ｃに格納されたかを確認する。この確認処理は、例えば、一定回数を上限として実行される。ここで、該当する完了通知がキュー１ｃに格納されたことを検知できなかった場合、制御部１ｂは、スレッド１１をサスペンド状態に遷移させる。
【００２１】
また、制御部１ｂは、スレッド１１〜１３のうちサスペンド状態でないスレッド１２，１３の中から、次に実行させるスレッドを選択する選択処理（ステップＳ２ａ）と、キュー１ｃの確認処理（ステップＳ２ｂ）とを交互に実行する第２の処理を実行する（ステップＳ２）。この第２の処理では、実行させるスレッドの選択処理が繰り返し実行されることで、制御部１ｂはスレッドスケジューラとして動作する。
【００２２】
ここで、選択処理と確認処理とが繰り返し実行されるうちに、あるタイミングで、ステップＳ１で発行された受信要求に対応するデータ１０が、通信インタフェース１ａによって受信され、バッファ１ｄに格納されたとする。この場合、制御部１ｂは、データ１０の受信後に実行したキュー１ｃの確認処理（ステップＳ２ｂ）により、ステップＳ１で発行された受信要求に応じた受信処理の完了を示す完了通知が、キュー１ｃに格納されたことを検知する。すると、制御部１ｂは、受信されたデータ１０をスレッド１１に受け渡す。そして、制御部１ｂは、スレッド１１をサスペンド状態から復帰させて、選択処理の対象にスレッド１１を復帰させる。
【００２３】
以上の処理によれば、制御部１ｂは、スレッド１１の実行によるステップＳ１での確認処理によって完了通知がキュー１ｃに格納されたことを検知できなかった場合、スレッド１１をサスペンド状態にさせる。それ以後、制御部１ｂは、スレッド１１をサスペンドさせた状態のまま、キュー１ｃの確認を周期的に実行する。そして、制御部１ｂは、完了通知がキュー１ｃに格納されたことを検知すると、受信されたデータ１０をスレッド１１に受け渡して、スレッド１１を復帰させる。
【００２４】
これにより、スレッド１１は、一度サスペンドした後は、キュー１ｃの確認のために復帰することはなく、第２の処理（ステップＳ２）の実行によって該当する完了通知がキュー１ｃから検知されると復帰する。したがって、スレッド１１がサスペンドと復帰とを繰り返すことがなくなり、データの受信が完了したかを確認するための制御部１ｂの処理負荷を軽減できる。その結果、情報処理装置１によるデータ受信処理全体の負荷を軽減し、データ受信処理を効率化することができる。
【００２５】
〔第２の実施の形態〕
図２は、第２の実施の形態に係るストレージシステムの構成例を示す図である。図２に示すストレージシステムは、ノード１００−１〜１００−４を有する。ノード１００−１，１００−２，１００−３，１００−４には、それぞれストレージ２００−１，２００−２，２００−３，２００−４が接続されている。そして、ノード１００−１，１００−２，１００−３，１００−４は、それぞれストレージ２００−１，２００−２，２００−３，２００−４に対するアクセスを制御するストレージ制御装置として動作する。
【００２６】
なお、ストレージ２００−１〜２００−４のそれぞれには、１台または複数台の不揮発性記憶装置が搭載されている。不揮発性記憶装置は、例えば、ＳＳＤ（Solid State Drive）やＨＤＤ（Hard Disk Drive）である。また、ノード１００−１とストレージ２００−１、ノード１００−２とストレージ２００−２、ノード１００−３とストレージ２００−３、ノード１００−４とストレージ２００−４は、それぞれストレージノードを形成する。なお、ストレージシステムに含まれるストレージノードの数は、図２のように４ノードに限定されるものではなく、２以上の任意の数とすることができる。
【００２７】
ノード１００−１〜１００−４は、スイッチ３００を介して互いに接続されている。本実施の形態では、ノード１００−１〜１００−４は、ＩｎｆｉｎｉＢａｎｄで互いに接続されている。また、ノード１００−１〜１００−４は、ネットワーク４００を介してホスト装置４１０，４２０と接続されている。ノード１００−１〜１００−４とホスト装置４１０，４２０との間は、例えば、ＳＡＳ（Serial Attached SCSI，SCSI：Small Computer System Interface）やＦＣ（Fibre Channel）を用いたＳＡＮ（Storage Area Network）によって接続されている。
【００２８】
このストレージシステムは、例えば、ホスト装置４１０，４２０から書き込みが要求されたデータが分散して格納される分散ストレージシステムとして動作する。例えば、次のようなストレージアクセス制御が実行される。
【００２９】
ストレージシステムは、ホスト装置４１０，４２０に対して複数の論理ボリュームを提供する。ホスト装置４１０，４２０は、ある論理ボリュームにアクセスする際、ノード１００−１〜１００−４のいずれかに対してＩＯ（Input／Output）要求を送信する。また、論理ボリュームにおける書き込みアドレスの範囲ごとに、データの格納を行う担当ノードがあらかじめ決められている。
【００３０】
例えば、あるノードがＩＯ要求として書き込み要求を受信したとする。書き込み要求を受信したノードは、書き込みアドレスを解析して、ノード１００−１〜１００−４の中から担当ノードを判別し、担当ノードに対して書き込みデータを転送する。担当ノードは、転送された書き込みデータを一旦キャッシュに格納した後、非同期のタイミングで、担当ノードに接続されているストレージに書き込みデータを格納する。
【００３１】
また、例えば、担当ノードは、書き込みデータのハッシュ値に基づいて決められていてもよい。この場合、担当ノードは、書き込みデータのハッシュ値に基づいて、同一内容のデータが重複してストレージに格納されないように制御する「重複除去」を行うこともできる。
【００３２】
なお、ストレージシステムに接続可能なホスト装置の台数は、図２のように２台に限定されるものではない。
図３は、ノードのハードウェア構成例を示す図である。図３に示すノード１００は、図２に示したノード１００−１〜１００−４のいずれかを示す。以下の説明では、ノード１００−１〜１００−４のそれぞれを特に区別せずに示す場合には、「ノード１００」と記載する場合がある。
【００３３】
ノード１００は、例えば、図３に示すようなコンピュータとして実現される。ノード１００は、ＣＰＵ（Central Processing Unit）１０１ａ〜１０１ｃ、メモリ１０２、ＳＳＤ１０３、読み取り装置１０４、ホストインタフェース１０５、ドライブインタフェース１０６およびＨＣＡ（Host Channel Adapter）１０７を有する。
【００３４】
ＣＰＵ１０１ａ〜１０１ｃは、ノード１００全体を統括的に制御する。なお、ＣＰＵの個数は３つに限定されるものではない。メモリ１０２は、ＤＲＡＭ（Dynamic Random Access Memory）などの揮発性記憶装置であり、ノード１００の主記憶装置として使用される。メモリ１０２には、ＣＰＵ１０１ａ〜１０１ｃに実行させるＯＳ（Operating System）プログラムやアプリケーションプログラムの少なくとも一部が一時的に格納される。また、メモリ１０２には、ＣＰＵ１０１ａ〜１０１ｃによる処理に必要な各種データが格納される。
【００３５】
ＳＳＤ１０３は、ノード１００の補助記憶装置として使用される。ＳＳＤ１０３には、ＯＳプログラム、アプリケーションプログラム、および各種データが格納される。なお、補助記憶装置としては、ＨＤＤなどの他の種類の不揮発性記憶装置が用いられてもよい。読み取り装置１０４には、可搬型記録媒体１０４ａが脱着される。読み取り装置１０４は、可搬型記録媒体１０４ａに記録されたデータを読み取ってＣＰＵ１０１ａ〜１０１ｃに送信する。可搬型記録媒体１０４ａとしては、光ディスク、光磁気ディスク、半導体メモリなどがある。
【００３６】
ホストインタフェース１０５は、ネットワーク４００を介してホスト装置４１０，４２０との間で通信するためのインタフェース装置である。ドライブインタフェース１０６は、ストレージ２００との間で通信するためのインタフェース装置である。ＨＣＡ１０７は、スイッチ３００を介して他のノード１００と通信するための、ＩｎｆｉｎｉＢａｎｄに準拠したインタフェース装置である。
【００３７】
以上のハードウェア構成によってノード１００（ノード１００−１〜１００−４）の処理機能を実現することができる。なお、ホスト装置４１０，４２０も、ノード１００と同様にＣＰＵやメモリなどを有するコンピュータとして実現することができる。
【００３８】
＜スレッドに対するキューの割り当て＞
次に、ノードで実行されるスレッドに対する、ノード間の通信で用いられるキューの割り当てについて説明する。ここではまず、図４、図５を用いて、ＩｎｆｉｎｉＢａｎｄを用いたノード間通信の比較例について説明し、その後に本実施の形態におけるノード間通信について説明する。
【００３９】
図４は、送信側ノードと受信側ノードとの間の基本的な通信処理手順について説明するための図である。図４では、ＨＣＡ５１１を有するノード５１０と、ＨＣＡ５２１を有するノード５２０とを示し、ノード５１０からノード５２０に対してＩｎｆｉｎｉＢａｎｄを介してデータが送信される場合について説明する。
【００４０】
ＩｎｆｉｎｉＢａｎｄでは、送信用のＱＰ５１２と、受信用のＱＰ５２２とを用いて通信が行われる。送信用のＱＰ５１２は、送信要求を示すエントリを格納するＦＩＦＯであり、「ＳＱ（Send Queue）」とも呼ばれる。ＱＰ５１２に格納されるエントリには、例えば、送信メッセージが格納されている送信バッファのアドレスなどが含まれる。また、受信用のＱＰ５２２は、受信要求を示すエントリを格納するＦＩＦＯであり、「ＲＱ（Receive Queue）」とも呼ばれる。ＱＰ５２２に格納されるエントリには、例えば、受信メッセージが格納される受信バッファのアドレスなどが含まれる。
【００４１】
送信側のノード５１０において、アプリケーション５１３は、メッセージを送信する際、送信関数「ｓｅｎｄ」（例えば、ibv＿post＿send()）を発行する。すると、送信要求を示すエントリがＱＰ５１２に格納されるとともに、引数として指定されたアドレスが示す送信バッファに送信メッセージがセットされる。なお、ＱＰ５１２に格納されるエントリはＷＱＥ（Work Queue Element）と呼ばれる。ＨＣＡ５１１は、ＱＰ５１２から取得したエントリに基づいて送信メッセージを送信する。
【００４２】
また、ＩｎｆｉｎｉＢａｎｄでは、ＱＰに加えてＣＱが用いられる。ＣＱは、完了を示すエントリを格納するＦＩＦＯである。ＣＱに格納されるエントリは、ＣＱＥ（Completion Queue Entry）と呼ばれる。このエントリが示す「完了（Completion）」の内容としては、ＱＰのエントリに対応する処理が正常に終了したことを示す「Successful Completion」と、エラーで終了したことを示す「Completion Error」とがある。
【００４３】
ＨＣＡ５１１によるメッセージ送信処理が完了すると、完了を示すエントリがＣＱ５１４に格納される。アプリケーション５１３は、送信関数「ｓｅｎｄ」の発行後にＣＱ５１４のポーリングを行うことで、送信要求に応じた処理の完了を示すエントリをＣＱ５１４から取得する。
【００４４】
一方、受信側のノード５２０において、アプリケーション５２３は、メッセージを受信する際、受信関数「ｒｅｃｖ」（例えば、ibv＿post＿recv()）を発行する。すると、受信要求を示すエントリがＱＰ５２２に格納される。ＨＣＡ５２１は、ＱＰ５２２から取得したエントリに基づいてメッセージを受信し、エントリに含まれるアドレスが示す受信バッファに受信メッセージをセットする。また、ＨＣＡ５２１によるメッセージ受信処理が完了すると、完了を示すエントリがＣＱ５２４に格納される。アプリケーション５２３は、受信関数「ｒｅｃｖ」の発行後にＣＱ５２４のポーリングを行うことで、受信要求に応じた処理の完了を示すエントリをＣＱ５２４から取得する。アプリケーション５２３は、取得したエントリに含まれるアドレスが示す受信バッファから、受信メッセージを取得する。
【００４５】
このように、ＩｎｆｉｎｉＢａｎｄを通じて通信する場合、アプリケーションは、メッセージの送信または受信を要求した後、ＣＱをポーリングすることで、要求した処理が完了したことを検知する。
【００４６】
図５は、複数スレッド同士での通信処理の比較例を示す図である。なお、これ以後、「ＱＰ／ＣＱ」とは、送信用のＱＰと、これに対応するＣＱと、受信用のＱＰと、これに対応するＣＱとを含むものとする。ただし、ＣＱは、送信用のＱＰと受信用のＱＰとで共用することも可能である。
【００４７】
ここでは、あるノードで実行される特定のスレッドと、それとは異なるノードで実行される特定のスレッドとの間で通信が行われる場合を想定する。この場合には、一方のノードの１つのスレッドと他方のノードの１つのスレッドとの間で、論定的な通信路であるコネクションを確立し、コネクションごとに個別のＱＰ／ＣＱを割り当てる方法が最も単純な方法である。なぜなら、この方法によれば、各スレッドは、送信や受信を要求した後、割り当てられたＣＱをポーリングするだけで、自分宛てのエントリを容易に取得できるからである。
【００４８】
例えば図５では、ノード５１０でスレッド５１５ａ〜５１５ｄが実行され、ノード５２０でスレッド５２５ａ〜５２５ｄが実行されている。そして、スレッド５１５ａとスレッド５２５ａとの間、スレッド５１５ｂとスレッド５２５ｂとの間、スレッド５１５ｃとスレッド５２５ｃとの間、スレッド５１５ｄとスレッド５２５ｄとの間で、それぞれ通信が行われる。
【００４９】
この場合、スレッド５１５ａとスレッド５２５ａとの間のコネクション５３１ａにおいては、スレッド５１５ａに対してＱＰ／ＣＱ５１６ａが割り当てられ、スレッド５２５ａに対してＱＰ／ＣＱ５２６ａが割り当てられる。同様に、スレッド５１５ｂとスレッド５２５ｂとの間のコネクション５３１ｂにおいては、スレッド５１５ｂに対してＱＰ／ＣＱ５１６ｂが割り当てられ、スレッド５２５ｂに対してＱＰ／ＣＱ５２６ｂが割り当てられる。また、スレッド５１５ｃとスレッド５２５ｃとの間にコネクション５３１ｃにおいては、スレッド５１５ｃに対してＱＰ／ＣＱ５１６ｃが割り当てられ、スレッド５２５ｃに対してＱＰ／ＣＱ５２６ｃが割り当てられる。さらに、スレッド５１５ｄとスレッド５２５ｄとの間のコネクション５３１ｄにおいては、スレッド５１５ｄに対してＱＰ／ＣＱ５１６ｄが割り当てられ、スレッド５２５ｄに対してＱＰ／ＣＱ５２６ｄが割り当てられる。
【００５０】
このような構成とすることで、例えば、ＱＰ／ＣＱ５２６ａのＣＱには、スレッド５２５ａ宛てのエントリだけが格納される。そのため、スレッド５２５ａは、メッセージの受信を要求した後、ＱＰ／ＣＱ５２６ａのＣＱを監視するだけで、受信要求に対応する完了のエントリを容易に取得できる。
【００５１】
しかしながら、このような構成では、スレッド間で確立されたコネクションの数が多くなった場合に次のような問題がある。
スレッド間で確立されたコネクション５３１ａ〜５３１ｄは、共通の物理的な通信経路上に存在する。そのため、確立されたコネクションの数が多いほど、スレッドが送信または受信を要求してから、その要求に対応する完了のエントリをＣＱから取得できるまでの遅延時間が長くなる可能性がある。
【００５２】
また、コネクション５３１ａ〜５３１ｄの間で通信頻度に偏りがある場合、通信頻度が高いスレッドに対応するＣＱには、上記の遅延時間が長くなったとしても、ＣＱに対して時間当たりに格納されるエントリの数が多くなる。そのため、通信頻度が高いコネクション上のスレッドほど、ＣＱに対してポーリングしたときに完了のエントリを取得できる確率が高まる。しかし、その一方で、通信頻度が低いコネクション上のスレッドほど、ＣＱに対してポーリングしたときに完了のエントリを取得できる確率が低下する。このように通信頻度が低いコネクション上のスレッドは、無駄なポーリングを多く実行していることになり、ＣＰＵやメモリなどのリソースを浪費するという問題がある。
【００５３】
このような問題に対して、本実施の形態では、次の図６のようにＱＰ／ＣＱが配置される。
図６は、本実施の形態におけるＱＰ／ＣＱの配置を示す図である。本実施の形態では、１つのノードは、通信相手のノードごとにＱＰ／ＣＱをそれぞれ１つだけ有する。具体的には、図６に示すように、ノード１００−１は、ノード１００−２，１００−３，１００−４とそれぞれ通信するためのＱＰ／ＣＱ１１１ａ−１，１１１ｂ−１，１１１ｃ−１を有する。ノード１００−２は、ノード１００−１，１００−３，１００−４とそれぞれ通信するためのＱＰ／ＣＱ１１１ａ−２，１１１ｂ−２，１１１ｃ−２を有する。ノード１００−３は、ノード１００−１，１００−２，１００−４とそれぞれ通信するためのＱＰ／ＣＱ１１１ａ−３，１１１ｂ−３，１１１ｃ−３を有する。ノード１００−４は、ノード１００−１，１００−２，１００−３とそれぞれ通信するためのＱＰ／ＣＱ１１１ａ−４，１１１ｂ−４，１１１ｃ−４を有する。
【００５４】
このように、本実施の形態では、１つのノード内で他の１つのノードとの通信で用いられるＱＰ／ＣＱが１つだけに限定される。そして、次の図７に示すように、１つのノードでは、他の１つのノードと通信する複数のスレッドが、１つのＱＰ／ＣＱを共用する。
【００５５】
図７は、複数スレッド同士の通信について説明するための図である。図７では、例として、ノード１００−１とノード１００−２との間の通信について説明する。また、ノード１００−１でスレッド５１５ａ〜５１５ｄが実行され、ノード１００−２でスレッド５２５ａ〜５２５ｄが実行されるものとする。そして、スレッド５１５ａとスレッド５２５ａとの間、スレッド５１５ｂとスレッド５２５ｂとの間、スレッド５１５ｃとスレッド５２５ｃとの間、スレッド５１５ｄとスレッド５２５ｄとの間で、それぞれ通信が行われるものとする。
【００５６】
ノード１００−１は、ノード１００−２との通信のためのＱＰ／ＣＱ１１１ａ−１を有する。そして、ＱＰ／ＣＱ１１１ａ−１は、ノード１００−２との通信の際にスレッド５１５ａ〜５１５ｄによって共用される。一方、ノード１００−２は、ノード１００−１との通信のためのＱＰ／ＣＱ１１１ａ−２を有する。そして、ＱＰ／ＣＱ１１１ａ−２は、ノード１００−１との通信の際にスレッド５２５ａ〜５２５ｄによって共用される。
【００５７】
ただし、この構成では、例えばスレッド５２５ａ〜５２５ｄからそれぞれ受信要求が発行された場合、ＱＰ／ＣＱ１１１ａ−２のＣＱには、スレッド５２５ａ〜５２５ｄのそれぞれを宛先とする完了のエントリが混在する。このとき、スレッド５２５ａ〜５２５ｄは、ＱＰ／ＣＱ１１１ａ−２のＣＱに格納されたエントリがどのスレッド宛てのものかを判別できない。
【００５８】
そこで、本実施の形態では、スレッド間で確立されたコネクションごとに、システム全体でユニークな識別番号である「ＸＩＤ」が付与される。そして、あるスレッドから他のノードのスレッド宛てにメッセージが送信される際に、それらのスレッド間のコネクションに対応するＸＩＤが送信メッセージに付加される。これにより、受信側ノードのスレッドは、ＣＱから取得したエントリに基づいて受信メッセージを取得したとき、受信メッセージに含まれるＸＩＤから、エントリが自分宛てであるか否かを判別できるようになる。
【００５９】
ＸＩＤは、ＸＩＤの発行元ノードを示すノード番号と、発行のたびにシーケンシャルに変更される番号とを組み合わせて生成される。ＸＩＤが発行元ノード番号を含むことで、他のいずれのノードでも同じＸＩＤが生成されないようにすることができる。なお、後述するように、ＸＩＤは、スレッド間のコネクションが確立される際に生成される。「発行元ノード」とは、コネクションの確立を持ちかけたノードを指す。
【００６０】
さらに、本実施の形態では、あるスレッドがポーリングによりＣＱからエントリを取得したとき、そのエントリが他のスレッド宛てであった場合には、その旨を他のスレッドに認識させることが可能となっている。例えば、スレッド５２５ａがＱＰ／ＣＱ１１１ａ−２のＣＱをポーリングして、受信完了を示すエントリを取得したとき、そのエントリがスレッド５２５ｂ宛てであった場合には、スレッド５２５ａは、エントリに対応する受信メッセージをスレッド５２５ｂに受け渡す。スレッド５２５ｂは、その受信メッセージを用いて処理を継続することができる。
【００６１】
以上のように、本実施の形態では、１つのノード内で他の１つのノードとの通信で用いられるＣＱが１つだけに限定される。また、ノード上のスレッドは、ポーリングによりＣＱからエントリを取得したとき、そのエントリがどのスレッド宛てのものかをＸＩＤから判別し、宛先のスレッドに対してそのエントリに対応する通信処理の完了を認識させる。
【００６２】
これにより、スレッド間で通信頻度に偏りがある場合でも、各スレッドがＣＱのポーリングを行ったときに、どのスレッド宛てのエントリも取得できないという確率が低くなる。その結果、無駄なポーリングの回数を減少させることができ、ＣＰＵやメモリなどのリソースの利用効率が向上する。また、ノードにおけるリソースの利用効率が向上することで、ホスト装置からのＩＯ要求に対する応答速度を高めることもできる。
【００６３】
なお、ＱＰ／ＣＱは、例えば、ストレージシステムの運用を開始した初期段階において、各ノードのメモリ領域に作成される。例えば、各ノードは、他のノードのＨＣＡ１０７のアドレスを指定することでそのＨＣＡ１０７のデバイス情報を取得し、デバイス情報を基に他のノードに対応するＱＰ／ＣＱを作成する。接続されたノード間でＱＰ／ＣＱの作成完了が認識されることで、ノード間の通信が可能になる。
【００６４】
＜ノードの処理機能＞
図８は、ノードが備える処理機能の構成例を示すブロック図である。ノード１００は、記憶部１１０、アプリケーション１２０、スレッドスケジューラ１３１〜１３３およびＨＣＡドライバ１４０を有する。
【００６５】
記憶部１１０は、例えば、メモリ１０２の記憶領域として実装される。記憶部１１０には、ＱＰ／ＣＱ１１１ａ〜１１１ｃ、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２、コネクションプール１１３、スレッド−関数対応テーブル１１４およびＲｅａｄｙキュー１１５ａ〜１１５ｃが記憶される。
【００６６】
ＱＰ／ＣＱ１１１ａ〜１１１ｃは、他のノードとの通信で使用されるＱＰ／ＣＱである。前述のように、ＱＰ／ＣＱ１１１ａ〜１１１ｃは、それぞれ個別のノードに対応付けられている。
【００６７】
ＸＩＤ−Ｑｓｔｒ対応テーブル１１２は、ＸＩＤと待ち合わせ構造体（Ｑ−Ｓｔｒｕｃｔｕｒｅ）との対応関係を保持する。ＸＩＤ−Ｑｓｔｒ対応テーブル１１２には、ノード間のコネクションが確立されて新たなＸＩＤが発行されるたびに、ＸＩＤと待ち合わせ構造体を示す情報とを含むレコードが追加登録される。なお、待ち合わせ構造体とは、後述するように、サスペンド状態のスレッドを管理するためのデータ構造体であり、１つのＸＩＤに対して１つ生成される。
【００６８】
コネクションプール１１３は、未使用のコネクション構造体を保持する。コネクション構造体とは、後述するように、スレッド間のコネクションを介した通信のために使用されるデータ構造体であり、１つのＸＩＤに対して１つ使用される。
【００６９】
スレッド−関数対応テーブル１１４は、スレッドの処理内容の種別と、その種別のスレッドで実行される関数との対応関係を保持する。
Ｒｅａｄｙキュー１１５ａ〜１１５ｃは、実行されるスレッドに対応するエントリを格納するキューである。Ｒｅａｄｙキュー１１５ａ，１１５ｂ，１１５ｃは、それぞれスレッドスケジューラ１３１，１３２，１３３から参照される。
【００７０】
アプリケーション１２０の処理は、例えば、ＣＰＵ１０１ａ〜１０１ｃによって所定のアプリケーションプログラムが実行されることで実現される。アプリケーション１２０は、例えば、ストレージのアクセス制御処理を実行する。アプリケーション１２０の処理は、複数のスレッドを含む。
【００７１】
スレッドスケジューラ１３１〜１３３およびＨＣＡドライバ１４０の処理は、例えば、ＣＰＵ１０１ａ〜１０１ｃによってＯＳプログラムが実行されることで実現される。
スレッドスケジューラ１３１は、Ｒｅａｄｙキュー１１５ａに基づいて、アプリケーション１２０のスレッドのうち、ＣＰＵ１０１ａによって実行されるスレッド１２１ａ，１２１ｂ，・・・の実行順を制御する。スレッドスケジューラ１３２は、Ｒｅａｄｙキュー１１５ｂに基づいて、アプリケーション１２０のスレッドのうち、ＣＰＵ１０１ｂによって実行されるスレッド１２２ａ，１２２ｂ，・・・の実行順を制御する。スレッドスケジューラ１３３は、Ｒｅａｄｙキュー１１５ｃに基づいて、アプリケーション１２０のスレッドのうち、ＣＰＵ１０１ｃによって実行されるスレッド１２３ａ，１２３ｂ，・・・の実行順を制御する。
【００７２】
ＨＣＡドライバ１４０は、ＨＣＡ１０７の動作を制御する。また、ＨＣＡドライバ１４０は、アプリケーション１２０に対して、ＨＣＡ１０７を使用するためのＡＰＩ（Application Programming Interface）を提供する。
【００７３】
＜ＣＱのポーリングとスレッドスケジューリング＞
次に、ＣＱのポーリングとスレッドスケジューリングについて説明する。まず、図９、図１０を用いて、スレッドスケジューリングの比較例について説明した後、図１１を用いて、本実施の形態のスレッドスケジューリングについて説明する。
【００７４】
図９は、スレッドスケジューリングの第１の比較例を示す図である。図９では例として、スレッドスケジューラ１３１によるスレッドのスケジューリングについて示す。スレッドスケジューラ１３１は、Ｒｅａｄｙキュー１１５ａからエントリを順に取得し、取得したエントリに対応するスレッドの実行を開始させる。スレッドは、ある一定の長さを限度とする処理を実行すると、サスペンドして、制御をスレッドスケジューラ１３１に移す。
【００７５】
例えば、図９に示すように、スレッドスケジューラ１３１は、スレッド１２１ａの実行を開始させる。スレッド１２１ａは、処理Ａ１を実行した後、サスペンドして、制御をスレッドスケジューラ１３１に移す。次に、スレッドスケジューラ１３１は、スレッド１２１ｂの実行を開始させる。スレッド１２１ｂは、処理Ｂ１を実行した後、サスペンドして、制御をスレッドスケジューラ１３１に移す。次に、スレッドスケジューラ１３１は、スレッド１２１ｃの実行を開始させる。スレッド１２１ｃは、処理Ｃ１を実行した後、サスペンドして、制御をスレッドスケジューラ１３１に移す。次に、スレッドスケジューラ１３１は、スレッド１２１ａの実行を開始させる。スレッド１２１ａは、処理Ａ１の次の処理Ａ２を実行する。
【００７６】
図１０は、スレッドスケジューリングの第２の比較例を示す図である。この図１０では、スレッド１２１ａ，１２１ｂが実行され、スレッド１２１ａによってメッセージの受信処理が行われる場合の例を示す。
【００７７】
まず、スレッドスケジューラ１３１は、スレッド１２１ａの実行を開始させる（タイミングＴ１１）。スレッド１２１ａは、ＨＣＡドライバ１４０に対して受信関数「ｒｅｃｖ」を発行する。これにより、受信メッセージに対応するエントリがＱＰに登録される。また、スレッド１２１ａは、メッセージの受信待ち状態となり、ＣＱに対してポーリングするための関数（ibv＿poll＿cq）を、受信要求に対応するエントリをＣＱから取得できるまでの間、一定時間ごとに発行する。しかし、所定回数だけ関数を発行しても対応するエントリを取得できなかった場合、スレッド１２１ａは、一旦サスペンドして、制御をスレッドスケジューラ１３１に移す（タイミングＴ１２）。
【００７８】
スレッドスケジューラ１３１は、スレッド１２１ｂの実行を開始させる（タイミングＴ１３）。スレッド１２１ｂは、処理Ｂ１を実行した後、サスペンドして、制御をスレッドスケジューラ１３１に移す（タイミングＴ１４）。スレッドスケジューラ１３１は、スレッド１２１ａを起床させる（タイミングＴ１５）。起床したスレッド１２１ａは、ポーリングのための関数の発行を再度繰り返す。しかし、所定回数だけ関数を発行しても対応するエントリを取得できなかった場合、スレッド１２１ａは、サスペンドして、制御をスレッドスケジューラ１３１に移す（タイミングＴ１６）。
【００７９】
スレッドスケジューラ１３１は、スレッド１２１ｂの実行を開始させる（タイミングＴ１７）。スレッド１２１ｂは、処理Ｂ１の次の処理Ｂ２を実行した後、サスペンドして、制御をスレッドスケジューラ１３１に移す（タイミングＴ１８）。スレッドスケジューラ１３１は、スレッド１２１ａを起床させる（タイミングＴ１９）。起床したスレッド１２１ａは、ポーリングのための関数の発行を再度繰り返す。しかし、所定回数だけ関数を発行しても対応するエントリを取得できなかった場合、スレッド１２１ａは、サスペンドして、制御をスレッドスケジューラ１３１に移す（タイミングＴ２０）。スレッドスケジューラ１３１は、スレッド１２１ｂの実行を開始させ（タイミングＴ２１）、スレッド１２１ｂは、処理Ｂ２の次の処理Ｂ３を実行する。
【００８０】
以上の例のように、受信関数「ｒｅｃｖ」の発行後に長期間受信メッセージが到着しない場合、スレッド１２１ａは、起床、ポーリング、サスペンドという動作を何度も繰り返すことになる。スレッド１２１ａの起床やサスペンドが行われるたびに、コンテキストスイッチが発生する。コンテキストスイッチは、レジスタのデータ退避などの処理を伴うため、ＣＰＵの処理負荷が大きい。このため、上記のようにスレッド１２１ａの起床やサスペンドが繰り返されると、ＣＰＵの処理負荷が増大して、実行可能な他のスレッド１２１ｂの処理が遅延してしまい、処理効率が低下するという問題がある。
【００８１】
このような問題に対して、本実施の形態では、スレッドだけでなく、スレッドスケジューラもＣＱのポーリングを実行可能にする。そして、スレッドは、受信関数「ｒｅｃｖ」の発行後、ＣＱのポーリングを１回だけ実行し、自分宛てのメッセージが到着していない場合にはサスペンドする。このスレッドに対応するエントリを取得するためのポーリングは、それ以後、スレッドスケジューラ（または他のスレッド）によって実行される。
【００８２】
図１１は、本実施の形態でのスレッドスケジューリングの例を示す図である。図１１では、図１０の比較例と同様に、スレッド１２１ａ，１２１ｂが実行され、スレッド１２１ａによってメッセージの受信処理が行われる場合の例を示す。
【００８３】
まず、スレッドスケジューラ１３１は、スレッド１２１ａの実行を開始させる（タイミングＴ３１）。スレッド１２１ａは、ＨＣＡドライバ１４０に対して受信関数「ｒｅｃｖ」を発行し、その後１回だけＣＱのポーリングを行う。このとき、対応するエントリを取得できなかった場合、スレッド１２１ａは、即座にサスペンドして、制御をスレッドスケジューラ１３１に移す（タイミングＴ３２）。
【００８４】
一方、スレッドスケジューラ１３１は、制御が移されるたびに、次に実行させるスレッドのスケジューリングとともに、ＣＱのポーリングを行う。図１１の例では、タイミングＴ３２でスレッド１２１ａから制御が移されると、スレッドスケジューラ１３１は、次に実行させるスレッドとしてスレッド１２１ｂを選択するとともに、ＣＱのポーリングを行う。そして、それが終了すると、スレッドスケジューラ１３１はスレッド１２１ｂの実行を開始させる（タイミングＴ３３）。
【００８５】
スレッド１２１ｂによる処理Ｂ１の実行が終了すると、制御がスレッドスケジューラ１３１に移り（タイミングＴ３４）、スレッドスケジューラ１３１によるスケジューリングとポーリングとが行われる。スレッド１２１ａに対応するエントリをＣＱから取得できない場合、スレッド１２１ｂが起床して後続の処理Ｂ２を実行する（タイミングＴ３５）。
【００８６】
処理Ｂ２の実行が終了すると、制御がスレッドスケジューラ１３１に移り（タイミングＴ３６）、スレッドスケジューラ１３１によるスケジューリングとポーリングとが行われる。ここでもスレッド１２１ａに対応するエントリをＣＱから取得できない場合、スレッド１２１ｂが起床して後続の処理Ｂ３を実行する（タイミングＴ３７）。
【００８７】
処理Ｂ３の実行が終了すると、制御がスレッドスケジューラ１３１に移り（タイミングＴ３８）、スレッドスケジューラ１３１によるスケジューリングとポーリングとが行われる。ここで、スレッド１２１ａに対応するエントリをＣＱから取得できた場合、スレッドスケジューラ１３１は、スレッド１２１ａを起床させる（タイミングＴ３９）。スレッド１２１ａは、受信メッセージを取得して、後続の処理を再開する。
【００８８】
以上のように、スレッド１２１ａは、受信関数「ｒｅｃｖ」の発行後、ＣＱのポーリングを１回だけ実行し、対応するエントリを取得できなかった場合にはサスペンドする。このスレッドに対応するエントリを取得するためのポーリングは、それ以後、スレッドスケジューラ１３１によって実行される。そして、スレッドスケジューラ１３１によってスレッド１２１ａに対応するエントリがＣＱから取得された場合、スレッド１２１ａが起床する。
【００８９】
このような処理により、ポーリングに失敗したスレッド１２１ａが起床とサスペンドを何度も繰り返すことが防止される。このため、無駄なコンテキストスイッチの発生回数が少なくなり、ＣＰＵの処理負荷が低下する。その結果、ＣＰＵの処理効率が向上し、実行可能なスレッド１２１ｂの実行遅延を小さくすることができる。
【００９０】
図１２は、スレッドスケジューリングで使用されるデータ構造の例を示す図である。本実施の形態では、上記のようなスレッドスケジューリングを実現するための、コネクション構造体１５１および待ち合わせ構造体１５２が使用される。
【００９１】
コネクション構造体１５１は、スレッド間のコネクションが確立されるたびに、そのコネクションの両側のスレッドによってそれぞれ作成され、各スレッドが他方のスレッドとの通信を行うために使用される。コネクション構造体１５１は、自ノード側スレッド、他ノード側スレッドの各識別番号、ＸＩＤ、ＱＰ／ＣＱへのポインタ、および待ち合わせ構造体へのポインタを保持する。
【００９２】
自ノード側スレッドは、コネクションの両側のノードのうち、自ノードのスレッドを示し、他ノード側スレッドは、他ノードのスレッドを示す。ＸＩＤは、前述のように、スレッド間のコネクションごとに生成される固有の番号である。ＱＰ／ＣＱへのポインタは、通信相手のスレッドとの通信で用いられるＱＰ／ＣＱ１１１内のＱＰおよびＣＱの位置を示す。待ち合わせ構造体へのポインタは、対応する待ち合わせ構造体１５２の位置を示す。
【００９３】
待ち合わせ構造体１５２は、自ノード側のスレッドの状態を管理するために使用されるデータ構造体である。待ち合わせ構造体１５２は、Ｂｌｏｃｋｅｄキュー１５２ａとメッセージ情報キュー１５２ｂとを保持する。Ｂｌｏｃｋｅｄキュー１５２ａには、サスペンド状態のスレッドに対応するエントリが、Ｒｅａｄｙキュー１１５ａ〜１１５ｃから取り出されて格納される。メッセージ情報キュー１５２ｂには、受信メッセージを格納するためのバッファ領域を示すポインタを含むエントリが格納される。
【００９４】
図１３は、キュー間のエントリ移動によるサスペンドおよび起床動作について説明するための図である。受信関数「ｒｅｃｖ」を発行したスレッドは、ポーリングに失敗すると、対応するエントリをＲｅａｄｙキュー１１５ａ〜１１５ｃのいずれかから取り出し、待ち合わせ構造体１５２のＢｌｏｃｋｅｄキュー１５２ａに格納することで、サスペンド状態に遷移する。このとき、スレッドは、受信メッセージを格納するためのバッファ領域を示すポインタを含むエントリを、待ち合わせ構造体１５２のメッセージ情報キュー１５２ｂに登録する。このバッファ領域は、ＨＣＡドライバ１４０によって受信バッファに格納された受信メッセージを退避するためのメモリ領域である。
【００９５】
その後、スレッドスケジューラまたは他のスレッドによって、受信バッファに格納された受信メッセージがバッファ領域にセットされ、対応するエントリがＢｌｏｃｋｅｄキュー１５２ａから取り出され、Ｒｅａｄｙキュー１１５ａ〜１１５ｃのいずれかに登録される。これにより、このエントリに対応するスレッドが起床する。
【００９６】
なお、スレッドが起床している状態とは、対応するエントリがＲｅａｄｙキュー１１５１ａ〜１１５ｃのいずれかに登録されており、そのスレッドが、スレッドスケジューラが次に実行させるスレッドを選択する際の選択対象に含まれている状態を指す。そして、そのエントリがＲｅａｄｙキュー１１５ａ〜１１５ｃのいずれかからスレッドスケジューラに取り出されることで、そのエントリに対応するスレッドの実行が開始される。
【００９７】
以下、図１４、図１５を用いて、スレッドの状態遷移の具体例について説明する。図１４、図１５では、例として、ノード１００−１においてスレッド＃０とスレッド＃１が実行される場合について示す。
【００９８】
図１４は、スレッドの状態遷移についての第１の例を示す図である。図１４の初期状態では、スレッド＃０と、他のノードのスレッド（ここでは、ノード１００−２のスレッド＃０１とする）とのコネクションが確立されている。そして、このコネクションにＸＩＤ「０」が付与され、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２において、ＸＩＤ「０」に対して待ち合わせ構造体Ｑｓｔｒ＃０が対応付けられている。また、スレッド＃１と、ノード１００−２の他のスレッド（スレッド＃１１とする）とのコネクションが確立されている。そして、このコネクションにＸＩＤ「１」が付与され、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２において、ＸＩＤ「１」に対して待ち合わせ構造体Ｑｓｔｒ＃１が対応付けられている。
【００９９】
さらに、スレッド＃０は、メッセージの受信を要求した後にサスペンド状態になっており、待ち合わせ構造体Ｑｓｔｒ＃０のＢｌｏｃｋｅｄキュー１５２ａには、スレッド＃０に対応するエントリが格納されている。また、待ち合わせ構造体Ｑｓｔｒ＃０のメッセージ情報キュー１５２ｂには、受信メッセージを格納するためのバッファ領域Ｂ０を示すポインタを含むエントリが登録されている。
【０１００】
なお、ＩｎｆｉｎｉＢａｎｄでは、メッセージの送信順序や受信順序は入れ替わらないことが保証されている。
上記状態から、スレッドスケジューラ１３１が、Ｒｅａｄｙキュー１１５ａからスレッド＃１に対応するエントリを取得し、スレッド＃１の実行を開始させたとする（ステップＳ１１）。スレッド＃１は、受信関数「ｒｅｃｖ」をＨＣＡドライバ１４０に発行して、メッセージの受信を要求する（ステップＳ１２）。これにより、スレッド＃１からの受信要求に対応するエントリがＱＰ／ＣＱ１１１ａのＱＰに格納される。さらに、スレッド＃１は、ＱＰ／ＣＱ１１１ａのＣＱに対するポーリングを行う（ステップＳ１３）。
【０１０１】
スレッド＃１は、ＣＱからエントリＥ０を取得し、エントリＥ０が示す受信バッファＲ０から受信メッセージを取得する。ここで、仮に、取得した受信メッセージがＸＩＤ「１」を含んでいれば、スレッド＃１は、エントリが自分宛てであることを認識し、受信メッセージを用いて後続の処理を実行できる。
【０１０２】
しかし、図１４の例では、取得した受信メッセージがＸＩＤ「０」を含んでいたとする。この場合、スレッド＃０が受信を要求したメッセージがＨＣＡ１０７によって受信済みであり、その受信メッセージが受信バッファＲ０に格納されている。スレッド＃１は、取得したエントリが自分宛てではないことを認識して、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２を参照し、ＸＩＤ「０」に対応する待ち合わせ構造体Ｑｓｔｒ＃０を特定する（ステップＳ１４）。
【０１０３】
スレッド＃１は、待ち合わせ構造体Ｑｓｔｒ＃０のメッセージ情報キュー１５２ｂからエントリを取得し、取得したエントリが示すバッファ領域Ｂ０に、受信バッファＲ０に格納されている受信メッセージを書き込む（ステップＳ１５）。さらに、スレッド＃１は、待ち合わせ構造体Ｑｓｔｒ＃０のＢｌｏｃｋｅｄキュー１５２ａからエントリを取り出して、このエントリをＲｅａｄｙキュー１１５ａに移動させる（ステップＳ１６）。これにより、スレッド＃０が起床する。すなわち、移動されたエントリがスレッドスケジューラ１３１に取得されてスレッド＃０の実行が開始されたとき、スレッド＃０は、バッファ領域Ｂ０に書き込まれた受信メッセージを用いて処理を続行できる。
【０１０４】
なお、バッファ領域Ｂ０は、受信バッファＲ０に格納された受信メッセージを退避するために用いられる。ステップＳ１３のポーリングが完了することにより、取得されたエントリＥ０が示す受信バッファＲ０は解放されてしまう。しかし、受信バッファＲ０に格納されていた受信メッセージがバッファ領域Ｂ０に退避されることで、スレッド＃０は、ポーリングの完了後にバッファ領域Ｂ０から受信メッセージを取得できるようになる。
【０１０５】
スレッド＃１は、以上の処理が完了すると、ステップＳ１１でＲｅａｄｙキュー１１５ａから取得されたエントリを、待ち合わせ構造体Ｑｓｔｒ＃１のＢｌｏｃｋｅｄキュー１５２ａに移動させる（ステップＳ１７）。さらに、スレッド＃１は、待ち合わせ構造体Ｑｓｔｒ＃１のメッセージ情報キュー１５２ｂに、受信メッセージを格納するためのバッファ領域Ｂ１を示すポインタを含むエントリを格納する。これにより、スレッド＃１はサスペンドする。
【０１０６】
図１５は、スレッドの状態遷移についての第２の例を示す図である。図１４に示したようにスレッド＃１がサスペンドした後に、スレッドスケジューラ１３１によるＱＰ／ＣＱ１１１ａのＣＱのポーリングによって、エントリＥ１が取得される。そして、取得されたエントリＥ１が示す受信バッファＲ１から、ＸＩＤ「１」を含む受信メッセージが取得されたとする（ステップＳ２１）。
【０１０７】
スレッドスケジューラ１３１は、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２を参照し、ＸＩＤ「１」に対応する待ち合わせ構造体Ｑｓｔｒ＃１を特定する（ステップＳ２２）。スレッドスケジューラ１３１は、待ち合わせ構造体Ｑｓｔｒ＃１のメッセージ情報キュー１５２ｂからエントリを取得し、取得したエントリが示すバッファ領域Ｂ１に、受信バッファＲ１に格納されている受信メッセージを書き込む（ステップＳ２３）。さらに、スレッドスケジューラ１３１は、待ち合わせ構造体Ｑｓｔｒ＃１のＢｌｏｃｋｅｄキュー１５２ａからエントリを取り出して、このエントリをＲｅａｄｙキュー１１５ａに移動させる（ステップＳ２４）。
【０１０８】
これにより、スレッド＃１が起床する。すなわち、移動されたエントリがスレッドスケジューラ１３１に取得されてスレッド＃１の実行が開始されたとき、スレッド＃１は、バッファ領域Ｂ１に書き込まれた受信メッセージを用いて処理を続行できる。
【０１０９】
以上の図１４、図１５の例のように、本実施の形態では、ＣＱのポーリングに１回失敗したスレッドは、それ以上ポーリングを行わずにサスペンドする。その後、スレッドスケジューラまたは他のスレッドによるＣＱのポーリングにより、サスペンドしたスレッドに対応するエントリがＣＱから取得されることで、サスペンドしたスレッドが起床する。
【０１１０】
このような仕組みにより、ポーリングに失敗してサスペンドしたスレッドは、要求したメッセージが受信されるまで起床しない。そのため、ポーリングに失敗したスレッドがポーリングの再実行のために起床とサスペンドを何度も繰り返すことがなくなり、無駄なコンテキストスイッチの発生回数が減少する。その結果、ＣＰＵの処理効率を向上させることができる。
【０１１１】
また、上記の仕組みにより、ＣＱに格納されたあるスレッド宛てのエントリは、そのスレッドによるポーリングだけでなく、他のスレッドやスレッドスケジューラによるポーリングによっても取得される。そして、取得されたエントリに対応する受信メッセージを、宛先のスレッドが利用できるようになる。これにより、ポーリングを行ったときに、どのスレッド宛てのエントリも取得できないという確率が低くなる。その結果、無駄なポーリングの回数を減少させることができ、ＣＰＵやメモリなどのリソースの利用効率が向上する。
【０１１２】
＜フローチャート＞
次に、ノード１００の処理についてフローチャートを用いて説明する。
図１６は、スレッド間のコネクション確立を要求する処理手順の例を示すフローチャートである。ここでは例として、ノード１００−１のスレッド＃１１が、ノード１００−２のスレッド＃２１との間でコネクションを確立するケースについて示す。
【０１１３】
［ステップＳ５１］スレッド＃１１は、コネクションプール１１３から未使用のコネクション構造体１５１を取得する。このとき、未使用の待ち合わせ構造体１５２も取得される。スレッド＃１１は、取得したコネクション構造体１５１に対して、自ノード側スレッドとしてスレッド＃１１を登録し、他ノード側スレッドとしてスレッド＃２１を登録する。また、スレッド＃１１は、取得したコネクション構造体１５１に対して、ノード１００−２との通信に使用するＱＰ／ＣＱ１１１ａに対するポインタと、取得した待ち合わせ構造体１５２に対するポインタとを登録する。
【０１１４】
さらに、スレッド＃１１は、新たなＸＩＤを発行して、取得したコネクション構造体１５１に登録する。ＸＩＤは、ノード１００−１の番号と、直前に発行されたシーケンシャル番号に「１」を加算した値とを組み合わせることによって算出される。ここでは、説明を簡単にするためにＸＩＤ「１１」が発行されたとする。
【０１１５】
［ステップＳ５２］スレッド＃１１は、発行したＸＩＤ「１１」と、取得した待ち合わせ構造体１５２を示す情報とを含むレコードを、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２に新たに登録する。
【０１１６】
［ステップＳ５３］スレッド＃１１は、コネクション確立依頼フラグと、通信相手のスレッド＃２１の種別を示すスレッド種別番号ｔｉｄと、ＸＩＤ「１１」とを、送信バッファにセットする。コネクション確立依頼フラグは、コネクションの確立要求であることを示す「１」にセットされる。
【０１１７】
［ステップＳ５４］スレッド＃１１は、ＨＣＡドライバ１４０に対して送信関数「ｓｅｎｄ」を発行する。このとき、スレッド＃１１は、引数として、コネクション構造体１５１へのポインタと、送信バッファのアドレスとをセットする。
【０１１８】
これにより、ＱＰ／ＣＱ１１１ａのＱＰに、コネクション確立のための送信要求を示すエントリが登録される。ＨＣＡドライバ１４０は、このエントリを取得すると、送信バッファにセットされた情報をノード１００−２に送信する。これにより、新たに発行されたＸＩＤ「１１」が相手のノード１００−２に伝達される。
【０１１９】
図１７は、メッセージの送信を要求する処理手順の例を示すフローチャートである。ここでは例として、図１６の処理によってスレッド＃２１とのコネクションが確立された後に、スレッド＃１１がスレッド＃２１に対してメッセージを送信するケースについて示す。
【０１２０】
［ステップＳ６１］スレッド＃１１は、自ノード側スレッドとしてスレッド＃１１が登録され、他ノード側スレッドとしてスレッド＃２１が登録されたコネクション構造体１５１を参照し、このコネクション構造体１５１からＸＩＤ「１１」を取得する。
【０１２１】
［ステップＳ６２］スレッド＃１１は、コネクション確立依頼フラグと、通信相手のスレッド＃２１の種別を示すスレッド種別番号ｔｉｄと、ＸＩＤ「１１」とが付加された送信メッセージを、送信バッファにセットする。コネクション確立依頼フラグは、コネクションの確立要求でないことを示す「０」にセットされる。
【０１２２】
［ステップＳ６３］スレッド＃１１は、ＨＣＡドライバ１４０に対して送信関数「ｓｅｎｄ」を発行する。このとき、スレッド＃１１は、引数として、コネクション構造体１５１へのポインタと、送信バッファのアドレスとをセットする。
【０１２３】
これにより、ＱＰ／ＣＱ１１１ａのＱＰに、メッセージの送信要求を示すエントリが登録される。ＨＣＡドライバ１４０は、このエントリを取得すると、送信バッファにセットされた送信メッセージをノード１００−２に送信する。これにより、送信メッセージとともにＸＩＤ「１１」が相手のノード１００−２に伝達される。
【０１２４】
図１８〜図２０は、メッセージの受信を要求する処理手順の例を示すフローチャートである。ここでは例として、ノード１００−２のスレッド＃２２が、ノード１００−１のスレッド＃１２から送信されるメッセージを受信するケースについて示す。なお、スレッド＃１２とスレッド＃２２との間のコネクションは確立済みであり、このコネクションに対してＸＩＤ「１２」が付与されているものとする。
【０１２５】
［ステップＳ７１］スレッド＃２２は、自ノード側スレッドとしてスレッド＃２２が登録され、他ノード側スレッドとしてスレッド＃１２が登録されたコネクション構造体１５１を参照し、このコネクション構造体１５１からＸＩＤ「１２」を取得する。
【０１２６】
［ステップＳ７２］スレッド＃２２は、ＨＣＡドライバ１４０に対して受信関数「ｒｅｃｖ」を発行する。このとき、スレッド＃２２は、引数として、ステップＳ７１で参照したコネクション構造体１５１へのポインタと、受信バッファのアドレスとをセットする。
【０１２７】
これにより、ＱＰ／ＣＱ１１１ａのＱＰに、メッセージの受信要求を示すエントリが登録される。ＨＣＡドライバ１４０は、このエントリを取得すると、ノード１００−２からメッセージを受信して受信バッファにセットする。そして、ＨＣＡドライバ１４０は、ＱＰ／ＣＱ１１１ａのＣＱに、受信完了を示すエントリを登録する。ただし、次のステップＳ７３の実行時点では、このエントリがＣＱに登録されているとは限らない。
【０１２８】
［ステップＳ７３］スレッド＃２２は、ＨＣＡドライバ１４０に対して、ノード１００−１との通信用のＣＱ、すなわち、ＱＰ／ＣＱ１１１ａのＣＱにポーリングするための関数を発行する。これにより、ＣＱのポーリングが行われる。
【０１２９】
［ステップＳ７４］スレッド＃２２は、ポーリングの結果として、受信完了を示すエントリをＣＱから取得できたかを判定する。スレッド＃２２は、該当エントリを取得できた場合、図１９のステップＳ８１の処理を実行し、取得できなかった場合、ステップＳ７５の処理を実行する。
【０１３０】
なお、ステップＳ７４で取得されるエントリは、ステップＳ７２による受信要求に対応する受信完了を示すとは限らない。
また、ステップＳ７４では、送信完了を示すエントリが取得される場合もある。この場合、スレッド＃２２は、送信要求を行ったスレッドを起床させた後、ステップＳ７５の処理を実行する。
【０１３１】
［ステップＳ７５］スレッド＃２２は、Ｒｅａｄｙキューからスレッドスケジューラによって取得された、スレッド＃２２に対応するエントリを、待ち合わせ構造体１５２のＢｌｏｃｋｅｄキュー１５２ａに移動させる。移動先の待ち合わせ構造体１５２は、ステップＳ７１で参照されたコネクション構造体１５１に登録されたポインタによって示される待ち合わせ構造体１５２である。
【０１３２】
また、スレッド＃２２は、この待ち合わせ構造体１５２のメッセージ情報キュー１５２ｂに、受信メッセージを格納するためのバッファ領域を示すポインタを含むエントリを格納する。以上のステップＳ７５の処理により、スレッド＃２２はサスペンド状態に遷移する。
【０１３３】
以下、図１９を用いて説明を続ける。
［ステップＳ８１］スレッド＃２２は、ＨＣＡドライバ１４０によって受信されたメッセージが格納されている受信バッファから、ステップＳ７４で取得されたエントリに対応する受信メッセージを取得する。スレッド＃２２は、受信メッセージから、コネクション確立依頼フラグと、スレッド種別番号ｔｉｄと、ＸＩＤとを取得する。
【０１３４】
［ステップＳ８２］スレッド＃２２は、コネクション確立依頼フラグが「１」の場合、ステップＳ８３の処理を実行し、「０」の場合、図２０のステップＳ９１の処理を実行する。
【０１３５】
［ステップＳ８３］コネクション確立依頼フラグが「１」の場合、スレッド間のコネクションを新たに確立することが要求されている。ここでは例として、図１６の処理によってスレッド＃１１とスレッド＃２１との間のコネクションの確立が要求されたものとして説明する。この場合、受信メッセージにはＸＩＤ「１１」が含まれている。
【０１３６】
スレッド＃２２は、まず、待ち合わせ構造体１５２を新たに作成する。
［ステップＳ８４］スレッド＃２２は、受信メッセージから取得したＸＩＤ「１１」と、ステップＳ８３で作成した待ち合わせ構造体１５２を示すポインタとを含むレコードを、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２に対して新たに登録する。
【０１３７】
［ステップＳ８５］スレッド＃２２は、スレッド−関数対応テーブル１１４を参照し、受信メッセージから取得したスレッド種別番号ｔｉｄに対応付けられたスレッド＃２１を特定する。スレッド＃２２は、特定されたスレッド＃２１を起動する。この後、スレッド＃２２は、図１８のステップＳ７５の処理を実行して、サスペンド状態に遷移する。
【０１３８】
［ステップＳ８６］ステップＳ８５で起動したスレッド＃２１は、コネクションプール１１３から未使用のコネクション構造体１５１を取得する。スレッド＃２１は、取得したコネクション構造体１５１に対して、自ノード側スレッドとしてスレッド＃２１を登録し、他ノード側スレッドとしてスレッド＃１１を登録する。また、スレッド＃２１は、取得したコネクション構造体１５１に対して、ステップＳ８１で受信メッセージから取得したＸＩＤを登録する。さらに、スレッド＃２１は、ノード１００−１との通信に使用するＱＰ／ＣＱ１１１ａに対するポインタと、ステップＳ８３で作成された待ち合わせ構造体１５２に対するポインタとを登録する。これにより、スレッド＃１１とスレッド＃２１とのコネクションが確立される。
【０１３９】
なお、この後、起動したスレッド＃２１は、スレッドスケジューラの制御の下で後続の処理を実行する。
以下、図２０を用いて説明を続ける。
【０１４０】
［ステップＳ９１］図１９のステップＳ８２でコネクション確立依頼フラグが「０」の場合、ＣＱから取得されたエントリは受信完了を示すエントリである。スレッド＃２２は、受信メッセージから取得したＸＩＤが、図１８のステップＳ７１で取得したＸＩＤ「１２」と一致するかを判定する。ＸＩＤが一致した場合、ＣＱから取得されたエントリはスレッド＃２２宛てのエントリである。この場合、スレッド＃２２は、ステップＳ９２の処理を実行する。一方、ＸＩＤが一致しない場合、ＣＱから取得されたエントリはスレッド＃２２以外の他のスレッド宛てのエントリである。この場合、スレッド＃２２は、ステップＳ９３の処理を実行する。
【０１４１】
［ステップＳ９２］スレッド＃２２は、取得した受信メッセージを用いて後続の処理を実行する。
［ステップＳ９３］スレッド＃２２は、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２を参照し、受信メッセージから取得したＸＩＤに対応する待ち合わせ構造体１５２を特定する。
【０１４２】
［ステップＳ９４］スレッド＃２２は、特定された待ち合わせ構造体１５２のメッセージ情報キュー１５２ｂからエントリを取得し、取得したエントリが示すバッファ領域に受信メッセージを書き込む。さらに、スレッド＃２２は、この待ち合わせ構造体１５２のＢｌｏｃｋｅｄキュー１５２ａからエントリを取り出して、このエントリをＲｅａｄｙキューに移動させる。ＣＱから取得されたエントリが、例えばスレッド＃２３宛てであったとすると、ステップＳ９４の処理により、スレッド＃２３が起床する。
【０１４３】
スレッド＃２２は、この後、図１８のステップＳ７５の処理を実行して、サスペンド状態に遷移する。
図２１、図２２は、スレッドスケジューラの処理手順の例を示すフローチャートである。ここでは例として、ノード１００−２のスレッドスケジューラ１３１の処理について示す。なお、図２１、図２２の処理は、繰り返し実行される。
【０１４４】
［ステップＳ１０１］スレッドスケジューラ１３１は、ノード１００−２のＣＱの中にポーリングしていないＣＱがあるかを判定する。スレッドスケジューラ１３１は、ポーリングしていないＣＱがある場合、ステップＳ１０２の処理を実行し、すべてのＣＱについてポーリング済みである場合、ステップＳ１０４の処理を実行する。
【０１４５】
［ステップＳ１０２］スレッドスケジューラ１３１は、ポーリングしていないＣＱに対してポーリングを行う。
［ステップＳ１０３］スレッドスケジューラ１３１は、ポーリングの結果として、受信完了を示すエントリをＣＱから取得できたかを判定する。スレッドスケジューラ１３１は、該当エントリを取得できた場合、図２２のステップＳ１１１の処理を実行し、取得できなかった場合、ステップＳ１０１の処理を実行する。
【０１４６】
［ステップＳ１０４］スレッドスケジューラ１３１は、Ｒｅａｄｙキュー１１５ａから先頭のエントリを取得し、そのエントリに対応するスレッドの実行を開始させる。
以下、図２２を用いて説明を続ける。
【０１４７】
［ステップＳ１１１］スレッドスケジューラ１３１は、ＨＣＡドライバ１４０によって受信されたメッセージが格納されている受信バッファから、図２１のステップＳ１０３で取得されたエントリに対応する受信メッセージを取得する。スレッドスケジューラ１３１は、受信メッセージから、コネクション確立依頼フラグと、スレッド種別番号ｔｉｄと、ＸＩＤとを取得する。
【０１４８】
［ステップＳ１１２］スレッドスケジューラ１３１は、コネクション確立依頼フラグが「１」の場合、ステップＳ１１３の処理を実行し、「０」の場合、ステップＳ１１６の処理を実行する。
【０１４９】
［ステップＳ１１３］コネクション確立依頼フラグが「１」の場合、スレッド間のコネクションを新たに確立することが要求されている。ここでは例として、図１６の処理によってスレッド＃１１とスレッド＃２１との間のコネクションの確立が要求されたものとして説明する。この場合、受信メッセージにはＸＩＤ「１１」が含まれている。
【０１５０】
スレッドスケジューラ１３１は、まず、待ち合わせ構造体１５２を新たに作成する。
［ステップＳ１１４］スレッドスケジューラ１３１は、受信メッセージから取得したＸＩＤ「１１」と、ステップＳ１１３で作成した待ち合わせ構造体１５２を示すポインタとを含むレコードを、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２に対して新たに登録する。
【０１５１】
［ステップＳ１１５］スレッドスケジューラ１３１は、スレッド−関数対応テーブル１１４を参照し、受信メッセージから取得したスレッド種別番号ｔｉｄに対応付けられたスレッド＃２１を特定する。スレッドスケジューラ１３１は、特定されたスレッド＃２１を起動する。この後、スレッドスケジューラ１３１は、図２１のステップＳ１０１の処理を実行する。
【０１５２】
［ステップＳ１１６］スレッドスケジューラ１３１は、ＸＩＤ−Ｑｓｔｒ対応テーブル１１２を参照し、受信メッセージから取得したＸＩＤに対応する待ち合わせ構造体１５２を特定する。
【０１５３】
［ステップＳ１１７］スレッドスケジューラ１３１は、特定された待ち合わせ構造体１５２のメッセージ情報キュー１５２ｂからエントリを取得し、取得したエントリが示すバッファ領域に受信メッセージを書き込む。さらに、スレッドスケジューラ１３１は、この待ち合わせ構造体１５２のＢｌｏｃｋｅｄキュー１５２ａからエントリを取り出して、このエントリをＲｅａｄｙキューに移動させる。ＣＱから取得されたエントリが、例えばスレッド＃２３宛てであったとすると、ステップＳ１１７の処理により、スレッド＃２３が起床する。
【０１５４】
この後、スレッドスケジューラ１３１は、図２１のステップＳ１０１の処理を実行する。
＜スレッドの具体例＞
次に、スレッドの具体的な処理例について説明する。
【０１５５】
図２３は、スレッドの処理例を示す図である。図２３の例では、ノード１００−１のスレッド＃１５と、ノード１００−２のスレッド＃２５との間でコネクションが確立されているものとする。スレッド＃１５は、ホスト装置からの書き込み要求を受け付けるスレッドであり、スレッド＃２５は、書き込みデータの格納を担当する「担当ノード」において、他のノードから転送された書き込みデータを受け付けるスレッドである。
【０１５６】
［ステップＳ１２１］スレッド＃１５は、ホスト装置から、書き込み要求および書き込みデータを受信する。
［ステップＳ１２２］スレッド＃１５は、書き込みアドレスを解析して、ノード１００−２を担当ノードと判別する。
【０１５７】
［ステップＳ１２３］スレッド＃１５は、担当ノードであるノード１００−２に対して書き込みデータを送信する。
［ステップＳ１２４］スレッド＃２５は、書き込みデータを受信する。
【０１５８】
［ステップＳ１２５］スレッド＃２５は、受信した書き込みデータをキャッシュに書き込む。
［ステップＳ１２６］スレッド＃２５は、書き込みの完了通知をノード１００−１に送信する。
【０１５９】
［ステップＳ１２７］スレッド＃１５は、完了通知を受信し、ホスト装置に対して書き込みが完了したことを通知する。
［ステップＳ１２８］スレッド＃１５は、次の書き込みデータの受信待ち状態になる。
【０１６０】
以上の処理において、スレッド＃２５は、例えば、ステップＳ１２４で書き込みデータを受信するために受信関数「ｒｅｃｖ」を発行し、続いてＣＱをポーリングする。スレッド＃２５は、ポーリングにより自分宛てのエントリを取得できなかった場合、サスペンドして受信待ち状態となる。その後、スレッド＃１５とスレッド＃２５とのコネクションに対応するＸＩＤが付加された書き込みデータが受信されると、ノード１００−２上の他のスレッドまたはスレッドスケジューラによるポーリングによって、ＣＱからスレッド＃２５宛てのエントリが取得される。すると、スレッド＃２５は起床し、受信された書き込みデータを取得して、ステップＳ１２５からの後続処理の実行を開始する。
【０１６１】
このような処理により、スレッド＃２５は、ポーリングによる書き込みデータの取得に失敗するとサスペンドし、書き込みデータの受信が完了するまで起床しない。このため、スレッド＃２５のサスペンドおよび起床の回数が低減されて、コンテキストスイッチの発生が抑制され、その結果、ノード１００−２のＣＰＵの利用効率が向上される。
【０１６２】
一方、スレッド＃１５は、例えば、ステップＳ１２３の書き込みデータ送信が完了した後、ステップＳ１２７で完了通知を受信するために受信関数「ｒｅｃｖ」を発行し、続いてＣＱをポーリングする。スレッド＃１５は、ポーリングにより自分宛てのエントリを取得できなかった場合、サスペンドして受信待ち状態となる。その後、スレッド＃１５とスレッド＃２５とのコネクションに対応するＸＩＤが付加された完了通知が受信されると、ノード１００−１上の他のスレッドまたはスレッドスケジューラによるポーリングによって、ＣＱからスレッド＃１５宛てのエントリが取得される。すると、スレッド＃１５は起床し、受信された完了通知を取得して、ステップＳ１２８からの後続処理の実行を開始する。
【０１６３】
このような処理により、スレッド＃１５は、ポーリングによる完了通知の取得に失敗するとサスペンドし、完了通知の受信が完了するまで起床しない。このため、スレッド＃１５のサスペンドおよび起床の回数が低減されて、コンテキストスイッチの発生が抑制され、その結果、ノード１００−１のＣＰＵの利用効率が向上される。
【０１６４】
なお、上記の各実施の形態に示した装置（例えば、情報処理装置１，２、ノード１００，１００−１〜１００−４）の処理機能は、コンピュータによって実現することができる。その場合、各装置が有すべき機能の処理内容を記述したプログラムが提供され、そのプログラムをコンピュータで実行することにより、上記処理機能がコンピュータ上で実現される。処理内容を記述したプログラムは、コンピュータで読み取り可能な記録媒体に記録しておくことができる。コンピュータで読み取り可能な記録媒体としては、磁気記憶装置、光ディスク、光磁気記録媒体、半導体メモリなどがある。磁気記憶装置には、ハードディスク装置（ＨＤＤ）、フレキシブルディスク（ＦＤ）、磁気テープなどがある。光ディスクには、ＤＶＤ（Digital Versatile Disc）、ＤＶＤ−ＲＡＭ、ＣＤ−ＲＯＭ（Compact Disc-Read Only Memory）、ＣＤ−Ｒ（Recordable）／ＲＷ（ReWritable）などがある。光磁気記録媒体には、ＭＯ（Magneto-Optical disk）などがある。
【０１６５】
プログラムを流通させる場合には、例えば、そのプログラムが記録されたＤＶＤ、ＣＤ−ＲＯＭなどの可搬型記録媒体が販売される。また、プログラムをサーバコンピュータの記憶装置に格納しておき、ネットワークを介して、サーバコンピュータから他のコンピュータにそのプログラムを転送することもできる。
【０１６６】
プログラムを実行するコンピュータは、例えば、可搬型記録媒体に記録されたプログラムまたはサーバコンピュータから転送されたプログラムを、自己の記憶装置に格納する。そして、コンピュータは、自己の記憶装置からプログラムを読み取り、プログラムにしたがった処理を実行する。なお、コンピュータは、可搬型記録媒体から直接プログラムを読み取り、そのプログラムにしたがった処理を実行することもできる。また、コンピュータは、ネットワークを介して接続されたサーバコンピュータからプログラムが転送されるごとに、逐次、受け取ったプログラムにしたがった処理を実行することもできる。
【符号の説明】
【０１６７】
１，２  情報処理装置
１ａ  通信インタフェース
１ｂ  制御部
１ｃ  キュー
１ｄ  バッファ
１０  データ
１１〜１３  スレッド
Ｓ１，Ｓ２，Ｓ２ａ，Ｓ２ｂ  ステップ
【図１】
2018181134.tif 000003
【図２】
2018181134.tif 000004
【図３】
2018181134.tif 000005
【図４】
2018181134.tif 000006
【図５】
2018181134.tif 000007
【図６】
2018181134.tif 000008
【図７】
2018181134.tif 000009
【図８】
2018181134.tif 000010
【図９】
2018181134.tif 000011
【図１０】
2018181134.tif 000012
【図１１】
2018181134.tif 000013
【図１２】
2018181134.tif 000014
【図１３】
2018181134.tif 000015
【図１４】
2018181134.tif 000016
【図１５】
2018181134.tif 000017
【図１６】
2018181134.tif 000018
【図１７】
2018181134.tif 000019
【図１８】
2018181134.tif 000020
【図１９】
2018181134.tif 000021
【図２０】
2018181134.tif 000022
【図２１】
2018181134.tif 000023
【図２２】
2018181134.tif 000024
【図２３】
2018181134.tif 000025
【手続補正書】
【提出日】平成30年7月10日(2018.7.10)
【手続補正１】
【補正対象書類名】明細書
【補正対象項目名】０００８
【補正方法】変更
【補正の内容】
【０００８】
１つの案では、情報処理装置が提供される。この情報処理装置は、他の情報処理装置と通信するための通信インタフェースと、次のような処理を実行する制御部とを有する。制御部は、複数のスレッドのうち一のスレッドの実行により、他の情報処理装置からのデータの受信要求を通信インタフェースに発行した後であって、複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理が実行されるよりも前に、受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、完了通知が格納されていない場合には、一のスレッドをサスペンド状態に遷移させる第１の処理を実行する。また、制御部は、選択処理と、選択処理によって選択されたスレッドについてキューを確認する確認処理とを実行する第２の処理を実行する。ここで、制御部は、確認処理によってキューに一のスレッドに対応する完了通知が格納されたことを検知した場合、受信データを一のスレッドに受け渡して一のスレッドをサスペンド状態から復帰させる。
【手続補正２】
【補正対象書類名】特許請求の範囲
【補正対象項目名】全文
【補正方法】変更
【補正の内容】
【特許請求の範囲】
【請求項１】
他の情報処理装置と通信するための通信インタフェースと、
複数のスレッドのうち一のスレッドの実行により、前記他の情報処理装置からのデータの受信要求を前記通信インタフェースに発行した後であって、前記複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理が実行されるよりも前に、前記受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、前記完了通知が格納されていない場合には、前記一のスレッドをサスペンド状態に遷移させる第１の処理と、
前記選択処理と、前記選択処理によって選択されたスレッドについて前記キューを確認する確認処理とを実行する第２の処理であって、前記確認処理によって前記キューに前記一のスレッドに対応する前記完了通知が格納されたことを検知した場合、前記受信データを前記一のスレッドに受け渡して前記一のスレッドをサスペンド状態から復帰させる、前記第２の処理と、
を実行する制御部と、
を有する情報処理装置。
【請求項２】
前記複数のスレッドをそれぞれ識別する第１の識別子を記憶する記憶部をさらに有し、
前記他の情報処理装置から送信されるデータには、前記複数のスレッドのうち宛先のスレッドを示す第２の識別子が付加されており、
前記第１の処理では、前記キューを確認したとき、前記複数のスレッドのうち少なくとも前記一のスレッド以外の他のスレッドの実行によって受信が要求された他の受信データの受信が完了したことを示す他の完了通知が格納されていることを検知した場合、前記他の受信データに付加された前記第２の識別子を取得し、前記記憶部を参照して、取得した前記第２の識別子に対応する前記他のスレッドを特定し、前記他のスレッドに対して前記他の受信データを受け渡して前記他のスレッドをサスペンド状態から復帰させ、前記一のスレッドをサスペンド状態に遷移させる、
請求項１記載の情報処理装置。
【請求項３】
前記確認処理では、前記キューに前記完了通知が格納されたことを検知したとき、前記受信データに付加された前記第２の識別子を取得し、取得した前記第２の識別子と、前記記憶部に記憶された前記第１の識別子との比較結果に基づいて、前記受信データの受け渡し先を前記一のスレッドと判定する、
請求項２記載の情報処理装置。
【請求項４】
前記確認処理では、前記キューを確認したとき、前記他の完了通知が格納されていることを検知した場合、前記他の受信データに付加された前記第２の識別子を取得し、前記記憶部を参照して、取得した前記第２の識別子に対応する前記他のスレッドを特定し、前記他のスレッドに対して前記他の受信データを受け渡して前記他のスレッドをサスペンド状態から復帰させる、
請求項２または３記載の情報処理装置。
【請求項５】
記憶部をさらに有し、
前記第１の処理では、前記一のスレッドによって参照される記憶領域を示す領域情報を前記記憶部に登録して、前記一のスレッドをサスペンド状態に遷移させ、
前記第２の処理では、前記領域情報に基づいて前記記憶領域を特定し、前記受信データを前記記憶領域に格納することによって前記受信データを前記一のスレッドに受け渡す、
請求項１記載の情報処理装置。
【請求項６】
コンピュータが、
複数のスレッドのうち一のスレッドの実行により、他のコンピュータからのデータの受信要求を前記コンピュータが備える通信インタフェースに発行した後であって、前記複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理が実行されるよりも前に、前記受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、前記完了通知が格納されていない場合には、前記一のスレッドをサスペンド状態に遷移させる第１の処理と、
前記選択処理と、前記選択処理によって選択されたスレッドについて前記キューを確認する確認処理とを実行する第２の処理であって、前記確認処理によって前記キューに前記一のスレッドに対応する前記完了通知が格納されたことを検知した場合、前記受信データを前記一のスレッドに受け渡して前記一のスレッドをサスペンド状態から復帰させる、前記第２の処理と、
を実行する情報処理方法。
【請求項７】
コンピュータに、
複数のスレッドのうち一のスレッドの実行により、他のコンピュータからのデータの受信要求を前記コンピュータが備える通信インタフェースに発行した後であって、前記複数のスレッドのうちサスペンド状態でないスレッドの中から次に実行させるスレッドを選択する選択処理が実行されるよりも前に、前記受信要求に対応する受信データを受信したことを示す完了通知がキューに格納されたかを確認し、前記完了通知が格納されていない場合には、前記一のスレッドをサスペンド状態に遷移させる第１の処理と、
前記選択処理と、前記選択処理によって選択されたスレッドについて前記キューを確認する確認処理とを実行する第２の処理であって、前記確認処理によって前記キューに前記一のスレッドに対応する前記完了通知が格納されたことを検知した場合、前記受信データを前記一のスレッドに受け渡して前記一のスレッドをサスペンド状態から復帰させる、前記第２の処理と、
を実行させる情報処理プログラム。