拡張同期・通信機能

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

ミューテックス

ミューテックスは、共有資源を使用する際にタスク間で排他制御を行うためのオブジェクトである。ミューテックスは、排他制御に伴う上限のない優先度逆転を防ぐための機構として、優先度継承プロトコル(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 の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。待ち解除の条件が満足されない(ロックが解除されない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

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 の説明を参照のこと。

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_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 の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(バッファに十分な空き領域ができない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

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 の説明を参照のこと。

移植ガイドライン

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 の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(メッセージが到着しない)まま tmout の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。

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 の説明を参照のこと。

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 Waiting Task ID受信待ちタスクのID
ID stsk Send Waiting Task ID送信待ちタスクの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 で指定したメッセージの最大長が返される。

注意

[1]

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