OpenVMS Alpha
オペレーティング・システム
64 ビット・アドレッシングおよび
VLM 機能説明書


前へ 次へ 目次 索引


7.4.1 64 ビット S2DGB 例

64 ビットの S2DGB の設定例を示します。


#include <s2dgbdef.h>                                  /* Define S2DGB   */ 
#include <far_pointers.h>                              /* Define VOID_PQ */ 
 
   S2DGB diag_desc; 
 
   /* Set up some default S2DGB descriptor values */ 
 
   diag_desc.s2dgb$l_opcode = OP_XCDB64               /* Use 64-bits  */ 
   diag_desc.s2dgb$l_flags =  (S2DGB$M_READ |         /* Flags*/ 
                         S2DGB$M_TAGGED_REQ | 
                         S2DGB$M_AUTOSENSE); 
   diag_desc.s2dgb$v_tag = S2DGB$K_SIMPLE;           /* SIMPLE que tag */ 
   diag_desc.s2dgb$pq_64cdbaddr = (VOID_PQ)(&cdb[0]);/* Command addr  */ 
   diag_desc.s2dgb$l_64cdblen =  6;                  /* Command length */ 
   diag_desc.s2dgb$pq_64dataddr = (VOID_PQ)(&buf[0]);/* Data addr      */ 
   diag_desc.s2dgb$l_64datlen = 20;                  /* Data length    */ 
   diag_desc.s2dgb$l_64padcnt = 0;                   /* Pad length    */ 
   diag_desc.s2dgb$l_64phstmo = 20;                  /* Phase timeout */ 
   diag_desc.s2dgb$l_64dsctmo = 10;                  /* Disc timeout  */ 
   diag_desc.s2dgb$pq_64senseaddr = (VOID_PQ)(&asn[0]);/* Autosense addr */ 
   diag_desc.s2dgb$l_64senselen = 255;               /* Sense length  */ 
   diag_desc.s2dgb$l_reserved_1 = 0;                 /* Reserved     */ 
        . 
        . 
        . 
 
   status = sys$qiow(0, target_chan, IO$_DIAGNOSE, &iosb, 0, 0, 
            &diag_desc,  S2DGB$K_XCDB64_LENGTH,  0,  0,  0,  0); 

パラメータがすべて有効な場合,クラス・ドライバは必要なポート関数を起動して,CDB の送信とデータの転送に加えて,入力 S2DGB によって定義されるセンス・データの戻し,保存,または廃棄を行います。終了時には,戻り IOSB の形式を 図 7-3 に示します。

図 7-3 戻り IOSB の形式


ほかの QIO 関数を実現する DKDRIVER,GKDRIVER,および MKDRIVER クラス・ドライバは,IO$_DIAGNOSE 要求と共にほかのタグ付き要求を混合します。要求が送られる順序は一般に,ドライバに対して要求が指定される順序に一致します。ただしこの順序には例外があり,ドライバが REQUEST SENSE を受け取り,これに対してオートセンス・データが以前に復元および保存されている場合がこれに相当します。この場合,IO$_DIAGNOSE が直ちに終了し,コマンドがターゲットに送られることはありません。

DKDRIVER,GKDRIVER,および MKDRIVER クラス・ドライバは,次に説明する場合を除き,任意の時点で,1 つの IO$_DIAGNOSE 操作に限って (開始の入出力ルーチンの中で) アクティブであることを許可します。しかしアプリケーションは,センス・データの存在を正しく検出し,要求される REQUEST SENSE コマンドを送信するために,IO$_DIAGNOSE 要求を単一スレッド化する必要があります。これは,VAX IO$_DIAGNOSE の動作に一致するものです。たとえば,3 つの読み込みが警告メッセージを伴わずに実行されると,最初の読み込みが CHECK CONDITION を受け取り,2 番目の読み込みが到着するときにセンス・データがターゲットによって廃棄されます。

DKDRIVER,GKDRIVER,および MKDRIVER ドライバは,すべてのアクティブ操作の S2DGB$V_AUTOSENSE フラグが 1 に等しいときに限って,複数の IO$_DIAGNOSE 操作が (開始の入出力ルーチンの中で) アクティブであることを許可します。S2DGB$V_AUTOSENSE が 0 に等しい IO$_DIAGNOSE が発生した時点で,クラス・ドライバは上で説明した制限を適用します。


第 8 章
OpenVMS Alpha 64 ビット API ガイドライン

本章では,OpenVMS Alpha 64 ビット仮想アドレッシングをサポートする,64 ビット・インタフェースを開発する際のガイドラインについて説明します。独自の 64 ビット・アプリケーション・プログラミング・インタフェースを開発しているアプリケーション・プログラマにとって,このガイドラインは大変有用です。

本章で推奨するガイドラインは,難しく厳密な規則ではありません。適切なプログラミングの例を紹介しながら,ガイドラインを説明します。

C ポインタ・プラグマについての詳細は,『DEC C User's Guide for OpenVMS Systems』を参照してください。

8.1 クォドワード/ロングワード引数ポインタのガイドライン

OpenVMS Alpha 64 ビット・アドレッシングのサポートは,アプリケーション・プログラムが 64 ビット・アドレス空間のデータへアクセスすることを認めています。そのためアプリケーションの中では,32 ビット符合拡張値でないポインタ(64 ビット・ポインタ)がより一般的になります。既存の 32 ビット API も引き続きサポートされるため,プログラマは 64 ビット・ポインタの存在を特に注意する必要があります。

たとえば 64 ビット・アドレスを,誤って 32 ビット・アドレスしか処理できないルーチンに渡す可能性が考えられます。また,新しい API が 64 ビット・ポインタをデータ構造に埋め込む場合も考えられます。このようなポインタは,新しいデータ構造の中では符号拡張の 32 ビット値として存在しますが,最初は 32 ビット・アドレス空間のポイントに制限されます。

どのルーチンも,32 ビット・アドレスに代わって 64 ビット・アドレスが渡される場所では,プログラミング・エラーに注意する必要があります。このようなチェックは符号拡張チェックと呼ばれるもので,ビット 31 の値に一致した状態で,アドレスの上位 32 ビットがすべて 0,またはすべて 1 であることを確認します。このチェックは,この制限を適用しているルーチン・インタフェースで実行できます。

ルーチン・インタフェースを新しく定義するときは,32 ビット・ソース・モジュールから,ルーチンの呼び出しを簡単にプログラムできるように考慮しなければなりません。また,64 ビット・アドレッシングのサポートをもともと意図している言語だけでなく,すべての OpenVMS プログラミング言語で作成された呼び出しを考慮しなければなりません。新規ルーチンの 32 ビット呼び出し側に対して不慣れなプログラミングを強いることを防ぐために,64 ビット呼び出し側だけでなく 32 ビット呼び出し側にも配慮しなければなりません。

32 ビット・アドレス空間 (P0/P1/S0/S1) での常駐が禁止されている参照渡しの引数は,その参照アドレスを符号拡張チェックする必要がある

OpenVMS 呼び出し規則では,ルーチンに渡される 32 ビット値は,ルーチンが呼び出される前に,64 ビットに符号拡張されることが要求されます。このため,呼び出されるルーチンは,常に 64 ビット値を受け取ります。32 ビット・ルーチンは,引数に対する参照を符号拡張チェックしない限り,その呼び出し側が 32 ビット・アドレスで正しくルーチンを呼び出したかどうかを判断できません。

データがディスクリプタでルーチンに渡される場合には,ディスクリプタへの参照に対してもこの符号拡張チェックが適用されます。

符号拡張チェックが失敗した場合,呼び出されたルーチンは,エラー状態 SS$_ARG_GTR_32_BITS を返します。

あるいは,呼び出されるルーチンが,エラーがない状態で 64 ビットの位置に渡されるデータを受け取ることが求められる場合,符号拡張チェックが失敗したときは,データを 32 ビット・アドレス空間にコピーすることができます。ルーチンがデータをコピーする 32 ビット・アドレス空間は,ローカル・ルーチン記憶域 (つまり,現在のスタック) です。ローカル記憶域以外の 32 ビット位置にデータがコピーされる場合,メモリ・リークおよびリエントラントについて考慮する必要があります。

新規ルーチンを開発する場合,コードへのポインタおよび新規ルーチンへ渡されるすべてのデータ・ポインタは,できるだけ 64 ビット・アドレス空間を利用することが望まれます。これは,データがルーチンの場合,またはプログラマやコンパイラ,リンカが通常は 64 ビット・アドレス空間に配置しない 静的データと一般に考えられる場合であっても同様です。コードと静的データが 64 ビット・アドレス空間の中でサポートされる場合,このルーチンを改めて変更する必要はありません。

32 ビット・ディスクリプタ引数が 32 ビット・ディスクリプタであることを確認する必要がある

ディスクリプタを受け取るルーチンは,32 ビットおよび 62 ビット・ディスクリプタ形式を区別するフィールドをチェックしなければなりません。64 ビット・ディスクリプタを受け取ると,ルーチンはエラーを返します。

既存の大半の 32 ビット・ルーチンは,64 ビット・ディスクリプタが間違って指定されると,次の理由でエラー状態 SS$_ACCVIO を返します。

図 8-1 32 ビット・ディスクリプタ


64 ビット・ディスクリプタで渡される引数を受け取るルーチンは,64 ビット・ディスクリプタと同様に 32 ビット・ディスクリプタに対処する必要がある

新規ルーチンは,同じルーチンの中で 32 ビット・ディスクリプタと 64 ビット・ディスクリプタに対処します。同じ引数で 32 ビット・ディスクリプタまたは 64 ビット・ディスクリプタを指すことができます。オフセット 0 での 64 ビット・ディスクリプタ MBO ワードは,値が 1 であることをテストし,オフセット 4 での 64 ビット・ディスクリプタ MBMO ロングワードは -1 であることをテストすることによって,32 ビット・ディスクリプタと 64 ビット・ディスクリプタを区別します。

32 ビット・ディスクリプタに加えて 64 ビット・ディスクリプタの処理を目的として変換されている,既存の 32 ビット・ルーチンを考えてみます。入力ディスクリプタが 64 ビット・ディスクリプタであると判断されると,64 ビット・ディスクリプタが指すデータを,まず 32 ビットのメモリ位置にコピーした上で,32 ビット・メモリの中で 32 ビット・ディスクリプタが作成されます。この新しい 32 ビット・ディスクリプタを既存の 32 ビット・コードに渡すことで,ルーチン内部での変更はこれ以上必要ありません。

32 ビット項目リスト引数が 32 ビット項目リスト引数であることを確認する必要がある

項目リストは,item_list_2 および item_list_3 という 2 種類の形式で定義されます。item_list_2 形式の項目リストは 2 つのロングワードで構成されており,先頭のロングワードには長さと項目コードのフィールドが含まれ,2 番目のロングワードには通常バッファ・アドレスが含まれています。

これに対して item_list_3 形式の項目リストは 3 つのロングワードで構成されています。先頭のロングワードには長さと項目コードのフィールドが含まれ,2 番目と 3 番目のロングワードには,通常バッファ・アドレスおよび戻り長アドレス・フィールドが含まれています。

32 ビット項目リストが 2 種類存在するため,64 ビット項目リストも 2 種類定義されています。新しく加えられた item_list_64a および item_list_64b は,32 ビットの項目リストにそれぞれ対応します。どちらの形式の項目リストも,オフセット 0 および 4 の位置に,MBO および MBMO フィールドをそれぞれ含んでいます。また,両方の項目リストとも,ワード・サイズの項目コード・フィールド,クォドワード・サイズの長さフィールド,およびクォドワード・サイズのバッファ・アドレス・フィールドをそれぞれ含んでいます。なお,item_list_64b 形式の項目リストは,これとは別にクォドワード・サイズの戻り値長アドレス・フィールドも含んでいます。戻り値長は 64 ビットです。

項目リストを受け取るルーチンは,フィールドをテストして,これが 32 ビット項目リストと 64 ビット項目リストのどちらであるかを区別しなければなりません。64 ビット項目リストを受け取った場合,ルーチンはエラーを返します。

既存の大半の 32 ビット・ルーチンは,64 ビット項目リストが間違って渡されたことを次の理由で判別した場合,エラー状態 SS$_ACCVIO を返します。またはこれをシグナル通知します。

図 8-2 item_list_64a


図 8-3 item_list_64b


64 ビット項目リスト引数で渡される引数を受け取るルーチンは,64 ビット項目リスト同様 32 ビット項目リストにも対処する必要がある

新規ルーチンは,同一ルーチン内で 32 ビット項目リストと 64 ビット項目リストに対処しなければなりません。同じ引数が,32 ビット項目リストと 64 ビット項目リストのどちらも指すことができます。64 ビット項目リストのオフセット 0 にある MBO ワードは 1 でなければならず,64 ビット項目リストのオフセット 4 にある MBMO ロングワードは -1 でなければなりません。そのため,これをテストすることによって,64 ビット項目リストと 32 ビット項目リストを区別します。

ポインタの参照渡しを避ける

特定のメモリ管理ルーチンなどで,ポインタを参照渡しする必要がある場合,ポインタは 64 ビットで定義します。

32 ビット・ポインタと 64 ビット・ポインタが混在すると,64 ビット・ポインタが期待されている場所に,呼び出し側が間違って 32 ビット・ポインタを参照渡しするなどの,プログラミング・エラーを引き起こします。

プログラマによってロングワードしか割り当てられていないのに,呼び出されたルーチンが 64 ビット・ポインタを読み込むと,ルーチンの中で間違ったアドレスが使用されることになります。

また,呼び出されたルーチンが 64 ビット・ポインタを返すと,プログラマによって割り当てられているロングワードに対して 64 ビット・アドレスが書き込まれるため,データの破損が発生します。

ポインタを参照渡しされる既存のルーチンには,64 ビット・サポート用の新規インタフェースが必要です。旧ルーチン・インタフェースは,32 ビット・メモリ位置の中でポインタをこれまでのように渡し,これに対して新規ルーチン・インタフェースは,64 ビット・メモリ位置でポインタを渡します。同じインタフェースを保持した上で,64 ビット・ポインタを渡すと,既存のプログラムに異常が発生します。

例: SYS$CRETVA_64 サービスで使用される戻り仮想アドレスは,参照渡しでポインタを渡すことのできる例です。P0 空間および P1 空間の中で作成される仮想アドレスは,64 ビットすべてが返されますが,意味があるのは 32 ビットだけであることが保証されています。SYS$CRETVA_64 は 64 ビット空間にアドレス空間を作成し,64 ビット・アドレスを返すこともできます。64 ビット・アドレスが返るため,返される値は常に 64 ビットであることが必要です。

メモリ割り当てルーチンは,可能な場合,値 (つまり R0) で割り当てられるデータへのポインタを返します。C 割り当てルーチン,malloc,calloc,realloc がこの例です。

メモリ管理ルーチンでないルーチンの新規インタフェースで,出力引数を定義してアドレスを受け取ることは避けてください。64 ビット・サブシステムがメモリを割り当て,32 ビット呼び出し側に対してポインタを出力引数で戻すと,問題が発生します。呼び出し側は,64 ビット・ポインタをサポートまたは指定できない可能性があります。あるデータへのポインタを返す代わりに,呼び出し側はバッファへのポインタを用意して,呼び出されたルーチンがこのユーザ・バッファにデータをコピーすることが望まれます。

参照渡しされる 64 ビット・ポインタは,ルーチンへの呼び出しが 64 ビット言語または 32 ビット言語で作成できるような環境で定義する必要があります。64 ビット・ポインタはすべての呼び出し側によって渡される必要があることを,明確に指示しなければなりません。

特に要求されない限りルーチンは 64 ビット・アドレスを返す必要はない

呼び出し側で 64 ビット・アドレスを処理できることが確実でない限り,メモリを割り当て,その呼び出し側に対してアドレスを返すルーチンは,常に 32 ビット・アドレス・メモリを割り当てることに,十分に注意してください。これは,関数の戻り値と出力パラメータの両方に当てはまります。この規則は,64 ビット・アドレスを求めていないアプリケーションに,64 ビット・アドレスが侵入することを防ぐものです。この結果,呼び出し可能なライブラリを開発しているプログラマは,特に注意してこの規則に従う必要があります。

既存のルーチンが,割り当てられているメモリのアドレスをルーチン値として返す場合を考えます。呼び出し側が 64 ビットを処理できることがわかっていて,ルーチンが入力パラメータを受け取った場合,64 ビット・アドレスを返すことに何も問題はありません。これ以外の場合は,引き続き 32 ビット符号拡張アドレスを返さなければなりません。 後者の場合,64 ビットを処理できる呼び出し側が 64 ビット・メモリの割り当てを優先するのであれば,既存のバージョンに代わって,ルーチンの新バージョンを提供できます。

例: 文字列ディスクリプタを操作する LIBRTL 内のルーチンは,渡されたディスクリプタが新しい 64 ビット形式であれば,呼び出し側が 64 ビットを処理できると判断します。この場合は,文字列データに 64 ビット・メモリを割り当てても安全です。これ以外の場合は,32 ビット・アドレス・メモリだけを引き続き使用します。


前へ 次へ 目次 索引