プログラミングインタフェース

インポート側のメモリーセグメント操作

インポート側の操作には、次の操作が含まれます。

接続操作は、RSM インポートセグメントを作成して、エクスポートされたセグメントとの論理的な接続を形成するときに使用します。

インポートされたセグメントメモリーへのアクセスは、次の 3 つのインタフェースカテゴリによって実現されます。

メモリーセグメントの接続と切断

セグメントへの接続

int rsm_memseg_import_connect( rsmapi_controller_handle_t controller, rsm_node_id_t node_id, rsm_memseg_id_t segment_id, rsm_permission_t perm, rsm_memseg_import_handle_t *im_memseg );

この関数は、指定されたアクセス権 perm を使用してリモートノード node_id 上にある セグメント segment_id に接続します。セグメントに接続した後、この関数はセグメントハンドルを返します。

引数 perm は、当該接続のインポータによって要求されるアクセスモードを指定します。接続を確立するとき、エクスポータが指定したアクセス権とインポータが使用するアクセスモード、ユーザー要求されるアクセスモードが無効な場合、接続要求は拒否されます。なお、perm 引数は次の 8 進数値に制限されます。

0400

読み取りモード

0200

書き込みモード

0600

読み取りおよび書き込みモード

指定されたコントローラは、セグメントのエクスポートに使用されるコントローラと物理的に接続されている必要があります。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_CTLR_HNDL

コントローラハンドルが無効です。

RSMERR_CTLR_NOT_PRESENT

コントローラが存在しません。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_PERM_DENIED

アクセス権がありません。

RSMERR_SEG_NOT_PUBLISHED_TO_NODE

セグメントがノードに公開されていません。

RSMERR_SEG_NOT_PUBLISHED

セグメントが公開されていません。

RSMERR_REMOTE_NODE_UNREACHABLE

リモートノードに到達できません。

RSMERR_INTERRUPTED

接続が割り込まれました。

RSMERR_INSUFFICIENT_MEM

メモリーが不足しています。

RSMERR_INSUFFICIENT_RESOURCES

リソースが不足しています。

RSMERR_BAD_ADDR

アドレスが不正です。

セグメントからの切断

int rsm_memseg_import_disconnect(rsm_memseg_import_handle_t im_memseg);

この関数はセグメントを切断します。セグメントを切断した後、この関数はセグメントのリソースを解放します。切断されたセグメントへの既存のマッピングはすべて削除されます。ハンドル im_memseg は解放されます。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_SEG_STILL_MAPPED

セグメントがマッピングされたままになっています。

RSMERR_POLLFD_IN_USE

pollfd は使用中です。

メモリーアクセスプリミティブ

次のインタフェースは、8 ビットから64 ビットまでのデータを転送するためのメカニズムを提供します。get インタフェースは、プロセスがメモリー上の連続するデータから読みとるべき、与えられたサイズのデータ項目の数を示すリピートカウント (rep_cnt) を使用します。メモリー上の連続するデータは、インポートされたセグメントのオフセット (offset) から始まります。データは datap から始まる連続する場所に書き込まれます。put インタフェースは、リピートカウント (rep_cnt) を使用して、プロセスが読み取るべきデータ項目数を指定します。連続する場所は、datap から始まります。データは次に、インポートされたセグメントの offset から始まる連続する場所に書き込まれます。

これらのインタフェースはまた、読み取り元と書き込み先のエンディアン特性に互換性がない場合にバイトを交換するメカニズムも提供します。

関数のプロトタイプ:

int rsm_memseg_import_get8(rsm_memseg_import_handle_t im_memseg, off_t offset, uint8_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_get16(rsm_memseg_import_handle_t im_memseg, off_t offset, uint16_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_get32(rsm_memseg_import_handle_t im_memseg, off_t offset, uint32_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_get64(rsm_memseg_import_handle_t im_memseg, off_t offset, uint64_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_put8(rsm_memseg_import_handle_t im_memseg, off_t offset, uint8_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_put16(rsm_memseg_import_handle_t im_memseg, off_t offset, uint16_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_put32(rsm_memseg_import_handle_t im_memseg, off_t offset, uint32_t *datap, ulong_t rep_cnt);
int rsm_memseg_import_put64(rsm_memseg_import_handle_t im_memseg, off_t offset, uint64_t *datap, ulong_t rep_cnt);

次のインタフェースは、セグメントアクセス操作がサポートするデータよりも大きなデータを転送するときに使用します。

セグメントの書き込み

int rsm_memseg_import_put( rsm_memseg_import_handle_t im_memseg, off_t offset , void *src_addr, size_t length );

この関数は、src_addrlength で指定されたローカルメモリーから、対応するインポートされたセグメントのハンドルとオフセットで指定された場所にデータを書き込みます。

セグメントの読み取り

int rsm_memseg_import_get( rsm_memseg_import_handle_t im_memseg, off_t offset , void *dst_addr, size_t length );

この関数は rsm_memseg_import_put() と似ていますが、データはインポートされたセグメントから dest_vec で定義されたローカル領域に移動します。

put ルーチンと get ルーチンは、引数 offset で指定したバイトオフセット位置から、指定された量のデータを書き込みまたは読み込みます。これらのルーチンはセグメントのベースから開始します。オフセットは適切な境界に整列している必要があります。たとえば、rsm_memseg_import_get64() の場合、offsetdatap はダブルワード境界に整列している必要がありますが、rsm_memseg_import_put32() の場合、offset はワード境界に整列している必要があります。

デフォルトでは、セグメントのバリアモード属性は暗黙的 (implicit) です。暗黙的なバリアモードは、操作から戻ってきたときにはデータ転送が完了または失敗していると呼び出し元が仮定していることを意味します。デフォルトのバリアモードは暗黙的であるため、アプリケーションはバリアを初期化する必要があります。デフォルトのバリアモードを使用するとき、put ルーチンまたは get ルーチンを呼び出す前に、アプリケーションは rsm_memseg_import_init_barrier() 関数を使用してバリアを初期化します。明示的な操作モードを使用するには、呼び出し元はバリア操作を使用して転送を強制的に完了させる必要があります。転送を強制的に完了させた後、結果としてエラーが発生したかどうかを判断する必要があります。


注 –

オフセットを rsm_memseg_import_map() ルーチンに渡すことによって、インポートセグメントは部分的にマッピングできます。インポートセグメントを部分的にマッピングする場合、put ルーチンまたは get ルーチンの offset 引数はセグメントのベースからです。ユーザーは、正しいバイトオフセットが put ルーチンまたは get ルーチンに渡されていることを確認する必要があります。


戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_ADDR

アドレスが不正です。

RSMERR_BAD_MEM_ALIGNMENT

メモリー整列が無効です。

RSMERR_BAD_OFFSET

オフセットが無効です。

RSMERR_BAD_LENGTH

長さが無効です。

RSMERR_PERM_DENIED

アクセス権がありません。

RSMERR_BARRIER_UNINITIALIZED

バリアが初期化されていません。

RSMERR_BARRIER_FAILURE

入出力完了エラー

RSMERR_CONN_ABORTED

接続が中断されました。

RSMERR_INSUFFICIENT_RESOURCES

リソースが不足しています。

Scatter-Gather アクセス

rsm_memseg_import_putv()rsm_memseg_import_getv () 関数を使用すると、単一の読み取り元アドレスや単一の書き込み先アドレスではなく、入出力要求のリストを使用できます。

関数のプロトタイプ:

int rsm_memseg_import_putv(rsm_scat_gath_t *sg_io);
int rsm_memseg_import_getv(rsm_scat_gath_t *sg_io);

Scatter-Gather リスト (sg_io) の入出力ベクトル構成要素を使用すると、ローカル仮想アドレスまたは local_memory_handles を指定できます。ハンドルはローカルアドレス範囲を繰り返して使用するための効率的な方法です。割り当てられたシステムリソース (ロックダウンされたローカルメモリーなど) はハンドルが解放されるまで保持されます。ハンドルをサポートする関数は rsm_create_localmemory_handle()rsm_free_localmemory_handle() です。

仮想アドレスやハンドルは、ベクトルに集めて、単一のリモートセグメントに書き込むことができます。この結果はまた、単一のリモートセグメントから読み取って、仮想アドレスまたはハンドルのベクトルに分散できます。

ベクトル全体の入出力は関数が返る前に初期化されます。インポートセグメントのバリアモード属性は、関数が返る前に入出力が完了しているかどうかを判断します。バリアモード属性を implicit (暗黙的) に設定すると、ベクトルに入った順番でデータ転送が完了することが保証されます。リストの各エントリは、暗黙的なバリアの開く操作と閉じる操作によって囲まれます。エラーが検出された場合、ベクトルの入出力は中断され、関数はすぐに返ります。残りのカウントは、入出力が完了または初期化されなかったエントリの数を示します。

putv 操作または getv 操作が正常に完了した場合に通知イベントをターゲットセグメントに送信することを指定できます。通知イベントを送信することを指定するには、rsm_scat_gath_t 構造体の flags エントリに RSM_IMPLICIT_SIGPOST 値を指定します。また、flags エントリに RSM_SIGPOST_NO_ACCUMULATE を指定しておくと、RSM_IMPLICIT_SIGPOST が設定されたときに、この値がシグナルポスト操作に渡されます。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SGIO

Scatter-Gather 構造体ポインタが無効です。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_CTLR_HNDL

コントローラハンドルが無効です。

RSMERR_BAD_ADDR

アドレスが不正です。

RSMERR_BAD_OFFSET

オフセットが無効です。

RSMERR_BAD_LENGTH

長さが無効です。

RSMERR_PERM_DENIED

アクセス権がありません。

RSMERR_BARRIER_FAILURE

入出力完了エラー

RSMERR_CONN_ABORTED

接続が中断されました。

RSMERR_INSUFFICIENT_RESOURCES

リソースが不足しています。

RSMERR_INTERRUPTED

シグナルによって操作が割り込まれました。

ローカルハンドルの取得

int rsm_create_localmemory_handle(rsmapi_controller_handle_t cntrl_handle, rsm_localmemory_handle_t *local_handle, caddr_t local_vaddr , size_t length);

この関数は、後続の putv または getv への呼び出しの入出力ベクトルで使用するためのローカルハンドルを取得します。ロックダウンの可能性があるので、メモリーがローカルハンドルによってスパンされている場合は特に、可能な限りハンドルを解放して、システムリソースを節約してください。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_CTLR_HNDL

コントローラハンドルが無効です。

RSMERR_BAD_LOCALMEM_HNDL

ローカルメモリーハンドルが無効です。

RSMERR_BAD_LENGTH

長さが無効です。

RSMERR_BAD_ADDR

アドレスが無効です。

RSMERR_INSUFFICIENT_MEM

メモリーが不足しています。

ローカルハンドルの解放

rsm_free_localmemory_handle( rsmapi_controller_handle_t cntrl_handle, rsm_localmemory_handle_t handle);

この関数は、ローカルハンドルに関連するシステムリソースを解放します。プロセスが終了するときにはプロセスに属するすべてのハンドルが解放されますが、この関数を呼び出すことでシステムリソースを節約できます。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_CTLR_HNDL

コントローラハンドルが無効です。

RSMERR_BAD_LOCALMEM_HNDL

ローカルメモリーハンドルが無効です。

次の例に、プライマリデータ構造体の定義を示します。


例 2–1 プライマリデータ構造体

typedef void *rsm_localmemory_handle_t
typedef struct {
   ulong_t	io_request_count;	number of rsm_iovec_t entries
   ulong_t	io_residual_count;	rsm_iovec_t entries not completed 

   in	flags;      
   rsm_memseg_import_handle_t		remote_handle; opaque handle for
                                                    import segment
   rsm_iovec_t							*iovec;		  pointer to
                                                    array of io_vec_t
} rsm_scat_gath_t;

typedef struct {
   int	io_type;		HANDLE or VA_IMMEDIATE
   union {
        rsm_localmemory_handle_t	handle;			used with HANDLE
        caddr_t						virtual_addr;		used with
                                                         VA_IMMEDIATE
    } local;
   size_t          local_offset;		       offset from handle base vaddr
   size_t          import_segment_offset;    offset from segment base vaddr
   size_t          transfer_length; 
} rsm_iovec_t; 

セグメントのマッピング

マッピング操作は、ネイティブなアーキテクチャの相互接続 (Dolphin-SCI や NewLink など) だけで利用できます。セグメントをマッピングすることによって CPU メモリー操作がそのセグメントにアクセスできるようになるので、メモリーアクセスプリミティブを呼び出すオーバーヘッドを省くことができます。

インポートされたセグメントのマッピング

int rsm_memseg_import_map(rsm_memseg_import_handle_t im_memseg, void **address, rsm_attribute_t attr, rsm_permission_t perm, off_t offset, size_t length);

この関数は、インポートされたセグメントを呼び出し元のアドレス空間にマッピングします。属性 RSM_MAP_FIXED が指定されている場合、この関数は **address に指定された値にあるセグメントをマッピングします。

typedef enum {
RSM_MAP_NONE = 0x0,   /* システムは使用できる仮想アドレスを選択する */
RSM_MAP_FIXED = 0x1,  /* セグメントを指定された仮想アドレスにマッピングする */
} rsm_map_attr_t;

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_ADDR

アドレスが無効です。

RSMERR_BAD_LENGTH

長さが無効です。

RSMERR_BAD_OFFSET

オフセットが無効です。

RSMERR_BAD_PERMS

アクセス権がありません。

RSMERR_SEG_ALREADY_MAPPED

セグメントはすでにマッピングされています。

RSMERR_SEG_NOT_CONNECTED

セグメントは接続されていません。

RSMERR_CONN_ABORTED

接続が中断されました。

RSMERR_MAP_FAILED

マッピング中にエラーが発生しました。

RSMERR_BAD_MEM_ALIGNMENT

アドレスがページ境界に整列されていません。

セグメントのマッピング解除

int rsm_memseg_import_unmap (rsm_memseg_import_handle_t im_memseg );

この関数は、ユーザーの仮想アドレス空間からインポートされたセグメントをマッピング解除します。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

バリア操作

バリア操作は、書き込みアクセス順番メモリーモデルに関する問題を解決するときに使用します。バリア操作は、リモートメモリーアクセスエラーを検出することもできます。

バリアメカニズムには、次のような操作が含まれます。

開く操作と閉じる操作は、エラーの検出と順番の決定を行う期間 (span-of-time) を定義します。初期化操作は、インポートされたセグメントごとにバリアの作成とバリアのタイプの指定を可能にします。現在サポートされるバリアのタイプだけが、セグメントごとに期間 (span-of-time) を持っています。タイプ引数には RSM_BAR_DEFAULT を使用してください。

閉じる操作を正常に実行することによって、バリアを開いてから閉じるまでの間に発生するアクセス操作が正常に完了することが保証されます。バリアを開いた後、個々のデータアクセス操作 (読み取りと書き込みの両方) が失敗しても、バリアを閉じるまでは報告されません。

バリアの有効範囲内で書き込みの順番を決定するには、明示的なバリア順番決定操作を使用します。バリア順番決定操作の前に発行された書き込み操作は、バリア順番決定操作後に発行された操作よりも前に完了します。あるバリアの有効範囲内の書き込み操作の順番は別のバリアの有効範囲を基準にして決定されます。

バリアの初期化

int rsm_memseg_import_init_barrier (rsm_memseg_import_handle_t im_memseg , rsm_barrier_type_t type, rsmapi_barrier_t *barrier);

注 –

現在のところ、サポートされるタイプは RSM_BAR_DEFAULT だけです。


戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_BARRIER_PTR

バリアポインタが無効です。

RSMERR_INSUFFICIENT_MEM

メモリーが不足しています。

バリアを開く

int rsm_memseg_import_open_barrier (rsmapi_barrier_t *barrier);

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_BARRIER_PTR

バリアポインタが無効です。

バリアを閉じる

int rsm_memseg_import_close_barrier (rsmapi_barrier_t *barrier);

この関数はバリアを閉じて、すべてのストアバッファーをフラッシュします。この関数は、rsm_memseg_import_close_barrier() の呼び出しが失敗した場合、最後の rsm_memseg_import_open_barrier 呼び出しまで、呼び出し元プロセスがすべてのリモートメモリー操作を再試行することを前提にして呼び出されます。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_BARRIER_PTR

バリアポインタが無効です。

RSMERR_BARRIER_UNINITIALIZED

バリアが初期化されていません。

RSMERR_BARRIER_NOT_OPENED

バリアが開かれていません。

RSMERR_BARRIER_FAILURE

メモリーアクセスエラー

RSMERR_CONN_ABORTED

接続が中断されました。

バリアの順番決定

int rsm_memseg_import_order_barrier (rsmapi_barrier_t *barrier);

この関数は、すべてのストアバッファーをフラッシュします。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_BARRIER_PTR

バリアポインタが無効です。

RSMERR_BARRIER_UNINITIALIZED

バリアが初期化されていません。

RSMERR_BARRIER_NOT_OPENED

バリアが開かれていません。

RSMERR_BARRIER_FAILURE

メモリーアクセスエラー

RSMERR_CONN_ABORTED

接続が中断されました。

バリアの破壊

int rsm_memseg_import_destroy_barrier(rsmapi_barrier_t *barrier);

この関数は、すべてのバリアリソースの割り当てを解除します。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

RSMERR_BAD_BARRIER_PTR

バリアポインタが無効です。

モードの設定

int rsm_memseg_import_set_mode (rsm_memseg_import_handle_t im_memseg, rsm_barrier_mode_t mode);

この関数は、put ルーチンで利用できるオプションの明示的なバリアの有効範囲決定をサポートします。有効なバリアモードは、RSM_BARRIER_MODE_EXPLICITRSM_BARRIER_MODE_IMPLICIT の 2 つです。バリアモードのデフォルト値は RSM_BARRIER_MODE_IMPLICIT です。暗黙モードでは、put 操作ごとに暗黙的なバリアの開く操作と閉じる操作が適用されます。バリアモードを RSM_BARRIER_MODE_EXPLICIT に設定する前は、rsm_memseg_import_init_barrier ルーチンを使用して、インポートされたセグメント im_memseg 用のバリアを初期化する必要があります。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。

モードの取得

int rsm_memseg_import_get_mode (rsm_memseg_import_handle_t im_memseg , rsm_barrier_mode_t *mode);

この関数は、put ルーチンにおける現在のバリアの有効範囲決定のモード値を取得します。

戻り値: 成功した場合、0 を返します。そうでない場合、エラー値を返します。

RSMERR_BAD_SEG_HNDL

セグメントハンドルが無効です。