Oracle Solaris Studio 12.2: C ユーザーガイド

3.9 メモリーバリアー組み込み関数

コンパイラには、SPARC プロセッサと x86 プロセッサ用のさまざまなメモリーバリアー組み込み関数を定義するヘッダーファイル mbarrier.h が用意されています。これらの組み込み関数は、開発者が独自の同期プリミティブを使用してマルチスレッドコードを記述するために使用できます。これらの組み込み関数が特定の状況で必要かどうか、また、いつ必要かを判断するには、ご使用のプロセッサのドキュメントを参照することをお勧めします。

mbarrier.h によりサポートされるメモリーオーダリング組み込み関数

__compiler_barrier() 組み込み関数を除くすべてのバリアー組み込み関数は、メモリーオーダリング組み込み関数を生成します。x86 では、mfencesfence、または lfence 組み込み関数で、SPARC プラットフォームでは membar 組み込み関数です。

__compiler_barrier() 組み込み関数は、命令を生成せず、代わりに今後メモリー操作を開始する前にそれまでのメモリー操作をすべて完了する必要があることをコンパイラに通知します。この実際の結果として、ローカルでないすべての変数、および static 記憶クラス指定子を持つローカル変数が、バリアー前のメモリーに再度格納されてバリアー後に再ロードされるため、コンパイラではバリアー前のメモリー操作とバリアー後のメモリー操作が混在することはありません。ほかのすべてのバリアーには、__compiler_barrier() 組み込み関数の動作が暗黙的に含まれています。

たとえば、次のコードでは、__compiler_barrier() 組み込み関数が存在しているためコンパイラによる 2 つのループのマージが止まります。


#include "mbarrier.h"
int thread_start[16];
void start_work()
{
/* Start all threads */
   for (int i=0; i<8; i++)
   {
     thread_start[i]=1;
   }
   __compiler_barrier();
/* Wait for all threads to complete */
   for (int i=0; i<8; i++)
   {
      while (thread_start[i]==1){}
   }
}