.. embProc 組み込みプロシージャの一覧 ========================== 組み込みプロシージャは、コンパイラが内蔵しているプロシージャで、必要に応じインライン展開されたり、サブルーチンコールとしてコードジェネレーションされるものです。 組み込みプロシージャは単独の文としての実行のみであり、式の中に現れてはいけません。組み込みプロシージャの中には変数を引数として値を返せるものや、コンパイラ既定変数 _emb_result_ を介して値を返せるものもあります。 なお、組み込みインラインプロシージャは、コンパイル時に引数を評価してしまうので、通常の関数と異なり、引数に式はとれません。単純変数もしくは定数のみを引数にとることができます。 その代りスタック等を消費せず、高速に処理が可能です。 実行制御 -------- **exit_success()** 成功番地へ飛び、実行を終了します。 0番のリーダーコアがこのインラインプロシージャを実行するとシステム全体が停止しますが、他のコアがこの命令を実行しても そのコアの繰り返し待ちループに遷移するだけで、他のコアには直接影響しません。(他コアと通信している最中に 実行してしまうと他コアが無限ループに陥るかもしれないので注意してください) **exit_failure()** 不成功番地へ飛び、実行を終了します。 0番のリーダーコアについても、0番以外のコアについても、このインラインプロシージャを呼び出すとシステム全体が停止します。 **ccb_read(コア名, CCB番号, スカラー変数名)** CCB(コア・コントロール・ブロック)から値をスカラー変数に読み込みます。 コア名として __this を使用すると自コアの値を読み出すことができます。 なお、CCB番号は0から15までの値を定数もしくはパラメータとして与えます。 **ccb_write(コア名, CCB番号, スカラー変数名)** スカラー変数からCCB(コア・コントロール・ブロック)に値を書き込みます。 コア名として __this を使用すると自コアのCCBに書き込むことができます。 自コアのCCBへの書き込みは iteration部内の任意の位置で書き込むことができます。 他コアのCCBへの書き込みは通常行ってはなりません。 他コアのCCBへの書き込みは、マスターコアが、他コアが自身のCCBへのアクセスをしていない初期化のタイミングで行う必要があります。 なお、CCB番号は0から15までの値を定数もしくはパラメータとして与えます。 **setup_interrupt** 各コアの割り込みレベルの設定など、割り込みを受け付けるために必要な設定を行います。 割り込みをイネーブルにする前に各コアの初期化コード中で実行しておく必要があります。 実機用モードの場合、コンパイラが自動生成するので、通常は記述する必要はありません。 **enable_interrupt** このインラインプロシージャを実行するコアを割り込みイネーブル状態とします。 実機用モードの場合、コンパイラが割り込み制御を自動生成します。 disable_interrputプロシージャを使って明示的に割り込まれないセクションを作った場合の復帰の場合に利用します。 **disable_interrupt** このインラインプロシージャを実行するコアを割り込みディスエーブル状態とします。 実機用モードにコンパイルされた場合、割り込みが許可されていないとiteration部は実行されません。 **init_fifo()** このインラインプロシージャを実行するコアのFIFOチャネルをFIFOセクションの定義に基づき初期化します。 FIFOによりコア間通信を行うのに先立って行っておく必要があります。 **join_all(タイムアウト値)** リーダーコアであるコア0で実行されるべき組み込みプロシージャです。コア0以外の全コアが実行状態から抜けるまで待つための組み込みプロシージャです。 このプロシージャを呼び出すことにより、コア0以外のコアがまだ実行中にコア0を終了させてしまうことを防ぐことができます。 ISIM上ではコア0の終了により、全システムが停止するので、実行途中で打ち切られることになります。 FPGA/RTL上では実行は打ち切らませんが、コア0は最後に待ち状態にする方がよいでしょう。 なお、タイムアウト値を引数としてとり、この値を超えると実行中のコアがあっても戻ります。 その際、全コアが終了していればコンパイラ既定変数 _emb_result_ に真(1)が入っています。そうでなければ偽(0)です。 ISIM上の入出力 -------------- **isim_out$XX(arg)** コンパイラが内蔵するISIM実行結果の可視化機構を使用し、変数の値などを出力するためのインラインプロシージャを生成します。 展開されるインラインプロシージャは、すべての実行環境で動作可能ではありますが、意味を持つのはコンパイラの制御の下でISIM上で実行した場合のみです。 コンパイラの制御の外でISIMで実行した場合には、変数値の出力等は観測できません。 ISIM用以外のターゲットに対してコンパイルするソースにこのプロシージャが含まれる場合、ウォーニングが発生し、コードは生成されません。 なお、このインラインプロシージャは仮想の出力バッファに値をセットするのみで実際の画面出力は行いません。 XXには以下のサブコマンドが入ります * STRING 文字列リテラル引数を出力バッファに転送します。 * I8 スカラー変数を引数にとり、1バイトの大きさの整数として符号付き10進数として出力バッファに転送します。 * I16 スカラー変数を引数にとり、2バイトの大きさの整数として符号付き10進数として出力バッファに転送します。 * I32 スカラー変数を引数にとり、4バイトの大きさの整数として符号付き10進数として出力バッファに転送します。 * U8 スカラー変数を引数にとり、1バイトの大きさの整数として符号無し16進数として出力バッファに転送します。 * U16 スカラー変数を引数にとり、2バイトの大きさの整数として符号無し16進数として出力バッファに転送します。 * U32 スカラー変数を引数にとり、4バイトの大きさの整数として符号無し16進数として出力バッファに転送します。 * F16Q6 スカラー変数を引数にとり、2バイトの大きさの16Q6形式の固定小数点数として出力バッファに転送します。 * F16Q8 スカラー変数を引数にとり、2バイトの大きさの16Q8形式の固定小数点数として出力バッファに転送します。 * F16Q10 スカラー変数を引数にとり、2バイトの大きさの16Q10形式の固定小数点数として出力バッファに転送します。 * F16Q12 スカラー変数を引数にとり、2バイトの大きさの16Q12形式の固定小数点数として出力バッファに転送します。 * F32Q16 スカラー変数を引数にとり、4バイトの大きさの32Q16形式の固定小数点数として出力バッファに転送します。 * Q8LP スカラー変数を引数にとり、1バイトの大きさのQ8LP形式の量子化浮動小数点数として出力バッファに転送します。 * VI8 ベクター変数を引数にとり、ベクターの各要素を1バイトの大きさの整数として符号付き10進数として出力バッファに転送します。 * VI16 ベクター変数を引数にとり、ベクターの各要素を2バイトの大きさの整数として符号付き10進数として出力バッファに転送します。 * VI32 ベクター変数を引数にとり、ベクターの各要素を4バイトの大きさの整数として符号付き10進数として出力バッファに転送します。 * VU8 ベクター変数を引数にとり、ベクターの各要素を1バイトの大きさの整数として符号無し16進数として出力バッファに転送します。 * VU16 ベクター変数を引数にとり、ベクターの各要素を1バイトの大きさの整数として符号無し16進数として出力バッファに転送します。 * VU32 ベクター変数を引数にとり、ベクターの各要素を1バイトの大きさの整数として符号無し16進数として出力バッファに転送します。 * VF16Q6 ベクター変数を引数にとり、ベクターの各要素を2バイトの大きさの16Q6形式の固定小数点数として出力バッファに転送します。 * VF16Q8 ベクター変数を引数にとり、ベクターの各要素を2バイトの大きさの16Q8形式の固定小数点数として出力バッファに転送します。 * VF16Q10 ベクター変数を引数にとり、ベクターの各要素を2バイトの大きさの16Q10形式の固定小数点数として出力バッファに転送します。 * VF16Q12 ベクター変数を引数にとり、ベクターの各要素を2バイトの大きさの16Q12形式の固定小数点数として出力バッファに転送します。 * VF32Q16 ベクター変数を引数にとり、ベクターの各要素を4バイトの大きさの32Q16形式の固定小数点数として出力バッファに転送します。 * VQ8LP ベクター変数を引数にとり、ベクターの各要素を1バイトの大きさのQ8LP形式の量子化浮動小数点数として出力バッファに転送します。 Q8LP形式の量子化浮動小数点数として出力する場合、スケールはコンパイラパラメータ __Q8LP_SCALE に定義されている浮動小数文字列、 ゼロ点はコンパイラパラメータ __Q8LP_ZEROPOINT に定義されているゼロ点を表す整数を用いて逆量子化されます。 **isim_write()** isim_outプロシージャにより仮想出力バッファにセットされた値を画面出力します。このプロシージャが意味を持つのはコンパイラの制御の下で ISIM上で実行した場合のみです。ISIM用以外のターゲットに対してコンパイルするソースにこのプロシージャが含まれる場合、ウォーニングが 発生し、コードは生成されません。 仮想バッファは、各コア別に存在し、該当するコア上で実行されるisim_write()に先立つすべてのisim_outで転送された出力が保持されています。 isim_write()プロシージャは、それらすべてを一度に出力します。出力後は該当コアの仮想バッファを空の状態にします。 以下のコードにより、スカラー変数 a に 1 という値が入っていたとすると 「a=1」という出力が画面に対してなされます。 .. code-block:: none isim_out$STRING( "a=" ); isim_out$I8( a ); isim_write(); FPGA(実機)制御 -------------- **fpga_LED(変数)** 実機(FPGA)上でのみ利用可能なデバッグ用プロシージャです。変数に与えられた 0~0xFFまでの1バイトの値をLEDに16進表示します。 ISIM上では警告が生じ、コードは生成されません。 **read_PerfCounter(書き込み可能な変数)** 実機(FPGA)上でのみ利用可能な性能測定用プロシージャです。引数与えられる変数にハード内蔵のパフォーマンスカウンタの生の値を書き込みます。 生データは32ビット値です。 **diff_PerfCounter(基準変数, 書き込み可能な変数)** 実機(FPGA)上でのみ利用可能な性能測定用プロシージャです。第1の引数にはread_PerfCounterで測定期間の先頭で取得した パフォーマンスカウンタ値を与えます。本プロシージャを測定期間の末尾で呼び出すことで、測定期間の時間長さを示す 0~255までの値が第2の変数に書きこまれます。50MHz動作の場合、1単位は82μ秒なので、82μ秒から 約20.9m秒までの時間を計測することができます。この値は8ビット値なので fpga_LED プロシージャでデバッグポートにそのまま 出力して観察することも可能です。 **restart(0または他の値)** 実機(FPGA)上でのみ利用可能なプロシージャです。物理コア0番で、引数に0を与えてこのプロシージャを呼び出すと、 即座に、すべてのコアはInitializeブロックを通る形で再起動されます。ただし、コールドブートルーチンは 通過しませんので、ハードリセットではありません。 物理コア0番以外か、引数に0以外の値を与えると、initializeブロックを通らない形で再起動されます。 **assert_resume** HRUに対して resume信号 をアサートします。実機(FPGA)上でのみ利用可能ですが、通常、コンパイラが自動生成するので、 特別なハード制御の意図がない限りユーザが記述することはありません。 **assert_update** HRUに対して update信号 をアサートします。実機(FPGA)上でのみ利用可能ですが、通常、コンパイラが自動生成するので、 特別なハード制御の意図がない限りユーザが記述することはありません。 **TODO** * ソフトウエア同期用のプロシージャ追加 * HRU/HTU サポート用のプロシージャ追加 変数操作 -------- **inc_selector(スカラー変数, 上限値)** スカラー変数は最初の使用前に0で初期化しておく必要があります。 このプロシージャにより該当のスカラー変数は+1されますが、上限値に到達すると0に戻ります。 **load_vector(ベクタ変数, "ベクタ変数文字列")** 通常、ベクタ変数を右辺に書くとキャッシュされていなければ、即座にキャッシュがアロケートされその変数がロードされます。 しかし、このインラインプロシージャでは、すでにアロケート済の第1の引数のベクタに、文字列として与えられる第2のベクタ変数を ダイレクトにロードすることができます。alloc_vectorコンパイラ・ディレクティブと組み合わせることで無駄なロードなどを 省くことができます。 **save_vector(ベクタ変数, "ベクタ変数文字列", レジスタオフセット)** 通常、ベクタ変数を左辺に書くとそのベクタ変数への書き込みが発生しますが、書き込まれる要素数は右辺のベクタと左辺のベクタの 短い方の長さの全長がセーブされます。このインラインプロシージャでは、レジスタオフセットを指定することでベクタ変数の先頭からオフセット分の レジスタを切り取ってさらに短くしたベクタを"ベクタ変数文字列"の指すベクタ変数に書き込むことができます。 ベクタ変数文字列には通常のベクタ型変数の他、ポインタ変数を指定することも可能です。 キャッシュされていなければ、即座にキャッシュがアロケートされその変数がロードされます。 しかし、このインラインプロシージャでは、すでにアロケート済の第1の引数のベクタに、文字列として与えられる第2のベクタ変数を ダイレクトにロードすることができます。alloc_vectorコンパイラ・ディレクティブと組み合わせることで無駄なロードなどを 省くことができます。 **read_neighbour(ベクタ変数, "ベクタ変数文字列")** 第1の引数には自コアから書き込めるベクタ型変数をとります。このインラインプロシージャは第1のベクタ型変数を書き換えてしまうので 不要なロードを起こさないためにも、第1の引数には通常の大域変数ベクタでなく自コア上でalloc_vectorコンパイラディレクティブにより定義されたベクタ変数 をとった方がよいです。第2の引数には、隣接コア(一つ番号の小さいコア)上でalloc_vectorコンパイラディレクティブにより 定義されたベクタ変数をしめすベクタ変数文字列を与えます。通常、他のコアのレジスタを見ることはできませんが、隣接コアのみ このインラインプロシージャを使用することで値を参照することが可能です。隣接コアから読み取った値は第1のベクタ型変数(のキャッシュ) に代入されます。また、このインラインプロシージャはレジスタ上の操作だけで、第1の引数をメモリに書き戻しません。 (書き戻そうにもalloc_vectorコンパイラディレクティブにより定義されたベクタ変数にはメモリ上の実体はありません。) 必要に応じて大域変数として定義されているベクタ変数に第1のベクタ型変数を代入することで値を保存することができます。 なお、計算に使うだけならば保存の必要はありません。キャッシュされたベクタ変数と異なり、alloc_vectorコンパイラディレクティブにより 宣言されたベクタ変数はパーマネントに存在を続けます。 **use_image(宣言するポインタ変数名, "イメージバッファ名", オフセットバイト数, 画面横幅バイト数, バッファバイトサイズ, 処理単位数)** このインラインプロシージャは画像入出力のためにハードウエアが備えるHTU, HRUにアクセスするため、あるいは、画像処理ソフトウエアを作成する場合の利便性のため コンパイラが生成可能なソフトウエア的イメージバッファにアクセスするためにポインタ変数を初期化します。 このプロシージャで使用を宣言した後は、それらのイメージバッファに通常のベクタ命令でアクセスするようにして読み書きできるようになります。 このインラインプロシージャは、一種のコンパイラ・ディレクティブとしての機能を内包しており第1の引数として与えられる識別子を新たなポインタ変数として宣言します。 ここで宣言されたポインタ変数は、大域変数部で宣言したポインタ変数と同様に大域スコープのポインタとなります。 さらにこのプロシージャは、インラインプロシージャとしてポインタ変数を初期化するための実体コードも同時に生成します。 第2の引数として、現状、以下の4個が定義されているイメージバッファを選択するためのバッファ名文字列をとります。 * IMAGE_BUFFER_A * IMAGE_BUFFER_B * HTU_BUFFER * HRU_BUFFER 上記以外のイメージバッファ名を指定するとエラーとなります。 第3の引数としてバッファ先頭から実際の処理の先頭アドレスまでのオフセットバイト数を与えます。 第4の引数としてイメージの横幅バイト数を与えます。 第5の引数は、イメージバッファとして使用する全体のバイトサイズです。物理的に設定されているサイズ以下であれば小さくすることも可能です。 第6の引数は、処理の最低単位となる1~16のベクタレジスタ長を与えます。1は32バイトを意味しますので、16と設定すると512バイトです。 本プロシージャにより通常はベクタ定義からコンパイラが計算して与えている各種の定数を直接操作することが可能です。 それら定数の値についてコンパイラはチェックをしないので、不正な値を用いると予期しない動作に陥る可能性がありますので注意してください。 **concat_vector(結合先のベクタ変数, 先に結合されるベクタ変数, 後に結合されるベクタ変数)** 第2、第3の引数で指定されるベクタ2個を結合し、第1の引数で指定されるベクタ変数に転送します。 この操作はレジスタ上でのみ行われるので、結合先のベクタをメモリに保存したい場合は、明示的に代入しなければなりません。 通常は、alloc_vectorコンパイラディレクティブによって宣言されたオンレジスタ変数を引数にとって操作を行います。 **concat_vector_sub(結合先のベクタ変数, 先に結合されるベクタ変数, 後に結合されるベクタ変数, レジスタ数即値)** 第2、第3の引数で指定されるベクタ2個を結合し、第1の引数で指定されるベクタ変数に転送しますが、 その際、第4の引数で指定されるレジスタ数だけ、第2のベクタの先頭をスキップします。 転送量は、第1の引数で確保されている量に一致し、まず第2の側を転送した後、空きがあれば第3の側を空きの分だけ転送します。 この操作はレジスタ上でのみ行われるので、結合先のベクタをメモリに保存したい場合は、明示的に代入しなければなりません。 通常は、alloc_vectorコンパイラディレクティブによって宣言されたオンレジスタ変数を引数にとって操作を行います。 **concat_neighbour(結合先のベクタ変数, "先に結合されるベクタ変数を示すベクタ文字列", 先に結合されるベクタ変数の実長, 後に結合されるベクタ変数)** 第2、第3の引数で指定される隣接コア上のオンレジスタのベクタと、第3の引数で指定される自コア上のベクタを第1の引数で指定されるベクタ変数に転送するものです。 この操作はレジスタ上でのみ行われるので、結合先のベクタをメモリに保存したい場合は、明示的に代入しなければなりません。 通常は、alloc_vectorコンパイラディレクティブによって宣言されたオンレジスタ変数を引数にとって操作を行います。 **concat_self(結合先のベクタ変数, "接続方法指定文字列", ベクタ変数)** このインラインプロシージャは"接続方法指定文字列"で指定される方法で、第4の引数で指定されるベクタの一部を複製して長さを拡張したベクタを生成します。 "接続方法指定文字列"で指定できるのは、leftもしくはrightで、leftの場合ベクタの最下位要素を、rightの場合ベクタの最上位要素を1ベクタレジスタ分 複製したベクトルを生成し、結合先のベクタ変数に格納します。 **set_vector(ベクタ変数, "要素幅指定文字列", 操作対象レジスタ番号, 設定値)** ベクタ変数の一部を直接書き換えます。操作対象はレジスタ番号で指定し、操作の幅は要素幅指定文字列で byte もしくは word と指定します。 **unpack_XY$x_y(データ, 下格納先変数, 上格納先変数)** x_yで示されるビットフィールドにもとづいて、32ビットデータをビットフィールド抽出し、下格納先変数, 上格納先変数に格納します。 x, yには1~31までの整数が入ります。xが下、yが上となります。xとyの合計が32を超えた場合は所望の結果が得られません。 **pack_XY$x_y(格納先変数, 下データ, 上データ)** x_yで示されるビットフィールドにもとづいて、下データと上データをパックして格納先変数に書き込みます。 x, yには1~31までの整数が入ります。xが下、yが上となります。xとyの合計が32を超えた場合は所望の結果が得られません。 **unpack_XYZ$x_y_z(データ, 下格納先変数, 中格納先変数, 上格納先変数)** x_y_zで示されるビットフィールドにもとづいて、32ビットデータをビットフィールド抽出し、下、中、上の格納先変数に格納します。 x, y, zには1~31までの整数が入ります。xが下、zが上となります。x,y,zの合計が32を超えた場合は所望の結果が得られません。 **pack_XYZ$x_y_z(格納先変数, 下データ, 中データ, 上データ)** x_y_zで示されるビットフィールドにもとづいて、下、中、上データをパックして格納先変数に書き込みます。 x, y, z には1~31までの整数が入ります。xが下、zが上となります。x,y,zの合計が32を超えた場合は所望の結果が得られません。 **average_XY$x(格納先変数, データ1, データ2)** 32ビットデータの下xビットがX,残りのビットがYであるとして、データ1とデータ2のX、Yそれぞれの平均値を求めて格納先変数に書き込みます。 XYで示されるような座標データ組から中心座標を求めるような場合に使用します。 **add_XY$x(格納先変数, データ1, データ2)** 32ビットデータの下xビットがX,残りのビットがYであるとして、データ1とデータ2のX、Yそれぞれの加算値を求めて格納先変数に書き込みます。 **sub_XY$x(格納先変数, データ1, データ2)** 32ビットデータの下xビットがX,残りのビットがYであるとして、データ1からデータ2を引いた値を求めて格納先変数に書き込みます。 **dist2_XY$x(格納先変数, データ1, データ2)** 32ビットデータの下xビットがX,残りのビットがYであるとして、データ1とデータ2のX,Yの差分二乗和を求めて格納先変数に書き込みます。 **read_mem(格納先変数, 大域変数, インデックス)** あるメモリ領域の最下位アドレスにアロケートされた大域変数をベースポインタとして、インデックス値(*4倍されます)を加えたメモリの32ビットデータを読み出して格納先変数にセットします。外部プログラムのデータ構造などにアクセスする場合に利用します。 **write_mem(データ保持変数, 大域変数, インデックス)** あるメモリ領域の最下位アドレスにアロケートされた大域変数をベースポインタとして、インデックス値(*4倍されます)を加えたメモリへ、データ保持変数が持っている32ビットデータを書き込みます。外部プログラムのデータ構造などにアクセスする場合に利用します。 **read_adr(格納先変数, アドレス変数, インデックス, オフセット)** あるメモリ領域の最下位アドレスを指しているアドレス変数(byNameキーワードで定義された引数)ををベースポインタとして、インデックス値(*4倍されます)およびオフセット値(*4倍されます)を加えたメモリの32ビットデータを読み出して格納先変数にセットします。外部プログラムのデータ構造などにアクセスする場合に利用します。 **write_adr(データ保持変数, アドレス変数, インデックス, オフセット)** あるメモリ領域の最下位アドレスを指しているアドレス変数(byNameキーワードで定義された引数)ををベースポインタとして、インデックス値(*4倍されます)およびオフセット値(*4倍されます)を加えたメモリへ、データ保持変数が持っている32ビットデータを書き込みます。 **set_pointer(転送先ポインタ変数, 転送元大域変数, 上限サイズ, ステップサイズ)** 転送先のポインタ変数に、転送元大域変数が保持する値をメモリアドレスとしてセットします。 転送元大域変数がポインタ変数であれば、ポインタ変数はメモリアドレスを保持しているので問題ありませんが、 それ以外の大域変数の場合、変数が保持している値が正しいメモリアドレスであることはプログラマの責任となります。 また、ポインタ操作時の上限サイズ、ステップサイズ(いずれもバイト単位)も直接セットすることができます。 ベクタプロパティ抽出子によるポインタ変数の初期化のように1度だけしか許されないことはなく、同じ転送先ポインタ に何度もセットすることが可能です。しかし、ベクタプロパティ抽出子による初期化はベクタ型変数のアドレスやサイズ を正しくセットするので不正な操作は起こり得ないのに対し、set_pointerは直接ポインタ変数に値を代入してしまうので 不正な操作を引き起こす可能性があります。 インラインアセンブラ関係 ------------------------ **bank_set(アロケート済ベクタ変数1, アロケート済ベクタ変数2)** アロケート済ベクタ変数1の存在するバンクをデスティネーション、アロケート済ベクタ変数2の存在するバンクをソースとする BSアセンブラ命令を配置します。次のinline_asm組み込みプロシージャで直接アセンブラ命令を出力する際に レジスタを確定させる意味を持ちます。 **inline_asm("アセンブラ命令文字列")** 引数の文字列をそのままアセンブラ出力に送ります。 アセンブラ命令としてのチェックはありません。問題があればアセンブルするときにエラーが発生します。 主としてテスト用です。 従来式同期関係 -------------- 以下にセマフォ同期、バリア同期のためのプロシージャを列挙しますが、これらの使用は非推奨です。 FIFOを使ったZOMP同期(with文で実現される)が使用できるのであれば、そちらを優先的に使用してください。 **createSem(ポインタ変数, 即値)** 指定されたポインタ変数をセマフォ変数として設定します。以降、該当のポインタ変数を通常の目的で使用してはいけません。 セマフォのカウンタを即値の値で初期化します。 セマフォ変数の初期化は、全プロセスが該当のセマフォ変数を使い始めていないことを保証できるタイミングで行わねばなりません。 リーダコアの初期化中に行うことを推奨します。 **waitSem(セマフォ変数, 即値)** 指定されたセマフォ変数カウンタが第2引数で与えられる即値と等しいか大きい場合、セマフォ変数カウンタから第2引数を減じて戻ります。 小さかった場合は、条件をみたすまでウエイトします。 **signalSem(セマフォ変数, 即値)** 指定されたセマフォ変数カウンタに第2引数で与えられる即値を加えます。 **createBarrier(ポインタ変数, 即値)** 指定されたポインタ変数をバリア変数として設定します。以降、該当のポインタ変数を通常の目的で使用してはいけません。 バリア変数の上限値を第2引数で与えられる数値で、現在値を0で初期化します。 複数のコア間でバリア同期を行う場合に、待ち合わせるコア数を上限として与えて初期化します。 **waitBarrier(バリア変数)** 指定されたバリア変数の現在値が上限値と等しいか大きい場合は即座に戻ります。 小さかった場合は、条件をみたすまでウエイトします。 内部で待っているコア数をカウントしており、待ち合わせの最後のコアがwaitから抜けると現在値カウンタが0に再初期化されます。 自コアが最後のコアかどうかはわからないので、バリア変数を使いまわす場合は、別のバリアと交互に使うことを推奨します。 **signalBarrier(バリア変数)** 指定されたバリア変数の現在値に1を加えます。