discard

指定された投機IDで特定される投機バッファを破棄します。

void discard(int id)

discard関数を使用すると、DTraceは指定された投機ID (id)で指定された投機バッファを破棄します。

投機バッファを破棄すると、その内容も破棄されます。投機がdiscardをコールしたCPU上でのみアクティブになっていた場合は、バッファをそのままspeculationコールで使用できます。投機が複数のCPUでアクティブになっている場合、破棄されたバッファはdiscardをコールした後しばらくしてから、次のspeculationに使用できます。1つのCPUのdiscardから、後の投機で使用可能になるバッファまでの時間の長さは、クリーニング・レートで指定される時間より長くないことが保証されます。speculationをコールしたときに、すべての投機バッファが破棄中またはコミット中のために使用可能なバッファがない場合、dtraceは次のようなメッセージを生成します:

dtrace: 905 failed speculations (available buffer(s) still busy)

投機バッファ数やクリーニング・レートをチューニングすれば、すべてのバッファが同時に使用不可になるのを防ぐことができます。

例7-15 投機の使用方法

次の例は、投機の使用方法を示しています。投機の正しい動作には、すべての投機関数が一緒に使用されている必要があります。

投機はsyscall::open:entryプローブに対して作成して、投機のIDはスレッド・ローカル変数にアタッチします。open()システム・コールの最初の引数は、printf関数を使用して投機バッファにトレースされます。

syscall::open:returnプローブには、さらに3つの節が含まれています。それらの節の最初で、投機バッファにerrnoをトレースします。2番目の節の述語では、ゼロ以外のerrno値をフィルタ処理して、投機バッファをコミットします。3番目の節の述語では、ゼロのerrno値をフィルタ処理して、投機バッファを破棄します。

プログラムの出力は主データ・バッファに返されるため、open()システム・コールが失敗すると、プログラムは実質的にファイル名とエラー番号を返します。このコールが失敗しない場合は、投機バッファにトレースされた情報が破棄されます。

syscall::open:entry
{
  /*
   * The call to speculation() creates a new speculation. If this fails,
   * dtrace will generate an error message indicating the reason for
   * the failed speculation(), but subsequent speculative tracing will be
   * silently discarded.
   */
  self->spec = speculation();
  speculate(self->spec);

  /*
   * Because this printf() follows the speculate(), it is being
   * speculatively traced; it will only appear in the primary data buffer if the
   * speculation is subsequently committed.
   */
  printf("%s", copyinstr(arg0));
}

syscall::open:return
/self->spec/
{
  /*
   * Trace the errno value into the speculation buffer.
   */
  speculate(self->spec);
  trace(errno);
}

syscall::open:return
/self->spec && errno != 0/
{
  /*
   * If errno is non-zero, commit the speculation.
   */
  commit(self->spec);
  self->spec = 0;
}

syscall::open:return
/self->spec && errno == 0/
{
  /*
   * If errno is not set, discard the speculation.
   */
  discard(self->spec);
  self->spec = 0;
}