拡張同期・通信機能

拡張同期・通信機能は、タスクとは独立したオブジェクトにより、タスク間の高度な同期・通信を行うための機能である。ミューテックス、メッセージバッファ、ランデブの各機能が含まれる。

ミューテックス

ミューテックスは、共有資源を使用する際にタスク間で排他制御を行うためのオブジェクトである。ミューテックスは、排他制御に伴う上限のない優先度逆転を防ぐための機構として、優先度継承プロトコル(priority inheritance protocol)と優先度上限プロトコル(priority ceiling protocol)をサポートする。

ミューテックス機能には、ミューテックスを生成/削除する機能、ミューテックスをロック/ロック解除する機能、ミューテックスの状態を参照する機能が含まれる。ミューテックスはID番号で識別されるオブジェクトである。ミューテックスのID番号をミューテックスIDと呼ぶ。

ミューテックスは、ロックされているかどうかの状態と、ロックを待つタスクの待ち行列を持つ。また、カーネルは、各ミューテックスに対してそれをロックしているタスクを、各タスクに対してそれがロックしているミューテックスの集合を管理する。タスクは、資源を使用する前に、ミューテックスをロックする。ミューテックスが他のタスクにロックされていた場合には、ミューテックスがロック解除されるまで、ミューテックスのロック待ち状態となる。ミューテックスのロック待ち状態になったタスクは、そのミューテックスの待ち行列につながれる。タスクは、資源の使用を終えると、ミューテックスのロックを解除する。

ミューテックスは、ミューテックス属性に TA_INHERIT(=0x02)を指定することにより優先度継承プロトコルを、TA_CEILING(=0x03)を指定することにより優先度上限プロトコルをサポートする。TA_CEILING 属性のミューテックスに対しては、そのミューテックスをロックする可能性のあるタスクの中で最も高いベース優先度を持つタスクのベース優先度を、ミューテックス生成時に上限優先度として設定する。TA_CEILING 属性のミューテックスを、その上限優先度よりも高いベース優先度を持つタスクがロックしようとした場合、E_ILUSE エラーとなる。また、TA_CEILING 属性のミューテックスをロックしているかロックを待っているタスクのベース優先度を、tk_chg_pri によってそのミューテックスの上限優先度よりも高く設定しようとした場合、tk_chg_priE_ILUSE エラーを返す。

これらのプロトコルを用いた場合、上限のない優先度逆転を防ぐために、ミューテックスの操作に伴ってタスクの現在優先度が自動的に変更される。優先度継承プロトコルと優先度上限プロトコルに厳密に従うなら、タスクの現在優先度を、次に挙げる優先度の最高値に常に一致するように変更する必要がある。これを、厳密な優先度制御規則と呼ぶ。

ここで、TA_INHERIT 属性のミューテックスを待っているタスクの現在優先度が、ミューテックス操作か tk_chg_pri によるベース優先度の変更に伴って変更された場合、そのミューテックスをロックしているタスクの現在優先度の変更が必要になる場合がある。これを推移的な優先度継承と呼ぶ。さらにそのタスクが、別の TA_INHERIT 属性のミューテックスを待っていた場合には、そのミューテックスをロックしているタスクに対して推移的な優先度継承の処理が必要になる場合がある。

T-Kernelでは、上述の厳密な優先度制御規則に加えて、現在優先度を変更する状況を限定した優先度制御規則(これを簡略化した優先度制御規則と呼ぶ)を規定し、どちらを採用するかは実装定義とする。具体的には、簡略化した優先度制御規則においては、タスクの現在優先度を高くする方向の変更はすべて行うのに対して、現在優先度を低くする方向の変更は、タスクがロックしているミューテックスがなくなった時にのみ行う(この場合には、タスクの現在優先度をベース優先度に戻すことになる)。より具体的には、次の状況でのみ現在優先度を変更する処理を行えばよい。

ミューテックスの操作に伴ってタスクの現在優先度を変更した場合には、次の処理を行う。

優先度を変更されたタスクが実行できる状態である場合、タスクの優先順位を、変更後の優先度にしたがって変化させる。変更後の優先度と同じ優先度を持つタスクの間での優先順位は、実装依存である。優先度が変更されたタスクが何らかのタスク優先度順の待ち行列につながれている場合にも、その待ち行列の中での順序を、変更後の優先度にしたがって変化させる。変更後の優先度と同じ優先度を持つタスクの間での順序は、実装依存である。タスクが終了する時に、そのタスクがロックしているミューテックスが残っている場合には、それらのミューテックスをすべてロック解除する。ロックしているミューテックスが複数ある場合には、それらをロック解除する順序は実装依存である。ロック解除の具体的な処理内容については、tk_unl_mtx の機能説明を参照すること。

注意補足事項
 

TA_TFIFO 属性または TA_TPRI 属性のミューテックスは、最大資源数が1のセマフォ(バイナリセマフォ)と同等の機能を持つ。ただし、ミューテックスは、ロックしたタスク以外はロック解除できない、タスク終了時に自動的にロック解除されるなどの違いがある。

ここでいう優先度上限プロトコルは、広い意味での優先度上限プロトコルで、最初に優先度上限プロトコルとして提案されたアルゴリズムではない。厳密には、highest locker protocolなどと呼ばれているアルゴリズムである。

ミューテックスの操作に伴ってタスクの現在優先度を変更した結果、優先度を変更されたタスクのタスク優先度順の待ち行列の中での順序が変化した場合、優先度を変更されたタスクないしはその待ち行列で待っている他のタスクの待ち解除が必要になる場合がある。

注意仕様決定の理由
 

ミューテックスの操作に伴ってタスクの現在優先度を変更した場合に、変更後の優先度と同じ優先度を持つタスクの間での優先順位を実装依存としたのは、次の理由による。アプリケーションによっては、ミューテックス機能による現在優先度の変更が頻繁に発生する可能性があり、それに伴ってタスク切替えが多発するのは望ましくない(同じ優先度を持つタスクの間での優先順位を最低とすると、不必要なタスク切替えが起こる)。理想的には、タスクの優先度ではなく優先順位を継承するのが望ましいが、このような仕様にすると実装上のオーバヘッドが大きくなるため、実装依存とすることにした。

tk_cre_mtx - ミューテックス生成

C言語インタフェース

#include <tk/tkernel.h>

ID mtxid = tk_cre_mtx (CONST T_CMTX *pk_cmtx );

パラメータ

CONST T_CMTX* pk_cmtx Packet to Create Mutexミューテックス生成情報

pk_cmtx の内容

void* exinf Extended Information拡張情報
ATR mtxatr Mutex Attributeミューテックス属性
PRI ceilpri Ceiling Priority of Mutexミューテックスの上限優先度
UB dsname[8] DS Object nameDSオブジェクト名称
──(以下に実装独自に他の情報を追加してもよい)──

リターンパラメータ

ID mtxid Mutex IDミューテックスID
またはError Codeエラーコード

エラーコード

E_NOMEM メモリ不足(管理ブロック用の領域が確保できない)
E_LIMIT ミューテックスの数がシステムの上限を超えた
E_RSATR 予約属性(mtxatr が不正あるいは利用できない)
E_PAR パラメータエラー(pk_cmtx, ceilpri が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

TK_SUPPORT_DISWAI ミューテックス属性としてTA_NODISWAI(待ち禁止の拒否)が指定可能
TK_SUPPORT_DSNAME TA_DSNAMEのミューテックス属性指定が可能

解説

ミューテックスを生成しミューテックスID番号を割り当てる。具体的には、生成するミューテックスに対して管理ブロックなどを割り付ける。

exinf は、対象ミューテックスに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_mtx で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf に入れる。カーネルでは exinf の内容について関知しない。

mtxatr は、下位側がシステム属性を表し、上位側が実装独自属性を表す。mtxatr のシステム属性の部分では、次のような指定を行う。

mtxatr:= (TA_TFIFO || TA_TPRI || TA_INHERIT || TA_CEILING) | [TA_DSNAME] | [TA_NODISWAI]

TA_TFIFO 待ちタスクのキューイングはFIFO
TA_TPRI 待ちタスクのキューイングは優先度順
TA_INHERIT 優先度継承プロトコル
TA_CEILING 優先度上限プロトコル
TA_DSNAME DSオブジェクト名称を指定する
TA_NODISWAI tk_dis_wai による待ち禁止を拒否する

TA_TFIFO の場合、ミューテックスのタスクの待ち行列はFIFOとなる。TA_TPRI, TA_INHERIT, TA_CEILING では、タスクの優先度順となる。TA_INHERIT では優先度継承プロトコル、TA_CEILING では優先度上限プロトコルが適用される。

TA_CEILING の場合のみ ceilpri が有効となり、ミューテックスの上限優先度を設定する。

TA_DSNAME を指定した場合に dsname が有効となり、DSオブジェクト名称として設定される。DSオブジェクト名称はデバッガがオブジェクトを識別するために使用され、T-Kernel/DSのシステムコール td_ref_dsnametd_set_dsname からのみ操作可能である。詳細は td_ref_dsnametd_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname が無視され、td_ref_dsnametd_set_dsname が、E_OBJ エラーとなる。

#define TA_TFIFO        0x00000000      /* 待ちタスクをFIFOで管理 */
#define TA_TPRI         0x00000001      /* 待ちタスクを優先度順で管理 */
#define TA_INHERIT      0x00000002      /* 優先度継承プロトコル */
#define TA_CEILING      0x00000003      /* 優先度上限プロトコル */
#define TA_DSNAME       0x00000040      /* DSオブジェクト名称を指定 */
#define TA_NODISWAI     0x00000080      /* 待ち禁止拒否 */

tk_del_mtx - ミューテックス削除

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_del_mtx (ID mtxid );

パラメータ

ID mtxid Mutex IDミューテックスID

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mtxid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mtxid のミューテックスが存在しない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mtxid で示されたミューテックスを削除する。

本システムコールの発行により、対象ミューテックスのID番号および管理ブロック用の領域は解放される。

対象ミューテックスにおいてロック待ちしているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。

ミューテックスが削除されると、そのミューテックスをロックしているタスクにとっては、ロックしているミューテックスが減ることになる。したがって、削除されるミューテックスが TA_INHERIT または TA_CEILING 属性の場合には、ロックしていたタスクの優先度が変更される場合がある。

tk_loc_mtx - ミューテックスのロック

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_loc_mtx (ID mtxid , TMO tmout );

パラメータ

ID mtxid Mutex IDミューテックスID
TMO tmout Timeoutタイムアウト指定(ミリ秒)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mtxid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mtxid のミューテックスが存在しない)
E_PAR パラメータエラー(tmout≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象ミューテックスが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)
E_ILUSE 不正使用(多重ロック、上限優先度違反)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mtxid のミューテックスをロックする。ミューテックスがロックできれば、本システムコールの発行タスクは待ち状態に入らず、実行を継続する。この場合、そのミューテックスはロック状態になる。ロックできなければ、本システムコールを発行したタスクは待ち状態に入る。すなわち、そのミューテックスに対する待ち行列につながれる。

tmout により待ち時間の最大値(タイムアウト値)を指定することができる。待ち解除の条件が満足されない(ロックが解除されない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

tmout としては、正の値のみを指定することができる。tmout の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。

tmout として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、ロックできなくても待ちに入らず E_TMOUT を返す。また、tmout として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにロックできるまで待ち続ける。

自タスクがすでに対象ミューテックスをロックしていた場合には、E_ILUSE(多重ロック)を返す。

対象ミューテックスが TA_CEILING 属性の場合、自タスクのベース優先度[1]が対象ミューテックスの上限優先度より高い場合には E_ILUSE(上限優先度違反)を返す。

補足事項

  • TA_INHERIT 属性のミューテックスの場合

    自タスクがロック待ち状態になる場合、そのミューテックスをロックしているタスクの現在優先度が自タスクより低ければ、ロックしているタスクの優先度を自タスクと同じ優先度まで引き上げる。ロックを待っているタスクがロックを獲得せずに待ちを終了した場合(タイムアウトなど)、そのミューテックスをロック中のタスクの優先度を、次の内の最も高い優先度まで引き下げる。ただし、この優先度の引き下げを行うか否かは実装依存である。

    1. そのミューテックスでロック待ちしているタスクの現在優先度の内の最も高い優先度。

    2. そのミューテックスをロック中のタスクがロックしている他のすべてのミューテックスの内の最も高い優先度。

    3. ロック中のタスクのベース優先度。

  • TA_CEILING 属性のミューテックスの場合

    自タスクがロックを獲得した場合、自タスクの現在優先度がミューテックスの上限優先度より低ければ、自タスクの優先度をミューテックスの上限優先度まで引き上げる。

tk_loc_mtx_u - ミューテックスのロック(マイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_loc_mtx_u (ID mtxid , TMO_U tmout_u );

パラメータ

ID mtxid Mutex IDミューテックスID
TMO_U tmout_u Timeoutタイムアウト指定(マイクロ秒)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mtxid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mtxid のミューテックスが存在しない)
E_PAR パラメータエラー(tmout_u≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象ミューテックスが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)
E_ILUSE 不正使用(多重ロック、上限優先度違反)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

以下のサービスプロファイルが有効に設定されている場合に限り、本システムコールはサポートされる。

TK_SUPPORT_USEC マイクロ秒命令をサポート

解説

tk_loc_mtx のパラメータである tmout を64ビットマイクロ秒単位の tmout_u としたシステムコールである。

パラメータが tmout_u となった点を除き、本システムコールの仕様は tk_loc_mtx と同じである。詳細は tk_loc_mtx の説明を参照のこと。

μT-Kernel 1.0との差異

T-Kernel 2.0仕様に基づき新たに追加されたAPIである。

tk_unl_mtx - ミューテックスのアンロック

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_unl_mtx (ID mtxid );

パラメータ

ID mtxid Mutex IDミューテックスID

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mtxid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mtxid のミューテックスが存在しない)
E_ILUSE 不正使用(自タスクがロックしたミューテックスではない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mtxid のミューテックスのロックを解除する。

ロック待ちしているタスクがあれば、待ち行列の先頭のタスクの待ちを解除し、そのタスクをロック獲得状態にする。

自タスクがロックしていないミューテックスを指定した場合、E_ILUSE を返す。

補足事項

ロック解除したミューテックスが TA_INHERIT または TA_CEILING 属性の場合、次のようにタスク優先度を引き下げる必要がある。

ロックを解除することにより、自タスクがロックしているミューテックスがすべてなくなった場合は、自タスクの優先度をベース優先度まで引き下げる。

自タスクがロック中のミューテックスが残っている場合、自タスクの優先度を次の内の最も高い優先度まで引き下げる。

  1. 自タスクがロックしている TA_INHERIT 属性を持つミューテックスの待ち行列につながれているタスクの現在優先度の中で最も高い優先度

  2. 自タスクがロックしている TA_CEILING 属性を持つミューテックスに設定されている上限優先度の中で最も高い優先度

  3. 自タスクのベース優先度

ただし、ロック中のミューテックスが残っている場合の優先度の引き下げを行うか否かは実装依存である。

ミューテックスをロックした状態でタスクを終了した(休止状態(DORMANT)または未登録状態(NON-EXISTENT)になった)場合、当該タスクがロックしているすべてのミューテックスは自動的にロック解除される。

tk_ref_mtx - ミューテックス状態参照

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ref_mtx (ID mtxid , T_RMTX *pk_rmtx );

パラメータ

ID mtxid Mutex IDミューテックスID
T_RMTX* pk_rmtx Packet to Refer Mutex Statusミューテックス状態を返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード

pk_rmtx の内容

void* exinf Extended Information拡張情報
ID htsk Locking Task IDロックしているタスクのID
ID wtsk Lock Waiting Task IDロック待ちタスクのID
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mtxid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mtxid のミューテックスが存在しない)
E_PAR パラメータエラー(pk_rmtx が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mtxid で示された対象ミューテックスの各種の状態を参照し、リターンパラメータとしてロック中のタスク(htsk)、ロック待ちタスク(wtsk)、拡張情報(exinf) を返す。

htsk は、このミューテックスをロックしているタスクのIDを示す。ロックしているタスクがない場合は htsk=0となる。

wtsk は、このミューテックスで待っているタスクのIDを示す。複数のタスクが待っている場合には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は wtsk=0となる。

対象ミューテックスが存在しない場合には、エラー E_NOEXS となる。

メッセージバッファ

メッセージバッファは、可変長のメッセージを受渡しすることにより、同期と通信を行うためのオブジェクトである。メッセージバッファ機能には、メッセージバッファを生成/削除する機能、メッセージバッファに対してメッセージを送信/受信する機能、メッセージバッファの状態を参照する機能が含まれる。メッセージバッファはID番号で識別されるオブジェクトである。メッセージバッファのID番号をメッセージバッファIDと呼ぶ。

メッセージバッファは、メッセージの送信を待つタスクの待ち行列(送信待ち行列)とメッセージの受信を待つタスクの待ち行列(受信待ち行列)を持つ。また、送信されたメッセージを格納するためのメッセージバッファ領域を持つ。メッセージを送信する側(イベントを知らせる側)では、送信したいメッセージをメッセージバッファにコピーする。メッセージバッファ領域の空き領域が足りなくなった場合、メッセージバッファ領域に十分な空きができるまでメッセージバッファへの送信待ち状態になる。

メッセージバッファへの送信待ち状態になったタスクは、そのメッセージバッファの送信待ち行列につながれる。一方、メッセージを受信する側(イベントを待つ側)では、メッセージバッファに入っているメッセージを一つ取り出す。メッセージバッファにメッセージが入っていない場合は、次にメッセージが送られてくるまでメッセージバッファからの受信待ち状態になる。メッセージバッファからの受信待ち状態になったタスクは、そのメッセージバッファの受信待ち行列につながれる。

メッセージバッファ領域のサイズを0にすることで、同期メッセージ機能を実現することができる。すなわち、送信側のタスクと受信側のタスクが、それぞれ相手のタスクがシステムコールを呼び出すのを待ち合わせ、両者がシステムコールを呼び出した時点で、メッセージの受渡しが行われる。

注意補足事項
 

メッセージバッファ領域のサイズを0にした場合の、メッセージバッファの動作を図3の例を用いて説明する。この図で、タスクAとタスクBは非同期に実行しているものとする。

  • もしタスクAが先に tk_snd_mbf を呼び出した場合には、タスクBが tk_rcv_mbf を呼び出すまでタスクAは待ち状態となる。この時タスクAは、メッセージバッファへの送信待ち状態になっている(図3(a))。

  • 逆にタスクBが先に tk_rcv_mbf を呼び出した場合には、タスクAが tk_snd_mbf を呼び出すまでタスクBは待ち状態となる。この時タスクBは、メッセージバッファからの受信待ち状態になっている(図3(b))。

  • タスクAが tk_snd_mbf を呼び出し、タスクBが tk_rcv_mbf を呼び出した時点で、タスクAからタスクBへメッセージの受渡しが行われる。その後は、両タスクとも実行できる状態となる。

図 3. メッセージバッファによる同期通信

メッセージバッファへの送信を待っているタスクは、待ち行列につながれている順序でメッセージを送信する。例えば、あるメッセージバッファに対して40バイトのメッセージを送信しようとしているタスクAと、10バイトのメッセージを送信しようとしているタスクBが、この順で待ち行列につながれている時に、別のタスクによるメッセージの受信により20バイトの空き領域ができたとする。このような場合でも、タスクAがメッセージを送信するまで、タスクBはメッセージを送信できない。

メッセージバッファは、可変長のメッセージをコピーして受渡しする。メールボックスとの違いは、メッセージをコピーすることである。

メッセージバッファは、リングバッファで実装することを想定している。

tk_cre_mbf - メッセージバッファ生成

C言語インタフェース

#include <tk/tkernel.h>

ID mbfid = tk_cre_mbf (CONST T_CMBF *pk_cmbf );

パラメータ

CONST T_CMBF* pk_cmbf Packet to Create Message Bufferメッセージバッファ生成情報

pk_cmbf の内容

void* exinf Extended Information拡張情報
ATR mbfatr Message Buffer Attributeメッセージバッファ属性
SZ bufsz Buffer Sizeメッセージバッファのサイズ(バイト数)
INT maxmsz Max Message Sizeメッセージの最大長(バイト数)
UB dsname[8] DS Object nameDSオブジェクト名称
void* bufptr Buffer Pointerユーザバッファポインタ
──(以下に実装独自に他の情報を追加してもよい)──

リターンパラメータ

ID mbfid Message Buffer IDメッセージバッファID
またはError Codeエラーコード

エラーコード

E_NOMEM メモリ不足(管理ブロックやリングバッファ用の領域が確保できない)
E_LIMIT メッセージバッファの数がシステムの上限を超えた
E_RSATR 予約属性(mbfatr が不正あるいは利用できない)
E_PAR パラメータエラー(pk_cmbf が不正, bufsz, maxmsz が負または不正, bufptr が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

TK_SUPPORT_USERBUF TA_USERBUFのメッセージバッファ属性指定が可能
TK_SUPPORT_AUTOBUF バッファの自動割り当て(TA_USERBUFのメッセージバッファ属性指定なし)が可能
TK_SUPPORT_DISWAI メッセージバッファ属性としてTA_NODISWAI(待ち禁止の拒否)が指定可能
TK_SUPPORT_DSNAME TA_DSNAMEのメッセージバッファ属性指定が可能

解説

メッセージバッファを生成しメッセージバッファID番号を割り当てる。具体的には、生成するメッセージバッファに対して管理ブロックを割り付ける。また、bufsz の情報を元に、メッセージキュー(受信されるのを待つメッセージの待ち行列) として利用するためのリングバッファの領域を確保する。

メッセージバッファは、可変長メッセージの送受信の管理を行うオブジェクトである。メールボックス(mbx)との違いは、送信時と受信時に可変長のメッセージ内容がコピーされるということである。また、バッファが一杯の場合に、メッセージ送信側も待ち状態に入る機能がある。

exinf は、対象メッセージバッファに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_mbf で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf に入れる。カーネルでは exinf の内容について関知しない。

mbfatr は、下位側がシステム属性を表し、上位側が実装独自属性を表す。mbfatr のシステム属性の部分では、次のような指定を行う。

mbfatr := (TA_TFIFO || TA_TPRI) | [TA_DSNAME] | [TA_USERBUF] | [TA_NODISWAI]

TA_TFIFO 送信待ちタスクのキューイングはFIFO
TA_TPRI 送信待ちタスクのキューイングは優先度順
TA_DSNAME DSオブジェクト名称を指定する
TA_USERBUF メッセージバッファ領域としてユーザが指定した領域を利用する
TA_NODISWAI tk_dis_wai による待ち禁止を拒否する

TA_TFIFO, TA_TPRI では、バッファが一杯の場合にメッセージを送信するタスクがメッセージバッファの待ち行列に並ぶ際の並び方を指定することができる。属性が TA_TFIFO であればタスクの待ち行列はFIFOとなり、属性が TA_TPRI であればタスクの待ち行列はタスクの優先度順となる。なお、メッセージキューの順序はFIFOのみである。

メッセージ受信待ちのタスクの待ち行列の順序はFIFOのみである。

TA_USERBUFを指定した場合にbufptrが有効になり、bufptrを先頭とするbufszバイトのメモリ領域をメッセージバッファ領域として使用する。この場合、メッセージバッファ領域はカーネルで用意しない。TA_USERBUFを指定しなかった場合はbufptrは無視され、メッセージバッファ領域はカーネルが確保する

TA_DSNAME を指定した場合に dsname が有効となり、DSオブジェクト名称として設定される。DSオブジェクト名称はデバッガがオブジェクトを識別するために使用され、T-Kernel/DSのシステムコール td_ref_dsnametd_set_dsname からのみ操作可能である。詳細は td_ref_dsnametd_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname が無視され、td_ref_dsnametd_set_dsname が、E_OBJ エラーとなる。

#define TA_TFIFO        0x00000000      /* 送信待ちタスクをFIFOで管理 */
#define TA_TPRI         0x00000001      /* 送信待ちタスクを優先度順で管理 */
#define TA_USERBUF      0x00000020      /* ユーザバッファポインタを指定 */
#define TA_DSNAME       0x00000040      /* DSオブジェクト名称を指定 */
#define TA_NODISWAI     0x00000080      /* 待ち禁止拒否 */

補足事項

送信待ちのタスクが複数あった場合、バッファの空きができて送信待ちが解除されるのは常に待ち行列の順となる。

例えば、30バイトのメッセージを送信しようとしているタスクAと、10バイトのメッセージを送信しようとしているタスクBがA-Bの順で待っていた場合、メッセージバッファに20バイトの空きができてもAのタスクを追い越してBのタスクが先に送信することはない。

メッセージキューを入れるリングバッファの中には、一つ一つのメッセージを管理する情報も入るため、bufsz で指定されたリングバッファのサイズとキューに入るメッセージのサイズの合計とは、一般には一致しない。後者の方が小さい値をとるのが普通である。その意味で、bufsz の情報は厳密な意味をもつものではない。

bufsz=0のメッセージバッファを生成することは可能である。この場合、このメッセージバッファでは送受信側が完全に同期した通信を行うことになる。すなわち、tk_snd_mbftk_rcv_mbf の一方のシステムコールが先に実行されると、それを実行したタスクは待ち状態となる。もう一方のシステムコールが実行された段階で、メッセージの受け渡し(コピー)が行われ、その後双方のタスクが実行を再開する。

bufsz=0のメッセージバッファの場合、具体的な動作は次のようになる。

  1. [図4]で、タスクAとタスクBは非同期に動いている。もし、タスクAが先に(1)に到達し、tk_snd_mbf(mbfid) を実行した場合には、タスクBが(2)に到達するまでタスクAはメッセージ送信待ち状態になる。この状態のタスクAを対象として tk_ref_tsk を発行すると、tskwaitTTW_SMBF となる。逆に、タスクBが先に(2)に到達し、tk_rcv_mbf(mbfid) を実行した場合には、タスクAが(1)に到達するまでタスクBはメッセージ受信待ち状態になる。この状態のタスクBを対象として tk_ref_tsk を発行すると、tskwaitTTW_RMBF となる。

  2. タスクAが tk_snd_mbf(mbfid) を実行し、かつタスクBが tk_rcv_mbf(mbfid) を実行した時点でタスクAからタスクBにメッセージが送信され、どちらのタスクも待ち解除となって実行を再開する。

図 4. bufsz=0のメッセージバッファを使った同期式通信

T-Kernel 2.0との差異

T_CMBFのメンバbufszの型がINTからSZに変更されている。TA_USERBUFbufptrが追加されている。

μT-Kernel 1.0との差異

T_CMBFのメンバbufszの型がWからSZに変更されている。

移植ガイドライン

T_CMBFのメンバmaxmszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。

T-Kernel 2.0にはTA_USERBUFbufptrが存在しない。このため、この機能を使っている場合はT-Kernel 2.0への移植の際に修正が必要となるが、正しくbufszを設定してあれば、TA_USERBUFbufptrを削除するだけで移植ができる。

tk_del_mbf - メッセージバッファ削除

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_del_mbf (ID mbfid );

パラメータ

ID mbfid Message Buffer IDメッセージバッファID

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mbfid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mbfid のメッセージバッファが存在しない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mbfid で示されたメッセージバッファを削除する。

本システムコールの発行により、対象メッセージバッファのID番号および管理ブロック用の領域およびメッセージを入れるバッファ領域は解放される。

対象メッセージバッファにおいてメッセージ受信またはメッセージ送信を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。また、対象メッセージバッファの中にメッセージが残っている場合でも、エラーとはならず、メッセージバッファの削除が行われ、中にあったメッセージは消滅する。

tk_snd_mbf - メッセージバッファへ送信

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_snd_mbf (ID mbfid , CONST void *msg , INT msgsz , TMO tmout );

パラメータ

ID mbfid Message Buffer IDメッセージバッファID
CONST void* msg Send Message送信メッセージの先頭アドレス
INT msgsz Send Message Size送信メッセージのサイズ(バイト数)
TMO tmout Timeoutタイムアウト指定(ミリ秒)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mbfid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mbfid のメッセージバッファが存在しない)
E_PAR パラメータエラー(msgsz≦0, msgszmaxmsz, msg が不正, tmout≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象メッセージバッファが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×(※条件により可能)

解説

tk_snd_mbf では、mbfid で示されたメッセージバッファに対して、msg のアドレスに入っているメッセージを送信する。メッセージのサイズは msgsz で指定される。すなわち、msg 以下の msgsz バイトが、mbfid で指定されたメッセージバッファのメッセージキューにコピーされる。メッセージキューは、リングバッファによって実現されることを想定している。

msgsz が、tk_cre_mbf で指定した maxmsz よりも大きい場合は、エラー E_PAR となる。

バッファの空き領域が少なく、msg のメッセージをメッセージキューに入れられない場合、本システムコールを発行したタスクはメッセージ送信待ち状態となり、バッファの空きを待つための待ち行列(送信待ち行列)につながれる。待ち行列の順序は tk_cre_mbf 時の指定によりFIFOまたはタスク優先度順となる。

tmout により待ち時間の最大値(タイムアウト値)を指定することができる。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(バッファに十分な空き領域ができない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

tmout としては、正の値のみを指定することができる。tmout の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。

tmout として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、バッファに十分な空きがない場合は待ちに入らず E_TMOUT を返す。また、tmout として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにバッファに空きができるまで待ち続ける。

長さが0のメッセージは送信することができない。msgsz≦0の場合には、エラー E_PAR となる。

タスク独立部やディスパッチ禁止状態から実行した場合はエラー E_CTX となるが、tmoutTMO_POL の場合は、実装によってはタスク独立部やディスパッチ禁止状態から実行することができる場合がある。

移植ガイドライン

msgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送れるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_snd_mbf_u - メッセージバッファへ送信(マイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_snd_mbf_u (ID mbfid , CONST void *msg , INT msgsz , TMO_U tmout_u );

パラメータ

ID mbfid Message Buffer IDメッセージバッファID
CONST void* msg Send Message送信メッセージの先頭アドレス
INT msgsz Send Message Size送信メッセージのサイズ(バイト数)
TMO_U tmout_u Timeoutタイムアウト指定(マイクロ秒)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mbfid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mbfid のメッセージバッファが存在しない)
E_PAR パラメータエラー(msgsz≦0, msgszmaxmsz, msg が不正, tmout_u≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象メッセージバッファが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×(※条件により可能)

関連するサービスプロファイル

以下のサービスプロファイルが有効に設定されている場合に限り、本システムコールはサポートされる。

TK_SUPPORT_USEC マイクロ秒命令をサポート

解説

tk_snd_mbf のパラメータである tmout を64ビットマイクロ秒単位の tmout_u としたシステムコールである。

パラメータが tmout_u となった点を除き、本システムコールの仕様は tk_snd_mbf と同じである。詳細は tk_snd_mbf の説明を参照のこと。

μT-Kernel 1.0との差異

T-Kernel 2.0仕様に基づき新たに追加されたAPIである。

移植ガイドライン

msgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送れるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_rcv_mbf - メッセージバッファから受信

C言語インタフェース

#include <tk/tkernel.h>

INT msgsz = tk_rcv_mbf (ID mbfid , void *msg , TMO tmout );

パラメータ

ID mbfid Message Buffer IDメッセージバッファID
void* msg Receive Message受信メッセージを入れるアドレス
TMO tmout Timeoutタイムアウト指定(ミリ秒)

リターンパラメータ

INT msgsz Receive Message Size受信したメッセージのサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_ID 不正ID番号(mbfid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mbfid のメッセージバッファが存在しない)
E_PAR パラメータエラー(msg が不正, tmout≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象メッセージバッファが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tk_rcv_mbf では、mbfid で示されたメッセージバッファからメッセージを受信し、msg で指定した領域に入れる。すなわち、mbfid で指定されたメッセージバッファのメッセージキューの先頭のメッセージの内容を、msg 以下の msgsz バイトにコピーする。

mbfid で示されたメッセージバッファにまだメッセージが送信されていない場合(メッセージキューが空の場合) には、本システムコールを発行したタスクは待ち状態となり、メッセージの到着を待つ待ち行列(受信待ち行列)につながれる。受信待ちタスクの待ち行列はFIFOのみである。

tmout により待ち時間の最大値(タイムアウト値)を指定することができる。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(メッセージが到着しない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

tmout としては、正の値のみを指定することができる。tmout の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。

tmout として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、メッセージがない場合にも待ちに入らず E_TMOUT を返す。また、tmout として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにメッセージが到着するまで待ち続ける。

tk_rcv_mbf_u - メッセージバッファから受信(マイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

INT msgsz = tk_rcv_mbf_u (ID mbfid , void *msg , TMO_U tmout_u );

パラメータ

ID mbfid Message Buffer IDメッセージバッファID
void* msg Receive Message受信メッセージを入れるアドレス
TMO_U tmout_u Timeoutタイムアウト指定(マイクロ秒)

リターンパラメータ

INT msgsz Receive Message Size受信したメッセージのサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_ID 不正ID番号(mbfid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mbfid のメッセージバッファが存在しない)
E_PAR パラメータエラー(msg が不正, tmout_u≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象メッセージバッファが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

以下のサービスプロファイルが有効に設定されている場合に限り、本システムコールはサポートされる。

TK_SUPPORT_USEC マイクロ秒命令をサポート

解説

tk_rcv_mbf のパラメータである tmout を64ビットマイクロ秒単位の tmout_u としたシステムコールである。

パラメータが tmout_u となった点を除き、本システムコールの仕様は tk_rcv_mbf と同じである。詳細は tk_rcv_mbf の説明を参照のこと。

μT-Kernel 1.0との差異

T-Kernel 2.0仕様に基づき新たに追加されたAPIである。

tk_ref_mbf - メッセージバッファ状態参照

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ref_mbf (ID mbfid , T_RMBF *pk_rmbf );

パラメータ

ID mbfid Message Buffer IDメッセージバッファID
T_RMBF* pk_rmbf Packet to Refer Message Buffer Statusメッセージバッファ状態を返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード

pk_rmbf の内容

void* exinf Extended Information拡張情報
ID wtsk Wait Task Information受信待ちタスクのID
ID stsk Send Task Information送信待ちタスクのID
INT msgsz Message Size次に受信されるメッセージのサイズ(バイト数)
SZ frbufsz Free Buffer Size空きバッファのサイズ(バイト数)
INT maxmsz Maximum Message Sizeメッセージの最大長(バイト数)
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_OK 正常終了
E_ID 不正ID番号(mbfid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(mbfid のメッセージバッファが存在しない)
E_PAR パラメータエラー(pk_rmbf が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mbfid で示された対象メッセージバッファの各種の状態を参照し、リターンパラメータとして送信待ちタスクのID(stsk)、次に受信されるメッセージのサイズ(msgsz)、空きバッファのサイズ(frbufsz)、メッセージの最大長(maxmsz)、受信待ちタスクのID(wtsk)、拡張情報(exinf) を返す。

wtsk は、このメッセージバッファで受信待ちしているタスクのIDを示す。また、stsk は送信待ちしているタスクのIDを示す。このメッセージバッファで複数のタスクが待っている場合には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は0となる。

対象メッセージバッファが存在しない場合には、エラー E_NOEXS となる。

msgsz には、メッセージキューの先頭のメッセージ(次に受信されるメッセージ)のサイズが返る。メッセージキューにメッセージが無い場合には、msgsz=0となる。なお、サイズが0のメッセージを送ることはできない。

どんな場合でも、msgsz=0とwtsk=0の少なくとも一方は成り立つ。

frbufsz は、メッセージキューを構成するリングバッファの空き領域のサイズを示すものである。この値は、あとどの程度の量のメッセージを送信できるかを知る手掛かりになる。

maxmsz には、tk_cre_mbf で指定したメッセージの最大長が返される。

T-Kernel 2.0との差異

T_RMBFのメンバfrbufszの型がINTからSZに変更されている。

ランデブ

ランデブ機能は、複数のタスクがサーバとクライアントの関係にある場合に、それらのタスク間での同期通信を行う機能である。具体的には、クライアント側タスクとサーバ側タスクの双方が処理の受付を待ち合わせる機能、クライアント側タスクからサーバ側タスクに処理を依頼するメッセージ(呼出メッセージ)を送る機能、サーバ側タスクの処理の完了をクライアント側タスクが待つ機能、サーバ側タスクからクライアント側タスクに処理結果のメッセージ(返答メッセージ)を返す機能が含まれる。ランデブのシステムコールを使うことにより、上記のような複数の一連の処理を簡単な手順で実現できる。ランデブ機能は、ランデブポートと呼ばれるオブジェクトの上で動作する。

図 5. クライアントタスクとサーバタスクの間のランデブの動作

ランデブ機能には、ランデブポートを生成/削除する機能、ランデブポートに対して処理の依頼を行う機能(ランデブの呼出)、ランデブポートで処理依頼を受け付ける機能(ランデブの受付)、処理結果を返す機能(ランデブの終了)、受け付けた処理依頼を他のランデブポートに回送する機能(ランデブの回送)ランデブポートおよびランデブの状態を参照する機能が含まれる。ランデブポートはID番号で識別されるオブジェクトである。ランデブポートのID番号をランデブポートIDと呼ぶ。

ランデブポートに対して処理依頼を行う側のタスク(クライアント側のタスク)は、ランデブポートとランデブ条件、依頼する処理に関する情報を入れたメッセージ(これを呼出メッセージと呼ぶ)を指定して、ランデブの呼出を行う。一方、ランデブポートで処理依頼を受け付ける側のタスク(サーバ側のタスク)は、ランデブポートとランデブ条件を指定して、ランデブの受付を行う。

ランデブ条件は、ビットパターンで指定する。あるランデブポートに対して、呼び出したタスクのランデブ条件のビットパターンと、受け付けたタスクのランデブ条件のビットパターンをビット毎に論理積をとり、結果が0以外の場合にランデブが成立する。ランデブを呼び出したタスクは、ランデブが成立するまでランデブ呼出待ち状態となる。逆に、ランデブを受け付けるタスクは、ランデブが成立するまでランデブ受付待ち状態となる。

ランデブが成立すると、ランデブを呼び出したタスクから受け付けたタスクへ、呼出メッセージが渡される。ランデブを呼び出したタスクはランデブ終了待ち状態へ移行し、依頼した処理が完了するのを待つ。一方、ランデブを受け付けたタスクは待ち解除され、依頼された処理を行う。ランデブを受け付けたタスクが依頼された処理を完了すると、処理結果を返答メッセージの形で呼び出したタスクに渡し、ランデブを終了する。この時点で、ランデブを呼び出したタスクが、ランデブ終了待ち状態から待ち解除される。

上記の動作を図6の例を用いて説明する。この図で、タスクAとタスクBは非同期に実行しているものとする。

図 6. ランデブの動作

ランデブポートは、ランデブ呼出待ち状態のタスクをつなぐための呼出待ち行列と、ランデブ受付待ち状態のタスクをつなぐための受付待ち行列を持つ。それに対して、ランデブが成立した後は、ランデブした双方のタスクはランデブポートから切り離される。すなわち、ランデブポートは、ランデブ終了待ち状態のタスクをつなぐための待ち行列は持たない。また、ランデブを受け付け、依頼された処理を実行しているタスクに関する情報も持たない。

カーネルは、同時に成立しているランデブを識別するために、ランデブ番号と呼ばれるユニークな番号を付与する。ランデブ番号の付与方法は実装依存であるが、少なくとも、ランデブを呼び出したタスクを指定するための情報を含んでいなければならない。また、同じタスクが呼び出したランデブであっても、1回目のランデブと2回目のランデブで異なるランデブ番号が付与される。

注意補足事項
 

ランデブ番号の付与方法の一例として、ランデブを呼び出したタスクのID番号をランデブ番号の下位ビットとし、その上位ビットにシーケンシャルな番号を付加する方法がある。

注意仕様決定の理由
 

本機能の名称である「ランデブ(rendezvous)」は、クライアント側タスクとサーバ側タスクの両者が「待ち合わせ」を行うことに由来している。また、本機能の導入に際しては、Ada言語のランデブや、その元になったCSP(Communicating Sequential Processes)の影響を受けている。ただし、T-Kernelが提供するランデブ機能とAda言語のランデブの機能が同一というわけではない。

ランデブ機能は、他の同期・通信機能を組み合わせて実現することも可能であるが、返答を伴う通信を行う場合には、それ専用の機能を用意した方が、アプリケーションプログラムが書きやすくなる。

また、他の同期・通信機能を組み合わせるよりも効率を上げることができると考えられる。一例として、ランデブ機能は、メッセージの受渡しが終わるまで双方のタスクを待たせておくために、メッセージを格納するための領域が必要ないという利点がある。

同じタスクが呼び出したランデブであっても、ランデブ番号をできる限りユニークにしなければならないのは、次の理由による。ランデブが成立してランデブ終了待ち状態となっているタスクが、タイムアウトや待ち状態の強制解除などにより待ち解除された後、再度ランデブを呼び出してランデブが成立した場合を考える。この時、最初のランデブのランデブ番号と、後のランデブのランデブ番号が同一の値であると、最初のランデブを終了させようとした時に、ランデブ番号が同一であるために後のランデブが終了してしまう。 2つのランデブに異なるランデブ番号を付与し、ランデブ終了待ち状態のタスクに待ち対象のランデブ番号を記憶しておけば、最初のランデブを終了させようとした時にエラーとすることができる。

tk_cre_por - ランデブポート生成

C言語インタフェース

#include <tk/tkernel.h>

ID porid = tk_cre_por (CONST T_CPOR *pk_cpor );

パラメータ

CONST T_CPOR* pk_cpor Packet to Create Portランデブポートの生成情報

pk_cpor の内容

void* exinf Extended Information拡張情報
ATR poratr Port Attributeランデブポート属性
INT maxcmsz Max Call Message Size呼出時のメッセージの最大長(バイト数)
INT maxrmsz Max Reply Message Size返答時のメッセージの最大長(バイト数)
UB dsname[8] DS Object nameDSオブジェクト名称
──(以下に実装独自に他の情報を追加してもよい)──

リターンパラメータ

ID porid Port IDランデブポートID
またはError Codeエラーコード

エラーコード

E_NOMEM メモリ不足(管理ブロック用の領域が確保できない)
E_LIMIT ランデブポートの数がシステムの上限を超えた
E_RSATR 予約属性(poratr が不正あるいは利用できない)
E_PAR パラメータエラー(pk_cpor が不正, maxcmsz, maxrmsz が負または不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

TK_SUPPORT_DISWAI ランデブポート属性として待ち禁止の拒否(TA_NODISWAI)が指定可能
TK_SUPPORT_DSNAME TA_DSNAMEのメッセージバッファ属性指定が可能

解説

ランデブポートを生成しランデブポートID番号を割り当てる。具体的には、生成されたランデブポートに対して管理ブロックを割り付ける。ランデブポートは、ランデブを実現するためのプリミティブとなるオブジェクトである。

exinf は、対象ランデブポートに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_por で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf に入れる。カーネルでは exinf の内容について関知しない。

poratr は、下位側がシステム属性を表し、上位側が実装独自属性を表す。poratr のシステム属性の部分では、次のような指定を行う。

poratr:= (TA_TFIFO || TA_TPRI) | [TA_DSNAME] | [TA_NODISWAI]

TA_TFIFO 呼出待ちタスクのキューイングはFIFO
TA_TPRI 呼出待ちタスクのキューイングは優先度順
TA_DSNAME DSオブジェクト名称を指定する
TA_NODISWAI tk_dis_wai による待ち禁止を拒否する

TA_TFIFO, TA_TPRI では、ランデブ呼出待ちのタスクの待ち行列の並び順を指定する。ランデブ受付待ちのタスクの待ち行列はFIFOのみである。

TA_DSNAME を指定した場合に dsname が有効となり、DSオブジェクト名称として設定される。DSオブジェクト名称はデバッガがオブジェクトを識別するために使用され、T-Kernel/DSのシステムコール td_ref_dsnametd_set_dsname からのみ操作可能である。詳細は td_ref_dsnametd_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname が無視され、td_ref_dsnametd_set_dsname が、E_OBJ エラーとなる。

#define TA_TFIFO        0x00000000      /* 待ちタスクをFIFOで管理 */
#define TA_TPRI         0x00000001      /* 待ちタスクを優先度順で管理 */
#define TA_DSNAME       0x00000040      /* DSオブジェクト名称を指定 */
#define TA_NODISWAI     0x00000080      /* 待ち禁止拒否 */

maxcmsz にはランデブの呼出時に渡すメッセージの最大サイズ(バイト数)を指定する。maxcmsz に0を指定することも可能である。ただし、maxcmsz に0を指定した場合は、ランデブの呼出時に渡すメッセージのサイズは0に限定され、メッセージ無しでの同期にのみ使用されることになる。

maxrmsz にはランデブの返答時に渡すメッセージの最大サイズ(バイト数)を指定する。maxrmsz に0を指定することも可能である。ただし、maxrmsz に0を指定した場合はランデブの返答時に渡すメッセージのサイズは0に限定されることになる。

移植ガイドライン

T_CPORのメンバmaxcmsz, maxrmszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送れるメッセージ最大長が32767バイトまでに制限される可能性がある。

tk_del_por - ランデブポート削除

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_del_por (ID porid );

パラメータ

ID porid Port IDランデブポートID

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

porid で示されたランデブポートを削除する。

本システムコールの発行により、対象ランデブポートのID番号および管理ブロック用の領域は解放される。

対象ランデブポートにおいてランデブ受付(tk_acp_por)や呼出(tk_cal_por)を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。

tk_del_por によりランデブポートが削除されても、既にランデブ成立済のタスクに対しては、影響を与えない。ランデブ受付側タスク(待ち状態ではない) には何も通知されないし、ランデブ呼出側タスク(ランデブ終了待ち状態) の状態もそのままである。ランデブ受付側タスクが tk_rpl_rdv を行う時に、ランデブ成立に使ったランデブポートが既に削除されていても、tk_rpl_rdv は正常に実行される。

tk_cal_por - ランデブポートに対するランデブの呼出

C言語インタフェース

#include <tk/tkernel.h>

INT rmsgsz = tk_cal_por (ID porid , UINT calptn , void *msg , INT cmsgsz , TMO tmout );

パラメータ

ID porid Port IDランデブポートID
UINT calptn Call Bit Pattern呼出側選択条件を表すビットパターン
void* msg Messageメッセージを入れるアドレス
INT cmsgsz Call Message Size呼出メッセージのサイズ(バイト数)
TMO tmout Timeoutタイムアウト指定(ミリ秒)

リターンパラメータ

INT rmsgsz Reply Message Size返答メッセージのサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)
E_PAR パラメータエラー(cmsgsz<0, cmsgszmaxcmsz, calptn=0, msg が不正, tmout≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象ランデブポートが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

ランデブポートに対するランデブ呼出を行う。

tk_cal_por の具体的な動作は次のようになる。porid で指定したランデブポートにおいてランデブ受付待ち状態のタスクがあり、そのタスクと tk_cal_por 発行タスクとの間でランデブ成立条件が満たされた場合は、ランデブ成立となる。この場合、ランデブ受付待ちだったタスクは実行可能状態(READY)となり、tk_cal_por 発行タスクはランデブ終了待ちの状態になる。ランデブ終了待ちの状態になったタスクは、ランデブの相手のタスク(ランデブ受付タスク)が tk_rpl_rdv を実行することにより待ち状態が解除される。この時点で tk_cal_por のシステムコールが終了する。

porid で指定したランデブポートに受付待ちタスクが無かった場合や、受付待ちタスクがあってもランデブ成立条件が満たされなかった場合には、tk_cal_por 発行タスクはこのランデブポートの呼出側待ち行列に並びランデブ呼出待ちの状態となる。ランデブ呼出待ち行列の順序は、tk_cre_por の指定によりFIFOまたはタスク優先度順となる。

ランデブ成立条件は、受付側タスクの acpptn と呼出側タスクの calptn との論理積が0かどうかによって判定される。論理積が0でない場合にランデブ成立となる。calptn が0の場合は、決してランデブが成立しなくなるので、パラメータエラー E_PAR とする。

ランデブ成立時には、呼出側タスクから受付側タスクに対してメッセージ(呼出メッセージ)を送ることができる。呼出メッセージのサイズは cmsgsz で指定される。具体的には、呼出側タスクが tk_cal_por で指定した msg 以下の領域の cmsgsz バイトが、受付側タスクが tk_acp_por で指定した msg 以下の領域にコピーされる。

逆に、ランデブ終了時には、受付側タスクから呼出側タスクに対してメッセージ(返答メッセージ)を送ることができる。具体的には、受付側タスクが tk_rpl_rdv で指定した返答メッセージの内容が、呼出側タスクが tk_cal_por で指定した msg 以下の領域にコピーされる。また、返答メッセージのサイズ rmsgsz は、tk_cal_por のリターンパラメータとなる。結局、tk_cal_pormsg パラメータで指定されたメッセージ領域は、tk_rpl_rdv 実行の際に送られてくるメッセージによって破壊されることになる。

なお、ランデブが回送された場合は、tk_cal_por で指定した msg のアドレスから最大で maxrmsz の領域をバッファとして使用するため、その内容を破壊する可能性がある。したがって、tk_cal_por で要求したランデブが回送される可能性がある場合は、期待する返答メッセージのサイズにかかわらず、msg 以下に少なくとも maxrmsz のサイズの領域を確保しておかなければならない。(詳細は tk_fwd_por の項を参照)

cmsgsz が、tk_cre_por で指定した maxcmsz よりも大きい場合は、エラー E_PAR となる。このエラーはランデブ呼出待ち状態に入る前にチェックされ、エラーの場合、tk_cal_por を実行したタスクはランデブ呼出待ち状態には入らない。

tmout によりランデブが成立するまでの待ち時間の最大値(タイムアウト値)を指定することができる。タイムアウト指定が行なわれた場合、待ち解除の条件が満足されない(ランデブが成立しない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

tmout としては、正の値のみを指定することができる。tmout の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。

tmout として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、対象ランデブポートにランデブ受付待ちタスクが無いか、ランデブ成立条件が満たされない場合には、待ちに入らず E_TMOUT を返す。

tmout として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトすることなくランデブが成立するまで待ち続ける。

いずれにしても、tmout の指定はランデブ成立までの時間に関するタイムアウトを意味するものであり、ランデブ成立からランデブ終了までの時間には関係しない。

移植ガイドライン

calptnがUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。

cmsgsz, rmsgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送信または受信できるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_cal_por_u - ランデブポートに対するランデブの呼出(マイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

INT rmsgsz = tk_cal_por_u (ID porid , UINT calptn , void *msg , INT cmsgsz , TMO_U tmout_u );

パラメータ

ID porid Port IDランデブポートID
UINT calptn Call Bit Pattern呼出側選択条件を表すビットパターン
void* msg Messageメッセージを入れるアドレス
INT cmsgsz Call Message Size呼出メッセージのサイズ(バイト数)
TMO_U tmout_u Timeoutタイムアウト指定(マイクロ秒)

リターンパラメータ

INT rmsgsz Reply Message Size返答メッセージのサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)
E_PAR パラメータエラー(cmsgsz<0, cmsgszmaxcmsz, calptn=0, msg が不正, tmout_u≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象ランデブポートが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

以下のサービスプロファイルが有効に設定されている場合に限り、本システムコールはサポートされる。

TK_SUPPORT_USEC マイクロ秒命令をサポート

解説

tk_cal_por のパラメータである tmout を64ビットマイクロ秒単位の tmout_u としたシステムコールである。

パラメータが tmout_u となった点を除き、本システムコールの仕様は tk_cal_por と同じである。詳細は tk_cal_por の説明を参照のこと。

μT-Kernel 1.0との差異

T-Kernel 2.0仕様に基づき新たに追加されたAPIである。

移植ガイドライン

calptnがUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。

cmsgsz, rmsgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送信または受信できるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_acp_por - ランデブポートに対するランデブ受付

C言語インタフェース

#include <tk/tkernel.h>

INT cmsgsz = tk_acp_por (ID porid , UINT acpptn , RNO *p_rdvno , void *msg , TMO tmout );

パラメータ

ID porid Port IDランデブポートID
UINT acpptn Accept Bit Pattern受付側選択条件を表すビットパターン
RNO* p_rdvno Pointer to Rendezvous Numberリターンパラメータ rdvno を返す領域へのポインタ
void* msg Packet of Call Message呼出メッセージを入れるアドレス
TMO tmout Timeoutタイムアウト指定(ミリ秒)

リターンパラメータ

RNO rdvno Rendezvous Numberランデブ番号
INT cmsgsz Call Message Size呼出メッセージのサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)
E_PAR パラメータエラー(acpptn=0, msg が不正, tmout≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象ランデブポートが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

ランデブポートに対するランデブ受付を行う。

tk_acp_por の具体的な動作は次のようになる。porid で指定したランデブポートの呼出側待ち行列に入っているタスクと、このタスクとの間で、ランデブ成立条件が満たされた場合は、ランデブ成立となる。この場合、呼出側待ち行列にあったタスクは行列から外れ、ランデブ呼出待ち(ランデブ成立待ち)の状態からランデブ終了待ちの状態に変わる。tk_acp_por の発行タスクは、実行を継続する。

porid で指定したランデブポートの呼出側待ち行列にタスクが無かった場合や、タスクがあってもランデブ成立条件が満たされなかった場合、tk_acp_por の発行タスクはそのランデブポートに対するランデブ受付待ち状態になる。この時、既に別のタスクがランデブ受付待ち状態であったとしても、エラーとはならず、tk_acp_por を発行したタスクはランデブ受付待ち行列につながれる。また、一つのランデブポートを使って、複数のタスクが同時にランデブを行うことが可能である。そのため、porid で指定したランデブポートで別のタスクがランデブを行っている間に(前に成立したランデブに関する tk_rpl_rdv が実行される前に) に次のランデブを行っても、エラーとはならない。

ランデブ成立条件は、受付側タスクの acpptn と呼出側タスクの calptn との論理積が0かどうかによって判定される。論理積が0でない場合にランデブ成立となる。先頭のタスクが条件を満たさなければ、待ち行列の次のタスクについて順にチェックを行う。calptnacpptn に0以外の同じ値を指定すれば、条件が無い(無条件)のと同じになる。また、acpptn が0の場合は、決してランデブが成立しなくなるので、パラメータエラー E_PAR とする。ランデブ成立までの処理に関しては、ランデブ呼出側とランデブ受付側で完全に対称である。

ランデブ成立時には、呼出側タスクから受付側タスクに対して呼出メッセージを送ることができる。呼出側タスクが指定した呼出メッセージの内容は、受付側タスクが tk_acp_por で指定した msg 以下の領域にコピーされる。また、呼出メッセージのサイズ cmsgsz は、tk_acp_por のリターンパラメータとなる。

ランデブ受付側のタスクが、同時に複数のランデブを行うことも可能である。具体的には、tk_acp_por によりあるランデブを受け付けたタスクが、tk_rpl_rdv を実行する前に、もう一度 tk_acp_por を実行しても構わない。また、この時の tk_acp_por は、前と異なるランデブポートを対象としたものであっても、前と同じランデブポートを対象としたものであっても構わない。特殊な例であるが、ランデブ中のタスクが同じランデブポートに対してもう一度 tk_acp_por を実行してランデブが成立した場合、同一のタスクが同一のランデブポートに対して複数の(多重の)ランデブを行っているという状態になる。もちろん、この場合にランデブの相手(呼出側タスク)は異なっている。

tk_acp_por のリターンパラメータとして返される rdvno は、同時に成立している複数のランデブを区別するための情報であり、ランデブ終了時に tk_rpl_rdv のパラメータとして使用する。また、ランデブ回送時には tk_fwd_por のパラメータとして使用する。rdvno の具体的な内容は実装依存であるが、ランデブ成立相手の呼出側タスクを指定するための情報を含んでいるはずである。

tmout により待ち時間の最大値(タイムアウト値)を指定することができる。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(ランデブが成立しない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

tmout としては、正の値のみを指定することができる。tmout の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。

tmout として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、対象ランデブポートにランデブ呼出待ちタスクが無いか、ランデブ成立条件が満たされない場合には、待ちに入らず E_TMOUT を返す。また、tmout として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトすることなくランデブの成立まで待ち続ける。

補足事項

ランデブ受付側のタスクも待ち行列を作る機能は、同じ処理をするサーバを複数個並列に走らせるような時に有用である。また、ランデブポートをタスク独立にしたという特徴を活かすことができる。

ランデブを受け付けたタスクが、何らかの理由でランデブ終了前(tk_rpl_rdv 実行前) に異常終了したような場合は、tk_cal_por を実行したランデブ呼出側のタスクがランデブ終了待ち状態から解放されないまま残ることになる。このようなケースを避けるためには、ランデブ受付側タスクの異常終了時に tk_rpl_rdv または tk_rel_wai を実行し、ランデブがエラーで終了したことをランデブ呼出側のタスクにも通知しておく必要がある。

rdvno にはランデブ成立相手の呼出側タスクを指定する情報を含むが、その番号の割当て方法は、できるだけユニークになるように配慮しなければならない。同一タスク間のランデブであっても、1回目のランデブと2回目のランデブでは異なる rdvno を割り当てる必要がある。この配慮により、以下のような問題を回避できる。

tk_cal_por を実行してランデブ終了待ちのタスクが、tk_rel_waitk_ter_tsktk_sta_tsk 等によって強制的に待ち解除となり、再度 tk_cal_por を実行してランデブが成立した場合を考える。最初のランデブに対する rdvno と後のランデブに対する rdvno が同じ値であると、最初のランデブに対する tk_rpl_rdv によって後のランデブが終了してしまう。rdvno の割当てをユニークにし、ランデブ終了待ちタスクの側で期待する rdvno を覚えておけば、最初のランデブに対する tk_rpl_rdv のエラーを検出することができる。

rdvno の具体的な実現方法としては、たとえば、rdvno の下位バイトを呼出側タスクのID、上位バイトをシーケンシャルな番号とすればよい。

calptn, acpptn によるランデブ成立条件の機能を使えば、ランデブの選択受付(Adaのselectに相当)の機能が実現可能となる。Adaのselect文の例[図7]に相当する具体的な処理方法を[図8]に示す。

図 7. select文を使ったAdaのプログラム例

select
    when condition_A
        accept entry_A do ... end;
or
    when condition_B
        accept entry_B do ... end;
or
    when condition_C
        accept entry_C do ... end;
end select;

図 8. ランデブによるAdaのselect機能の実現方法

  • entry_A, entry_B, entry_C がそれぞれ一つのランデブポートに対応するのではなく、select文全体が一つのランデブポートに対応する。

  • entry_A, entry_B, entry_C を、calptn, acpptn の 20, 21, 22 のビットに対応させる。

  • Adaのプログラム例の中のselect文は、次のようになる。

    ptn := 0;
    if conditon_A then ptn := ptn + 2^0 endif;
    if conditon_B then ptn := ptn + 2^1 endif;
    if conditon_C then ptn := ptn + 2^2 endif;
    tk_acp_por(acpptn := ptn);
  • もし、プログラム例中のselect文以外に、select無しの単なるentry_Aのacceptがあれば、

    tk_acp_por(acpptn := 2^0);
    を実行すれば良い。また、entry_A, entry_B, entry_Cを無条件にORで待ちたい時は、
    tk_acp_por(acpptn := 2^2+2^1+2^0);
    を実行すれば良い。

  • 一方、これを呼び出す側は、entry_Aの呼出であれば

    tk_cal_por(calptn := 2^0);
    を実行し、entry_Cの呼出であれば
    tk_cal_por(calptn := 2^2);
    を実行すれば良い。

Adaの選択機能は受け付け側にしか用意されていないが、ランデブでは、calptn で複数のビットを指定することにより、呼出側に選択機能を持たせることも可能である。

仕様決定の理由

ランデブ成立条件に関して呼出側と受付側が全く対称であるにもかかわらず、tk_cal_portk_acp_por が別システムコールとなっているのは、ランデブ成立後の処理が異なるからである。すなわち、呼出側はランデブ成立後に待ち状態になるのに対して、受付側はランデブ成立後に実行可能状態(READY)となる。

移植ガイドライン

acpptnがUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。

cmsgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に受信できるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_acp_por_u - ランデブポートに対するランデブ受付(マイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

INT cmsgsz = tk_acp_por_u (ID porid , UINT acpptn , RNO *p_rdvno , void *msg , TMO_U tmout_u );

パラメータ

ID porid Port IDランデブポートID
UINT acpptn Accept Bit Pattern受付側選択条件を表すビットパターン
RNO* p_rdvno Pointer to Rendezvous Numberリターンパラメータ rdvno を返す領域へのポインタ
void* msg Packet of Call Message呼出メッセージを入れるアドレス
TMO_U tmout_u Timeoutタイムアウト指定(マイクロ秒)

リターンパラメータ

RNO rdvno Rendezvous Numberランデブ番号
INT cmsgsz Call Message Size呼出メッセージのサイズ(バイト数)
またはError Codeエラーコード

エラーコード

E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)
E_PAR パラメータエラー(acpptn=0, msg が不正, tmout_u≦(-2))
E_DLT 待ちオブジェクトが削除された(待ちの間に対象ランデブポートが削除)
E_RLWAI 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け)
E_DISWAI 待ち禁止による待ち解除
E_TMOUT ポーリング失敗またはタイムアウト
E_CTX コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

関連するサービスプロファイル

以下のサービスプロファイルが有効に設定されている場合に限り、本システムコールはサポートされる。

TK_SUPPORT_USEC マイクロ秒命令をサポート

解説

tk_acp_por のパラメータである tmout を64ビットマイクロ秒単位の tmout_u としたシステムコールである。

パラメータが tmout_u となった点を除き、本システムコールの仕様は tk_acp_por と同じである。詳細は tk_acp_por の説明を参照のこと。

μT-Kernel 1.0との差異

T-Kernel 2.0仕様に基づき新たに追加されたAPIである。

移植ガイドライン

acpptnがUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。

cmsgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に受信できるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_fwd_por - ランデブポートに対するランデブ回送

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_fwd_por (ID porid , UINT calptn , RNO rdvno , CONST void *msg , INT cmsgsz );

パラメータ

ID porid Port ID回送先のランデブポートID
UINT calptn Call Bit Pattern呼出側選択条件を表すビットパターン
RNO rdvno Rendezvous Number回送前のランデブ番号
CONST void* msg Call Message回送するメッセージを入れるアドレス
INT cmsgsz Call Message Size回送するメッセージのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)
E_PAR パラメータエラー(cmsgsz<0, cmsgsz>回送後の maxcmsz, cmsgsz>回送前の maxrmsz, calptn=0, msg が不正)
E_OBJ オブジェクトの状態が不正(rdvno が不正, 回送後の maxrmsz>回送前の maxrmsz)
E_CTX コンテキストエラー(タスク独立部から発行,実装依存)
E_DISWAI 待ち禁止による待ち解除

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

一旦受け付けたランデブを別のランデブポートに回送する。

このシステムコールを発行したタスク(タスクXとする)は、現在ランデブ中の状態(tk_acp_por を実行した後の状態)でなければならない。また、ランデブ相手の呼出側タスクはタスクY、tk_acp_por のリターンパラメータとして返されたランデブ番号は rdvno であるものとする。その状態で tk_fwd_por を実行すると、タスクXとタスクYとの間のランデブ状態が解除され、その後 porid で示される別のランデブポート(ランデブポートB)に対してタスクYがランデブ呼出を行ったのと同じ状況になる。

tk_fwd_por の具体的な動作は次のようになる。

  1. rdvno で示されるランデブを解除する。

  2. タスクYを、porid のランデブポートに対してランデブ呼出待ちの状態にする。この時、ランデブ成立のための呼出側選択条件を表すビットパターン calptn は、タスクYが tk_cal_por で指定したものではなく、タスクXが tk_fwd_por で指定したものが使用される。タスクYから見ると、ランデブ終了待ちの状態からランデブ呼出待ちの状態に戻ることになる。

  3. その後、porid のランデブポートに対するランデブが受け付けられれば、それを受け付けたタスクとタスクYとの間でランデブ成立となる。もちろん、porid のランデブポートに既にランデブ受付待ちタスクが存在し、ランデブ成立条件が満たされていれば、tk_fwd_por の実行により即座にランデブ成立となることもある。ここで、ランデブ成立時に受付側に送られるメッセージは、タスクYが tk_cal_por で指定したものではなく、タスクXが tk_fwd_por で指定したものが使用される(calptnと同様)。

  4. 新しいランデブが終了した際に tk_rpl_rdv で返されるメッセージは、タスクXが tk_fwd_por で指定した msg 以下の領域ではなく、タスクYが tk_cal_por で指定した msg 以下の領域にコピーされる。

基本的には、

tk_cal_por (porid=portA, calptn=ptnA, msg=mesA) の後で tk_fwd_por (porid=portB, calptn=ptnB, msg=mesB) が実行された状態」

と、

tk_cal_por (porid=portB, calptn=ptnB, msg=mesB) が実行された状態」

とは全く同じ状態になる。結果的に、カーネルとしてはランデブ回送の履歴を覚えておく必要はないことになる。

tk_fwd_por によってランデブ呼出待ち状態に戻ったタスクに対して tk_ref_tsk を実行した場合、tskwaitTTW_CAL となる。また、wid も回送先のランデブポートのID番号になる。

tk_fwd_por の実行は即座に終了する。このシステムコールで待ち状態になることはない。また、tk_fwd_por の実行が終わった後の tk_fwd_por 発行タスクは、回送前のランデブが成立したランデブポート、回送後のランデブポート(porid のランデブポート)、それらの上でランデブを行ったタスクのいずれとも無関係になる。

cmsgsz が、回送後のランデブポートの maxcmsz よりも大きい場合は、エラー E_PAR となる。このエラーはランデブの回送を行う前にチェックされる。エラーの場合、ランデブの回送は行われず、rdvno で示されるランデブも解除されない。

tk_fwd_por で指定した送信メッセージは、tk_fwd_por 実行時に他の領域(たとえば tk_cal_por で指定したメッセージ領域)にコピーされる。したがって、回送されたランデブが成立する前に tk_fwd_pormsg で示されるメッセージ領域の内容が変更されても、回送されたランデブはその影響を受けない。

tk_fwd_por でランデブを回送する場合、回送後のランデブポート(porid のランデブポート)の maxrmsz は、回送前のランデブの成立したランデブポートの maxrmsz と等しいか、それよりも小さくなければならない。回送後のランデブポートの maxrmsz が回送前のランデブポートの maxrmsz よりも大きかった場合は、回送先のランデブポートが不適当であるという意味で、E_OBJ のエラーとなる。ランデブ呼出側では、回送前のランデブポートの maxrmsz に合わせて返答メッセージ受信領域を用意しているため、ランデブの回送によって返答メッセージの最大サイズが大きくなると、呼出側に対して予期せぬ大きさの返答メッセージを返す可能性を生じ、問題を起こす。maxrmsz の大きなランデブポートにランデブを回送できないのは、このような理由による。

また、tk_fwd_por で送信するメッセージのサイズ cmsgsz についても、回送前のランデブの成立したランデブポートの maxrmsz と等しいか、それよりも小さくなければならない。これは、tk_fwd_por の実装方法として、tk_cal_por で指定したメッセージ領域を送信メッセージのバッファとして使うことを想定しているためである。cmsgsz が回送前のランデブポートの maxrmsz より大きかった場合には、E_PAR のエラーとなる。(詳細は【補足事項】を参照)

タスク独立部から tk_fwd_por, tk_rpl_rdv を発行する必要はないが、ディスパッチ禁止中あるいは割込み禁止中のタスクから tk_fwd_por, tk_rpl_rdv を発行することは可能である。この機能は、tk_fwd_portk_rpl_rdv と不可分に何らかの処理を行う場合に利用できる。なお、タスク独立部から tk_fwd_por, tk_rpl_rdv が発行された場合のエラーチェックは実装依存である。

tk_fwd_por により、ランデブ終了待ち状態であったタスクYがランデブ呼出待ちの状態に戻った場合、次にランデブが成立するまでのタイムアウトは、常に永久待ち(TMO_FEVR) として扱われる。

回送先のランデブポートは、前のランデブに使っていたランデブポート(rdvno のランデブが成立したランデブポート)と同じランデブポートであっても構わない。この場合は、tk_fwd_por によって、一旦受け付けたランデブの受付処理をとりやめることになる。ただし、この場合でも、呼出メッセージや calptn は、呼出側タスクが tk_cal_por で指定したものではなく、受付側タスクが tk_fwd_por で指定したものに変更される。

一旦回送されてきたランデブを、さらに回送することも可能である。

補足事項

tk_fwd_por を使ったサーバタスクの動作イメージを[図9][2] に示す。

図 9. tk_fwd_porを使ったサーバタスクの動作イメージ

一般に、tk_fwd_por を実行するのは、[図9]に示されるようなサーバ分配タスク(サーバの受け付けた処理を別のタスクに分配するためのタスク)である。したがって、tk_fwd_por を実行したサーバ分配タスクは、回送したランデブの成立の可否にかかわらず、次の要求を受け付ける処理に移らなければならない。その場合、tk_fwd_por のメッセージ領域は次の要求を処理するために利用されるので、メッセージ領域の内容を変更しても、前に処理したランデブの回送には影響しないようにしなければならない。このため、tk_fwd_por の実行後は、回送されたランデブの成立前であっても、tk_fwd_pormsg で示されるメッセージ領域の内容を変更することが可能でなければならない。

実装上は、この仕様を実現するために、tk_cal_por で指定したメッセージ領域をバッファとして使うことが許される。すなわち、tk_fwd_por の処理では、tk_fwd_por で指定した呼出メッセージを tk_cal_pormsg で指定したメッセージ領域にコピーし、tk_fwd_por 発行タスクがメッセージ領域の内容を変更しても構わないようにする。ランデブ成立時には、ランデブが回送されたものかどうかにかかわらず、tk_cal_por のメッセージ領域に置かれていたメッセージが受付側に渡される。

このような実装方法を適用できるように、以下のような仕様を設けている。

  • tk_cal_por で要求したランデブが回送される可能性がある場合は、期待する返答メッセージのサイズにかかわらず、tk_cal_pormsg 以下に少なくとも maxrmsz のサイズの領域を確保しておかなければならない。

  • tk_fwd_por で送信するメッセージのサイズ cmsgsz は、回送前のランデブポートの maxrmsz と等しいか、それよりも小さくなければならない。

  • tk_fwd_por によりランデブが回送される場合に、回送後のランデブポートの maxrmsz が回送前のランデブポートの maxrmsz より大きくなることはない。等しい値をとるか、小さくなっていく。

仕様決定の理由

システム全体で持つべき状態の数を減らすため、tk_fwd_por の仕様は、ランデブ回送の履歴を保存しないという前提で設計されている。ランデブ回送の履歴を覚える必要がある用途では、tk_fwd_por ではなく、tk_cal_portk_acp_por の組をネストして使えばよい。

移植ガイドライン

calptnがUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。

cmsgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送信できるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_rpl_rdv - ランデブ返答

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_rpl_rdv (RNO rdvno , CONST void *msg , INT rmsgsz );

パラメータ

RNO rdvno Rendezvous Numberランデブ番号
CONST void* msg Reply Message返答メッセージを入れるアドレス
INT rmsgsz Reply Message Size返答メッセージのサイズ(バイト数)

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_OK 正常終了
E_PAR パラメータエラー(rmsgsz<0, rmsgszmaxrmsz, msg が不正)
E_OBJ オブジェクトの状態が不正(rdvno が不正)
E_CTX コンテキストエラー(タスク独立部から発行,実装依存)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

ランデブの相手のタスク(呼出側タスク)に対して返答を返し、ランデブを終了する。

このシステムコールを発行したタスク(タスクXとする)は、ランデブ中の状態(tk_acp_por を実行した後の状態)でなければならない。また、ランデブ相手の呼出側タスクはタスクY、tk_acp_por のリターンパラメータとして返されたランデブ番号は rdvno であるものとする。その状態で tk_rpl_rdv を実行すると、タスクXとタスクYとの間のランデブ状態が解除され、ランデブ終了待ち状態にあった呼出側タスクYは実行可能状態(READY)に戻る。

tk_rpl_rdv でランデブを終了する時には、受付側タスクXから呼出側タスクYに対して返答メッセージを送ることができる。受付側タスクが指定した返答メッセージの内容は、呼出側タスクが tk_cal_por で指定した msg 以下の領域にコピーされる。また、返答メッセージのサイズ rmsgsz は、tk_cal_por のリターンパラメータとなる。

rmsgsz が、tk_cre_por で指定した maxrmsz よりも大きい場合は、エラー E_PAR となる。このエラーが検出された場合、ランデブは終了せず、tk_cal_por を実行したタスクのランデブ終了待ち状態は解除されない。

タスク独立部から tk_fwd_por, tk_rpl_rdv を発行することはできないが、ディスパッチ禁止中あるいは割込み禁止中のタスクから tk_fwd_por, tk_rpl_rdv を発行することは可能である。この機能は、tk_fwd_portk_rpl_rdv と不可分に何らかの処理を行う場合に利用できる。なお、タスク独立部から tk_fwd_por, tk_rpl_rdv が発行された場合のエラーチェックは実装依存である。

補足事項

ランデブを呼び出したタスクが、何らかの理由でランデブ終了前(tk_rpl_rdv 実行前) に異常終了したような場合にも、ランデブ受付側のタスクは直接それを知ることができない。この場合は、ランデブ受付側のタスクが tk_rpl_rdv を実行する時に E_OBJ のエラーとなる。

ランデブ成立後は、原則としてタスクとランデブポートとが切り離されてしまう(相互に情報を参照する必要がない) が、tk_rpl_rdv のメッセージ長のチェックに使用する maxrmsz のみは、ランデブポートに依存した情報であるため、ランデブ中のタスクがどこかに覚えておく必要がある。実装上の工夫としては、待ち状態になっている呼出側タスクのTCB、あるいはTCBから参照可能な領域(スタック等)に入れておくことが考えられる。

仕様決定の理由

tk_rpl_rdvtk_fwd_por のパラメータでは、成立中のランデブを区別する情報として rdvno を指定するが、ランデブ成立に利用したランデブポートのID(porid) は指定しない。これは、ランデブ成立後のタスクがランデブポートとは無関係になるという方針に基づいたものである。

rdvno が不正値の場合のエラーコードとして、E_PAR ではなく E_OBJ を使用している。これは、rdvno の実体が呼出側タスクを示しているという理由による。

移植ガイドライン

rmsgszがINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送信できるメッセージのサイズが32767バイトまでに制限される可能性がある。

tk_ref_por - ランデブポート状態参照

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ref_por (ID porid , T_RPOR *pk_rpor );

パラメータ

ID porid Port IDランデブポートID
T_RPOR* pk_rpor Packet to Refer Port Statusランデブポート状態を返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード

pk_rpor の内容

void* exinf Extended Information拡張情報
ID wtsk Wait Task Information呼出待ちタスクのID
ID atsk Accept Task Information受付待ちタスクのID
INT maxcmsz Maximum Call Message Size呼出時のメッセージの最大長(バイト数)
INT maxrmsz Maximum Reply Message Size返答時のメッセージの最大長(バイト数)
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_OK 正常終了
E_ID 不正ID番号(porid が不正あるいは利用できない)
E_NOEXS オブジェクトが存在していない(porid のランデブポートが存在しない)
E_PAR パラメータエラー(pk_rpor が不正)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

porid で示された対象ランデブポートの各種の状態を参照し、リターンパラメータとして受付待ちタスクのID(atsk)、呼出待ちタスクのID(wtsk)、メッセージの最大長(maxcmsz,maxrmsz)、拡張情報(exinf) を返す。

wtsk は、このランデブポートでランデブ呼出待ちになっているタスクのIDを示す。ランデブ呼出待ちタスクが無い場合は wtsk=0となる。一方、atsk は、このランデブポートでランデブ受付待ちになっているタスクのIDを示す。ランデブ受付待ちタスクが無い場合は atsk=0となる。

このランデブポートで複数のタスクが呼出待ち状態または受付待ち状態になっている場合には、それぞれ呼出待ち行列または受付待ち行列の先頭のタスクのIDを返す。

対象ランデブポートが存在しない場合には、エラー E_NOEXS となる。

補足事項

このシステムコールでは、現在ランデブ中のタスクに関する情報を知ることはできない。

注意

[1]

ベース優先度:ミューテックスによって自動的に引き上げられる前のタスクの優先度を示す。最後(ミューテックスのロック中も含む)に tk_chg_pri によって設定された優先度、または tk_chg_pri を一度も発行していない場合はタスク生成時に指定したタスク優先度が、ベース優先度である。

[2]

  • 太枠内はランデブポート(ランデブエントリ)を表す。

  • tk_fwd_por の代わりに tk_cal_por を使うことも可能であるが、その場合はランデブがネストする。処理A~Cのサーバタスクの処理終了後にそのまま要求タスクXの実行を再開して構わないのであれば、tk_fwd_por を利用することによってランデブのネストが不要となり、効率良い動作をすることができる。