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

API ライブラリ関数

API ライブラリ関数は次の操作をサポートします。

相互接続コントローラ操作

コントローラ操作は、コントローラへのアクセスを取得するメカニズムを提供します。コントローラ操作はまた、配下の相互接続の特性も決定します。相互接続コントローラ操作には、次のような操作が含まれます。

rsm_get_controller

int rsm_get_controller(char *name, rsmapi_controller_handle_t *controller);

rsm_get_controller は、指定されたコントローラのインスタンス (sci0loopback など) のコントローラハンドルを取得します。返されるコントローラハンドルは後続の RSM ライブラリ呼び出しに使用されます。

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

RSMERR_BAD_CTLR_HNDL

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

RSMERR_CTLR_NOT_PRESENT

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

RSMERR_INSUFFICIENT_MEM

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

RSMERR_BAD_LIBRARY_VERSION

ライブラリのバージョンが無効です

RSMERR_BAD_ADDR

アドレスが不正です

rsm_release_controller

int rsm_release_controller(rsmapi_controller_handle_t chdl);

この関数は、指定されたコントローラハンドルに関連するコントローラを解放します。rsm_release_controller の呼び出しごとに対応する rsm_get_controller が存在する必要があります。つまり、コントローラに関連付けられたコントローラハンドルをすべて解放すると、コントローラに関連付けられたシステム資源が解放されます。コントローラハンドルにアクセスしたり、解放されたコントローラハンドル上のインポートセグメントまたはエクスポートセグメントにアクセスしたりすることは不正です。このような場合の結果は定義されていません。

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

RSMERR_BAD_CTLR_HNDL

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

rsm_get_controller_attr

int rsm_get_controller_attr(rsmapi_controller_handle_t chdl, rsmapi_controller_attr_t *attr);

この関数は、指定されたコントローラハンドルの属性を取得します。この関数に現在定義されている属性は次のとおりです。

typedef struct {
     uint_t       attr_direct_access_sizes;
     uint_t       attr_atomic_sizes;
     size_t       attr_page_size;
     size_t       attr_max_export_segment_size;
     size_t       attr_tot_export_segment_size;
     ulong_t      attr_max_export_segments;
     size_t       attr_max_import_map_size;
     size_t       attr_tot_import_map_size;
     ulong_t      attr_max_import_segments;
 } rsmapi_controller_attr_t;

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

RSMERR_BAD_CTLR_HNDL

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

RSMERR_BAD_ADDR

アドレスが不正です

クラスタトポロジ操作

エクスポート操作とインポート操作に必要な鍵となる相互接続データは次のとおりです。

基本的な制約として、インポートセグメント用に指定されたコントローラは、関連するエクスポートセグメント用に使用されるコントローラと物理的に接続されている必要があります。このインタフェースが定義する相互接続トポロジによって、アプリケーションは効率的なエクスポートポリシーとインポートポリシーを確立できます。提供されるデータには、各ローカルコントローラのローカルノード ID、ローカルコントローラインスタンス名、およびリモート接続指定が含まれます。

メモリーをエクスポートするアプリケーション構成要素は、インタフェースが提供するデータを使用して、既存のローカルコントローラセットを発見します。インタフェースが提供するデータはまた、セグメントを作成および発行するためのコントローラを正しく割り当てるために使用できます。アプリケーション構成要素は、ハードウェア相互接続とアプリケーションソフトウェアディストリビューションに整合性があるコントローラセットを使用して、エクスポートされたセグメントを効率的に分散できます。

メモリーをインポートするアプリケーション構成要素は、メモリーのエクスポートで使用されるセグメント ID とコントローラを通知する必要があります。この情報は通常、事前定義されているセグメントとコントローラのペアによって伝達されます。メモリーをインポートしている構成要素はトポロジデータを使用して、セグメントインポート操作に適切なコントローラを決定できます。

rsm_get_interconnect_topology

int rsm_get_interconnect_topology(rsm_topology_t **topology_data);

この関数は、アプリケーションポインタによって指定された場所にあるトポロジデータへのポインタを返します。トポロジデータ構造体は次のように定義されます。

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

RSMERR_BAD_TOPOLOGY_PTR

トポロジポインタが無効です

RSMERR_INSUFFICIENT_MEM

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

RSMERR_BAD_ADDR

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

rsm_free_interconnect_topology

void rsm_free_interconnect_topology(rsm_topology_t *topology_data);

rsm_free_interconnect_topology 操作は、rsm_get_interconnect_topology で割り当てられたメモリーを解放します。

戻り値: ありません。

データ構造体

rsm_get_topology_data から返されるポインタは rsm_topology_t structure を参照します。この構造体は、各ローカルコントローラのローカルノード ID と connections_t 構造体へのポインタの配列を提供します。

typedef struct rsm_topology {
   rsm_nodeid_t    local_nodeid;
   uint_t          local_cntrl_count;
   connections_t   *connections[1];
} rsm_topology_t;

管理操作

RSM セグメント ID はアプリケーションが指定するか、システムが rsm_memseg_export_publish() 関数を使用して生成します。セグメント ID を指定するアプリケーションは、予約されたセグメント ID の範囲を使用する必要があります。セグメント ID の範囲を予約するには、rsm_get_segmentid_range 関数を使用して、予約されたセグメント ID の範囲をセグメント ID 構成ファイル /etc/rsm/rsm.segmentid に定義します。rsm_get_segmentid_range 関数を使用すると、アプリケーションは自分用に予約されたセグメント ID の範囲を取得できます。この関数は、指定されたアプリケーション ID の /etc/rsm/rsm.segmentid ファイルに定義されているセグメント ID の範囲を読み取ります。

アプリケーション ID はアプリケーションを識別するための NULL で終了する文字列です。アプリケーションは baseid 以上で baseid+length 未満の値を使用できます。baseid または length が変更された場合、アプリケーションに返されるセグメント ID は予約された範囲内ではない場合がありますので、セグメント ID を取得するときには、予約されたセグメント ID の範囲内のオフセットを使用してください。

/etc/rsm/rsm.segmentid ファイル内のエントリは次のような形式です。


#keyword      appid      baseid       length
reserve       SUNWfoo    0x600000     100

エントリを構成する文字列は、タブまたは空白で区切ることができます。この文字列は先頭から、キーワード reserve、アプリケーション識別子 (空白を含まない文字列)、baseid (予約された範囲の開始セグメント ID (16 進数))、および、length (予約されたセグメント ID の数) から構成されます。コメント行には、最初の列に # を指定します。このファイルには、空白 (空白の行) があってはなりません。システムに予約されたセグメント ID は/usr/include/rsm/rsm_common.h ヘッダーファイルに定義されています。アプリケーションはシステムに予約されたセグメント ID を使用できません。

成功した場合、rsm_get_segmentid_range 関数は 0 を返します。失敗した場合、この関数は次のエラー値のうちの 1 つを返します。

RSMERR_BAD_ADDR

渡されたアドレスが無効です

RSMERR_BAD_APPID

アプリケーション ID が /etc/rsm/rsm.segmentid ファイルに定義されていません

RSMERR_BAD_CONF

構成ファイル /etc/rsm/rsm.segmentid が存在しないか、読み取ることができません。構成ファイルの書式が正しくありません

メモリーセグメント操作

RSM セグメントは、連続する仮想アドレスの範囲にマッピングされた (一般的に) 連続しない物理メモリーページセットを表します。RSM セグメントのエクスポート操作とインポート操作によって、相互接続のシステム間で物理メモリー領域を共有できるようになります。物理メモリーページが存在するノードのプロセスのことをメモリーの「エクスポータ」と呼びます。リモートアクセス用に発行するためにエクスポートされたセグメントは、指定されたノードに固有なセグメント識別子を持ちます。セグメント ID はエクスポータが指定するか、RSMAPI フレームワークが割り当てます。

エクスポートされたメモリーへのアクセスを取得するために、相互接続のノードのプロセスは RSM インポートセグメントを作成します。この RSM インポートセグメントは、ローカルの物理ページではなく、エクスポートされたセグメントと接続しています。相互接続がメモリーマッピングをサポートする場合、インポータはインポートセグメントのメモリーマッピングされたアドレスを使用して、エクスポートされたメモリーを読み書きできます。相互接続がメモリーマッピングをサポートしない場合、インポートしているプロセス (インポータ) はメモリーアクセスプリミティブを使用します。

エクスポート側のメモリーセグメント操作

メモリーセグメントをエクスポートするとき、アプリケーションはまず、通常のオペレーティングシステムインタフェース (System V Shared Memory Interface、mmap、または valloc など) を使用して、自分の仮想アドレス空間にメモリーを割り当てます。メモリーを割り当てたあと、アプリケーションは RSMAPI ライブラリインタフェースを呼び出し、セグメントを作成して、ラベルを付けます。セグメントにラベルを付けたあと、RSMAPI ライブラリインタフェースは割り当てた仮想アドレスの範囲に物理ページをバインドします。物理ページをバインドしたあと、RSMAPI ライブラリインタフェースはセグメントを発行して、インポートしているプロセス (インポータ) がアクセスできるようにします。


注 –

mmap を使用して仮想アドレス空間を取得した場合、マッピングは MAP_PRIVATE である必要があります。


エクスポート側のメモリーセグメント操作には、次のような操作が含まれます。

メモリーセグメントの作成と破壊

rsm_memseg_export_create を使用して新しいメモリーセグメントを確立すると、セグメントを作成するときに物理メモリーを関連付けることができます。この操作は、エクスポート側のメモリーセグメントハンドルを新しいメモリーセグメントに戻します。セグメントは作成するプロセスが動作している間、または、rsm_memseg_export_destroy を使用して破壊するまで存在します。


注 –

インポート側が切断する前に破壊操作が行われた場合、切断が強制的に行われます。


セグメントの作成

int rsm_memseg_export_create(rsmapi_controller_handle_t controller, rsm_memseg_export_handle_t *memseg, void *vaddr, size_t size, uint_t flags);

この関数はセグメントハンドルを作成します。セグメントハンドルを作成したあと、この関数はセグメントハンドルを指定された仮想アドレス範囲 [vaddr..vaddr+size] にバインドします。この範囲は有効であり、コントローラの alignment プロパティー上に整列している必要があります。flags 引数はビットマスクで、次の操作を有効にします。


注 –

RSM_LOCK_OPS フラグは RSMAPI の初期リリースには含まれません。


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

RSMERR_BAD_CTLR_HNDL

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

RSMERR_CTLR_NOT_PRESENT

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_BAD_LENGTH

コントローラの長さが 0 あるいは、制限を超えています

RSMERR_BAD_ADDR

アドレスが無効です

RSMERR_PERM_DENIED

Permission denied

RSMERR_INSUFFICIENT_MEM

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

RSMERR_INSUFFICIENT_RESOURCES

資源が不足しています

RSMERR_BAD_MEM_ALIGNMENT

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

RSMERR_INTERRUPTED

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

セグメントの破壊

int rsm_memseg_export_destroy(rsm_memseg_export_handle_t memseg);

この関数はセグメントとその空き資源の割り当てを解除します。インポートしているプロセス (インポータ) はすべて強制的に切断されます。

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_POLLFD_IN_USE

pollfd は使用中です

メモリーセグメントの発行、再発行、および発行解除

発行操作によって、相互接続上にあるほかのノードがメモリーセグメントをインポートできます。エクスポートセグメントは複数の相互接続アダプタ上で発行できます。

セグメント ID は承認された範囲または 0 を指定した場合、有効なセグメント ID が RSMAPI フレームワークによって生成され、返されます。

セグメントアクセス制御リストはノード ID とアクセス権のペアから構成されます。リストでは、指定したノード ID ごとに、Solaris のファイルアクセス権とともに所有者、グループ、およびその他のユーザーの 3 つの 8 進数によって関連する読み取り権と書き込み権が示されます。アクセス制御リストでは、各 8 進数は次の値を持ちます。

2

書き込みアクセス。

4

読み取り専用アクセス。

6

読み取りおよび書き込みアクセス。

たとえば、0624 というアクセス権は次のことを意味します。

アクセス制御リストが提供される場合、リストに含まれないノードはセグメントをインポートできません。ただし、アクセス制御リストが NULL の場合は、すべてのノードがセグメントをインポートできます。すべてのノードのアクセス権は、エクスポートするプロセス (エクスポータ) の所有者、グループ、およびその他のファイル作成権と同じになります。


注 –

ノードアプリケーションはセグメント識別子の割り当てを管理し、エクスポートするノード上で一意性を保証する義務があります。


セグメントの発行

int rsm_memseg_export_publish(rsm_memseg_export_handle_t memseg, rsm_memseg_id_t *segment_id, rsmapi_access_entry_t ACCESS_list[], uint_t access_list_length);
typedef struct {
    rsm_node_id_t       ae_node;    /* remote node id allowed to access resource */
    rsm_permission_t    ae_permissions;    /* mode of access allowed */
} rsmapi_access_entry_t;.

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_SEG_ALREADY_PUBLISHED

セグメントはすでに発行されています

RSMERR_BAD_ACL

アクセス制御リストが無効です

RSMERR_BAD_SEGID

セグメント ID が無効です

RSMERR_SEGID_IN_USE

セグメント ID は使用中です

RSMERR_RESERVED_SEGID

セグメント ID は予約されています

RSMERR_NOT_CREATOR

セグメントの作成者ではありません

RSMERR_BAD_ADDR

アドレスが不正です

RSMERR_INSUFFICIENT_MEM

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

RSMERR_INSUFFICIENT_RESOURCES

資源が不足しています

認可されたセグメント ID の範囲:

#define RSM_DRIVER_PRIVATE_ID_BASE

0

#define RSM_DRIVER_PRIVATE_ID_END

0x0FFFFF

#define RSM_CLUSTER_TRANSPORT_ID_BASE

0x100000

#define RSM_CLUSTER_TRANSPORT_ID_END

0x1FFFFF

#define RSM_RSMLIB_ID_BASE

0x200000

#define RSM_RSMLIB_ID_END

0x2FFFFF

#define RSM_DLPI_ID_BASE

0x300000

#define RSM_DLPI_ID_END

0x3FFFFF

#define RSM_HPC_ID_BASE

0x400000

#define RSM_HPC_ID_END

0x4FFFFF

次に示す範囲は、公開値が 0 の場合、システムによる割り当て用に予約されています。

#define RSM_USER_APP_ID_BASE

0x80000000

#define RSM_USER_APP_ID_END

0xFFFFFFF

セグメントの再発行

int rsm_memseg_export_republish(rsm_memseg_export_handle_t memseg, rsmapi_access_entry_t access_list[], uint_t access_list_length);

この関数は、ノードのアクセス (制御) リストとセグメントのアクセスモードを新たに確立します。これらの変更は将来のインポート呼び出しだけに影響し、すでに許可されているインポート要求は取り消しません。

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_SEG_NOT_PUBLISHED

セグメントが発行されていません

RSMERR_BAD_ACL

アクセス制御リストが無効です

RSMERR_NOT_CREATOR

セグメントの作成者ではありません

RSMERR_INSUFFICIENT_MEMF

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

RSMERR_INSUFFICIENT_RESOURCES

資源が不足しています

RSMERR_INTERRUPTED

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

セグメントの発行解除

int rsm_memseg_export_unpublish(rsm_memseg_export_handle_t memseg);

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_SEG_NOT_PUBLISHED

セグメントが発行されていません

RSMERR_NOT_CREATOR

セグメントの作成者ではありません

RSMERR_INTERRUPTED

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

メモリーセグメントの再バインド

再バインド操作は、エクスポートセグメントの現在のバッキングストアを解放します。現在のバッキングストアを解放したあと、再バインド操作は、新しいバッキングストアを割り当てます。まず始めにアプリケーションは、セグメント用の新しい仮想メモリー割り当てを取得する必要があります。この操作はセグメントのインポータに透過的です。


注 –

アプリケーションは、再バインド操作が完了するまで、セグメントデータへアクセスしてはいけません。再バインド中にセグメントからデータを取得しようとしてもシステムエラーにはなりませんが、このような操作の結果は定義されていません。


セグメントの再バインド

int rsm_memseg_export_rebind(rsm_memseg_export_handle_t memseg, void *vaddr, offset_t off, size_t size);

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_BAD_LENGTH

長さが無効です

RSMERR_BAD_ADDR

アドレスが無効です

RSMERR_REBIND_NOT_ALLOWED

再バインドは許可されていません

RSMERR_NOT_CREATOR

セグメントの作成者ではありません

RSMERR_PERM_DENIED

Permission denied

RSMERR_INSUFFICIENT_MEM

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

RSMERR_INSUFFICIENT_RESOURCES

資源が不足しています

RSMERR_INTERRUPTED

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

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

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

接続操作は、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

Permission 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

Permission 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

Permission 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 */

    int        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,    /* system will choose available virtual address */
    RSM_MAP_FIXED = 0x1,    /* map segment at specified virtual address */
} 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

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

イベント操作

イベント操作によって、プロセスはメモリーアクセスイベントと同期をとることができます。rsm_intr_signal_wait() 関数を使用できない場合、rsm_memseg_get_pollfd() でポーリング記述子を取得し、poll システムコールを使用することによって、プロセスはイベント待機を多重送信できます。


注 –

rsm_intr_signal_post() 操作および rsm_intr_signal_wait() 操作を使用した場合、カーネルへの ioctl 呼び出しを処理する必要があります。


シグナルの送信

int rsm_intr_signal_post(void *memseg, uint_t flags);

void ポインタ *memseg を使用すると、インポートセグメントハンドルまたはエクスポートセグメントハンドルのどちらでもタイプキャスト (型変換) できます。*memseg がインポートセグメントハンドルを参照している場合、この関数はエクスポートしているプロセス (エクスポータ) にシグナルを送信します。*memseg がエクスポートセグメントハンドルを参照している場合、この関数はそのセグメントのすべてのインポータにシグナルを送信します。flags 引数に RSM_SIGPOST_NO_ACCUMULATE を設定すると、あるイベントがすでにターゲットセグメントに対して保留中である場合、当該イベントを破棄します。

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_REMOTE_NODE_UNREACHABLE

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

シグナルの待機

int rsm_intr_signal_wait(void * memseg, int timeout);

void ポインタ *memseg を使用すると、インポートセグメントハンドルまたはエクスポートセグメントハンドルのどちらでもタイプキャスト (型変換) できます。プロセスは timeout ミリ秒まで、あるいは、イベントが発生するまでブロックされます。値が -1 の場合、プロセスはイベントが発生するまで、あるいは、割り込みが発生するまでブロックされます。

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

RSMERR_BAD_SEG_HNDL

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

RSMERR_TIMEOUT

タイマーが満了しました

RSMERR_INTERRUPTED

待機中に割り込みが発生しました

pollfd の取得

int rsm_memseg_get_pollfd(void *memseg, struct pollfd *pollfd);

この関数は、指定された pollfd 構造体を、指定されたセグメントの記述子と rsm_intr_signal_post() で生成された単一固定イベントで初期化します。pollfd 構造体を poll システムコールで使用すると、rsm_intr_signal_post によってシグナル送信されるイベントを待機します。メモリーセグメントがまだ発行されていない場合、poll システムコールは有効な pollfd を返しません。呼び出しが成功するたびに、指定されたセグメントの pollfd 参照カウントがインクリメントします。

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

RSMERR_BAD_SEG_HNDL

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

pollfd の解放

int rsm_memseg_release_pollfd(oid *memseg);

この呼び出しは、指定されたセグメントの pollfd 参照カウントをデクリメントします。参照カウントが 0 以外の場合、セグメントを発行解除、破壊、またはマッピング解除する操作は失敗します。

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

RSMERR_BAD_SEG_HNDL

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