拡張同期・通信機能は、タスクとは独立したオブジェクトにより、タスク間の高度な同期・通信を行うための機能である。ミューテックス、メッセージバッファの各機能が含まれる。
ミューテックスは、共有資源を使用する際にタスク間で排他制御を行うためのオブジェクトである。ミューテックスは、排他制御に伴う上限のない優先度逆転を防ぐための機構として、優先度継承プロトコル(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_pri が E_ILUSE エラーを返す。
これらのプロトコルを用いた場合、上限のない優先度逆転を防ぐために、ミューテックスの操作に伴ってタスクの現在優先度が自動的に変更される。優先度継承プロトコルと優先度上限プロトコルに厳密に従うなら、タスクの現在優先度を、次に挙げる優先度の最高値に常に一致するように変更する必要がある。これを、厳密な優先度制御規則と呼ぶ。
タスクのベース優先度
タスクが TA_INHERIT 属性のミューテックスをロックしている場合、それらのミューテックスのロックを待っているタスクの中で、最も高い現在優先度を持つタスクの現在優先度
タスクが TA_CEILING 属性のミューテックスをロックしている場合、それらのミューテックス中で、最も高い上限優先度を持つミューテックスの上限優先度
ここで、TA_INHERIT 属性のミューテックスを待っているタスクの現在優先度が、ミューテックス操作か tk_chg_pri によるベース優先度の変更に伴って変更された場合、そのミューテックスをロックしているタスクの現在優先度の変更が必要になる場合がある。これを推移的な優先度継承と呼ぶ。さらにそのタスクが、別の TA_INHERIT 属性のミューテックスを待っていた場合には、そのミューテックスをロックしているタスクに対して推移的な優先度継承の処理が必要になる場合がある。
T-Kernelでは、上述の厳密な優先度制御規則に加えて、現在優先度を変更する状況を限定した優先度制御規則(これを簡略化した優先度制御規則と呼ぶ)を規定し、どちらを採用するかは実装定義とする。具体的には、簡略化した優先度制御規則においては、タスクの現在優先度を高くする方向の変更はすべて行うのに対して、現在優先度を低くする方向の変更は、タスクがロックしているミューテックスがなくなった時にのみ行う(この場合には、タスクの現在優先度をベース優先度に戻すことになる)。より具体的には、次の状況でのみ現在優先度を変更する処理を行えばよい。
タスクがロックしている TA_INHERIT 属性のミューテックスを、そのタスクよりも高い現在優先度を持つタスクが待ち始めた時
タスクAによってロックされている TA_INHERIT 属性のミューテックスを待っている別のタスクBが、タスクAよりも高い現在優先度に変更された時
タスクが、そのタスクの現在優先度よりも高い上限優先度を持つ TA_CEILING 属性のミューテックスをロックした時
タスクがロックしているミューテックスがなくなった時
ミューテックスの操作に伴ってタスクの現在優先度を変更した場合には、次の処理を行う。
優先度を変更されたタスクが実行できる状態である場合、タスクの優先順位を、変更後の優先度にしたがって変化させる。変更後の優先度と同じ優先度を持つタスクの間での優先順位は、実装依存である。優先度が変更されたタスクが何らかのタスク優先度順の待ち行列につながれている場合にも、その待ち行列の中での順序を、変更後の優先度にしたがって変化させる。変更後の優先度と同じ優先度を持つタスクの間での順序は、実装依存である。タスクが終了する時に、そのタスクがロックしているミューテックスが残っている場合には、それらのミューテックスをすべてロック解除する。ロックしているミューテックスが複数ある場合には、それらをロック解除する順序は実装依存である。ロック解除の具体的な処理内容については、tk_unl_mtx の機能説明を参照すること。
補足事項 | |
---|---|
TA_TFIFO 属性または TA_TPRI 属性のミューテックスは、最大資源数が1のセマフォ(バイナリセマフォ)と同等の機能を持つ。ただし、ミューテックスは、ロックしたタスク以外はロック解除できない、タスク終了時に自動的にロック解除されるなどの違いがある。 ここでいう優先度上限プロトコルは、広い意味での優先度上限プロトコルで、最初に優先度上限プロトコルとして提案されたアルゴリズムではない。厳密には、highest locker protocolなどと呼ばれているアルゴリズムである。 ミューテックスの操作に伴ってタスクの現在優先度を変更した結果、優先度を変更されたタスクのタスク優先度順の待ち行列の中での順序が変化した場合、優先度を変更されたタスクないしはその待ち行列で待っている他のタスクの待ち解除が必要になる場合がある。 |
仕様決定の理由 | |
---|---|
ミューテックスの操作に伴ってタスクの現在優先度を変更した場合に、変更後の優先度と同じ優先度を持つタスクの間での優先順位を実装依存としたのは、次の理由による。アプリケーションによっては、ミューテックス機能による現在優先度の変更が頻繁に発生する可能性があり、それに伴ってタスク切替えが多発するのは望ましくない(同じ優先度を持つタスクの間での優先順位を最低とすると、不必要なタスク切替えが起こる)。理想的には、タスクの優先度ではなく優先順位を継承するのが望ましいが、このような仕様にすると実装上のオーバヘッドが大きくなるため、実装依存とすることにした。 |
pk_cmtx
の内容
ミューテックスを生成しミューテックス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_dsname と td_set_dsname からのみ操作可能である。詳細は td_ref_dsname 、td_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname
が無視され、td_ref_dsname や td_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 /* 待ち禁止拒否 */
mtxid
で示されたミューテックスを削除する。
本システムコールの発行により、対象ミューテックスのID番号および管理ブロック用の領域は解放される。
対象ミューテックスにおいてロック待ちしているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。
ミューテックスが削除されると、そのミューテックスをロックしているタスクにとっては、ロックしているミューテックスが減ることになる。したがって、削除されるミューテックスが TA_INHERIT または TA_CEILING 属性の場合には、ロックしていたタスクの優先度が変更される場合がある。
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 属性のミューテックスの場合
自タスクがロック待ち状態になる場合、そのミューテックスをロックしているタスクの現在優先度が自タスクより低ければ、ロックしているタスクの優先度を自タスクと同じ優先度まで引き上げる。ロックを待っているタスクがロックを獲得せずに待ちを終了した場合(タイムアウトなど)、そのミューテックスをロック中のタスクの優先度を、次の内の最も高い優先度まで引き下げる。ただし、この優先度の引き下げを行うか否かは実装依存である。
そのミューテックスでロック待ちしているタスクの現在優先度の内の最も高い優先度。
そのミューテックスをロック中のタスクがロックしている他のすべてのミューテックスの内の最も高い優先度。
ロック中のタスクのベース優先度。
TA_CEILING 属性のミューテックスの場合
自タスクがロックを獲得した場合、自タスクの現在優先度がミューテックスの上限優先度より低ければ、自タスクの優先度をミューテックスの上限優先度まで引き上げる。
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_loc_mtx のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_loc_mtx と同じである。詳細は tk_loc_mtx の説明を参照のこと。
mtxid
のミューテックスのロックを解除する。
ロック待ちしているタスクがあれば、待ち行列の先頭のタスクの待ちを解除し、そのタスクをロック獲得状態にする。
自タスクがロックしていないミューテックスを指定した場合、E_ILUSE を返す。
ロック解除したミューテックスが TA_INHERIT または TA_CEILING 属性の場合、次のようにタスク優先度を引き下げる必要がある。
ロックを解除することにより、自タスクがロックしているミューテックスがすべてなくなった場合は、自タスクの優先度をベース優先度まで引き下げる。
自タスクがロック中のミューテックスが残っている場合、自タスクの優先度を次の内の最も高い優先度まで引き下げる。
自タスクがロックしている TA_INHERIT 属性を持つミューテックスの待ち行列につながれているタスクの現在優先度の中で最も高い優先度
自タスクがロックしている TA_CEILING 属性を持つミューテックスに設定されている上限優先度の中で最も高い優先度
自タスクのベース優先度
ただし、ロック中のミューテックスが残っている場合の優先度の引き下げを行うか否かは実装依存である。
ミューテックスをロックした状態でタスクを終了した(休止状態(DORMANT)または未登録状態(NON-EXISTENT)になった)場合、当該タスクがロックしているすべてのミューテックスは自動的にロック解除される。
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は非同期に実行しているものとする。
メッセージバッファへの送信を待っているタスクは、待ち行列につながれている順序でメッセージを送信する。例えば、あるメッセージバッファに対して40バイトのメッセージを送信しようとしているタスクAと、10バイトのメッセージを送信しようとしているタスクBが、この順で待ち行列につながれている時に、別のタスクによるメッセージの受信により20バイトの空き領域ができたとする。このような場合でも、タスクAがメッセージを送信するまで、タスクBはメッセージを送信できない。 メッセージバッファは、可変長のメッセージをコピーして受渡しする。メールボックスとの違いは、メッセージをコピーすることである。 メッセージバッファは、リングバッファで実装することを想定している。 |
pk_cmbf
の内容
メッセージバッファを生成しメッセージバッファ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_dsname と td_set_dsname からのみ操作可能である。詳細は td_ref_dsname 、td_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname
が無視され、td_ref_dsname や td_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_mbf と tk_rcv_mbf の一方のシステムコールが先に実行されると、それを実行したタスクは待ち状態となる。もう一方のシステムコールが実行された段階で、メッセージの受け渡し(コピー)が行われ、その後双方のタスクが実行を再開する。
bufsz
=0のメッセージバッファの場合、具体的な動作は次のようになる。
[図4]で、タスクAとタスクBは非同期に動いている。もし、タスクAが先に(1)に到達し、tk_snd_mbf(mbfid
) を実行した場合には、タスクBが(2)に到達するまでタスクAはメッセージ送信待ち状態になる。この状態のタスクAを対象として tk_ref_tsk を発行すると、tskwait
=TTW_SMBF となる。逆に、タスクBが先に(2)に到達し、tk_rcv_mbf(mbfid
) を実行した場合には、タスクAが(1)に到達するまでタスクBはメッセージ受信待ち状態になる。この状態のタスクBを対象として tk_ref_tsk を発行すると、tskwait
=TTW_RMBF となる。
タスクAが tk_snd_mbf(mbfid
) を実行し、かつタスクBが tk_rcv_mbf(mbfid
) を実行した時点でタスクAからタスクBにメッセージが送信され、どちらのタスクも待ち解除となって実行を再開する。
T_CMBFのメンバmaxmsz
がINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。
T-Kernel 2.0にはTA_USERBUFとbufptr
が存在しない。そのため、この機能を使っている場合はT-Kernel 2.0への移植の際に修正が必要となるが、正しくbufsz
を設定してあれば、TA_USERBUFとbufptr
を削除するだけで移植できる。
mbfid
で示されたメッセージバッファを削除する。
本システムコールの発行により、対象メッセージバッファのID番号および管理ブロック用の領域およびメッセージを入れるバッファ領域は解放される。
対象メッセージバッファにおいてメッセージ受信またはメッセージ送信を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。また、対象メッセージバッファの中にメッセージが残っている場合でも、エラーとはならず、メッセージバッファの削除が行われ、中にあったメッセージは消滅する。
E_OK | 正常終了 |
E_ID | 不正ID番号(mbfid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mbfid のメッセージバッファが存在しない) |
E_PAR | パラメータエラー(msgsz ≦0, msgsz >maxmsz , 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 となるが、tmout
=TMO_POL の場合は、実装によってはタスク独立部やディスパッチ禁止状態から実行することができる場合がある。
msgsz
がINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送れるメッセージのサイズが32767バイトまでに制限される可能性がある。
E_OK | 正常終了 |
E_ID | 不正ID番号(mbfid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mbfid のメッセージバッファが存在しない) |
E_PAR | パラメータエラー(msgsz ≦0, msgsz >maxmsz , msg が不正, tmout_u ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メッセージバッファが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_snd_mbf のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_snd_mbf と同じである。詳細は tk_snd_mbf の説明を参照のこと。
msgsz
がINT型であり、処理系によってとれる値の範囲に異なる可能性があるため注意が必要である。例えば、16ビット環境では一度に送れるメッセージのサイズが32767バイトまでに制限される可能性がある。
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)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにメッセージが到着するまで待ち続ける。
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_rcv_mbf のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_rcv_mbf と同じである。詳細は tk_rcv_mbf の説明を参照のこと。
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 を一度も発行していない場合はタスク生成時に指定したタスク優先度が、ベース優先度である。 |