マルチスレッドのプログラミング

LWP とスケジューリングクラス

Solaris のカーネルには、ディスパッチ優先順位の 3 つの範囲があります。もっとも高い優先順位の範囲 (100 - 159) は、リアルタイム (RT) スケジューリングクラスに対応しています。中間の優先順位の範囲 (60 - 99) は、システム (SYS) スケジューリングクラスに対応しています。システム (system) クラスは、ユーザープロセスには適用されません。もっとも低い優先順位の範囲 (0 - 59) は、タイムシェアリング (TS)、対話型 (IA)、公平配分 (FSS)、および固定優先順位 (FX) スケジューリングクラスで共有されます。

スケジューリングクラスは、LWP ごとに管理されます。プロセスが生成されると、そのプロセスの初期 LWP は、親プロセスのスケジューリングクラスと作成元の LWP の優先順位を継承します。スレッドが生成されていく過程で、関連 LWP はこのスケジューリングクラスと優先順位を継承します。

スレッドは、関連付けられている LWP と同じスケジューリングクラスおよび優先順位を持ちます。プロセス内の各 LWP は、カーネルから参照される固有のスケジューリングクラスおよび優先順位を持つことができます。

同期オブジェクトへの競合は、スレッドの優先順位によって調節されます。デフォルトでは、LWP はタイムシェアクラスです。計算が大きな比率を占めるマルチスレッドの場合、スレッドの優先順位はあまり役立ちません。MT ライブラリを使って頻繁に同期を行うマルチスレッドアプリケーションでは、スレッドの優先順位はより意味を持ちます。

スケジューリングクラスは、priocntl(2) によって設定されます。最初の 2 つの引数で、この設定の適用範囲を呼び出し側の LWP に限定したり、1 つ以上のプロセスのすべての LWP にしたりすることが可能です。3 番目の引数はコマンドで、次のいずれかのコマンドを指定できます。()

LWP のユーザーレベルの優先順位は、そのディスパッチ優先順位ではなく、そのクラス内の優先順位です。この優先順位は、priocntl() システムコールのアプリケーションによる場合を除き、時間が経っても変更されることはありません。カーネルは、LWP のディスパッチ優先順位を、そのスケジューリングクラス、そのクラス内での優先順位、さらには最近使用された CPU 時間などのほかの要因に基づいて決定します。

タイムシェアスケジューリング

タイムシェアスケジューリングは、プロセッサリソースをタイムシェアリング (TS) および対話型 (IA) スケジューリングクラス内の LWP の間で公平に配分しようとします。

priocntl(2) の呼び出しは、1 つ以上のプロセスまたは LWP のクラス優先順位を設定します。タイムシェアクラスの優先順位の標準の範囲は -60 - +60 です。この値が大きいほど、カーネルのディスパッチ優先順位は高くなります。タイムシェアクラスのデフォルトの優先順位は 0 です。

プロセスに対する nice 値の古い概念 (nice 値が小さいほど高い優先順位を示す) は、TS、IA、および FSS のすべてのスケジューリングクラスのために維持されています。古い nice ベースの setpriority(3C)nice(2) のインタフェースは、nice 値を優先順位の値に対応させることによって引き続き動作します。nice 値を設定すると優先順位が変更され、その逆も同様です。nice 値の範囲は -20 - +20 です。0 の nice 値が 0 の優先順位に対応し、-20 の nice 値が +60 の優先順位に対応します。

タイムシェアクラスの LWP のディスパッチ優先順位は、LWP のその時点での CPU 使用率と、その LWP のクラス優先順位から計算されます。タイムシェアスケジューラにとって、クラス優先順位は、LWP 間の相対的な優先順位を表します。

LWP のクラス優先順位が低いほど、その LWP に配分される CPU 時間は少なくなりますが 0 になることはありません。多くの CPU 時間をすでに消費している LWP は、CPU 時間をほとんど (あるいは、まったく) 消費していない LWP よりもディスパッチ優先順位が下げられます。

リアルタイムスケジューリング

リアルタイムクラス (RT) は、プロセス全体、または単一プロセス内の 1 つ以上の LWP に適用できます。リアルタイムクラスを使用するには、スーパーユーザー特権が必要です。

リアルタイムクラスの優先順位の標準の範囲は 0 - 59 です。リアルタイムクラス内の LWP のディスパッチ優先順位は、そのクラス優先順位プラス 100 に固定されています。

スケジューラは、もっとも高い優先順位を持つリアルタイムクラスの LWP をディスパッチします。もっとも優先順位の高いリアルタイム LWP は、優先順位の高い LWP が実行可能になると、優先順位の低いほうの LWP を横取りします。横取りされた LWP は、レベルキューの先頭に配置されます。

リアルタイム LWP は、LWP が横取りされたり、LWP が一時停止したり、リアルタイム優先順位が変更されたりしないかぎり、プロセッサを制御し続けます。リアルタイムクラスの LWP には、タイムシェアクラスのプロセスよりも絶対的に高い優先順位が与えられます。

新しく生成された LWP は、親プロセスまたは親 LWP のスケジューリングクラスを継承します。リアルタイムクラスの LWP は、親のタイムスライス (リソース割り当て時間) を有限または無限指定に関係なく継承します。

有限タイムスライスを指定された LWP が実行を停止するのは、LWP が終了するか、入出力イベントでブロックされるか、より優先順位の高い実行可能なリアルタイムプロセスによって横取りされるか、タイムスライスが期限切れになったときだけです。

無限タイムスライスを持つ LWP は、LWP が終了するか、ブロックされるか、または横取りされるまで実行されます。

公平配分スケジューリング

公平配分スケジューラ (FSS) スケジューリングクラスでは、配分に基づいて CPU 時間を割り当てることができます。

公平配分スケジューラクラスの優先順位の標準の範囲は -60 - 60 です。この範囲は、スケジューラによって、TS および IA スケジューリングクラスと同じ範囲 (0 - 59) のディスパッチ優先順位に対応付けされます。プロセス内の LWP は、すべて同じスケジューリングクラスで実行する必要があります。FSS クラスでは、プロセス全体ではなく、個々の LWP のスケジュールを設定します。FSS および TS/IA のクラスを同時に使用すると、どちらのクラスも予期しないスケジュールで動作することがあります。

TS/IA と FSS のスケジューリングクラスプロセスが、同じ CPU を奪い合うことはありません。複数のプロセッサセットを使用する場合、TS/IP と FSS を同一システム内に混在させることができます。ただし、各プロセッサセット内のプロセスはすべて、TS/IA または FSS のどちらかのスケジューリングクラスでなければなりません。

固定優先順位スケジューリング

固定優先順位のスケジューリングクラス (FX) は、リソースの消費量とは無関係に、優先順位および時間量に固定値を割り当てます。プロセスの優先順位は、そのプロセス自体、または適切な特権が割り当てられたほかのプロセスだけが変更できます。FX については、priocntl(1) および dispadmin (1M) のマニュアルページを参照してください。

固定優先順位スケジューラクラスの優先順位の標準の範囲は 0 - 60 です。この範囲は、スケジューラによって、TS および IA スケジューリングクラスと同じ範囲 (0 - 59) のディスパッチ優先順位に対応付けされます。