同期・通信機能は、タスクとは独立したオブジェクトにより、タスク間の同期・通信を行うための機能である。セマフォ、イベントフラグ、メールボックスの各機能が含まれる。
セマフォは、使用されていない資源の有無や数量を数値で表現することにより、その資源を使用する際の排他制御や同期を行うためのオブジェクトである。セマフォ機能には、セマフォを生成/削除する機能、セマフォの資源を獲得/返却する機能、セマフォの状態を参照する機能が含まれる。セマフォはID番号で識別されるオブジェクトである。セマフォのID番号をセマフォIDと呼ぶ。
セマフォは、対応する資源の有無や数量を表現するセマフォ資源数(セマフォカウント値)と、資源の獲得を待つタスクの待ち行列を持つ。資源をm個返却する側(イベントを知らせる側)では、セマフォの資源数をm個増やす。一方、資源をn個獲得する側(イベントを待つ側)では、セマフォの資源数をn個減らす。セマフォの資源数が足りなくなった場合(具体的には、資源数を減らすと資源数が負になる場合)、資源を獲得しようとしたタスクは、次に資源が返却されるまでセマフォ資源の獲得待ち状態となる。セマフォ資源の獲得待ち状態になったタスクは、そのセマフォの待ち行列につながれる。
また、セマフォに対して資源が返却され過ぎるのを防ぐために、セマフォ毎にセマフォ資源数の最大値を設定することができる。最大資源数を越える資源がセマフォに返却されようとした場合(具体的には、セマフォの資源数を増やすと最大資源数を超える場合)には、エラーを報告する。
pk_csem
の内容
セマフォを生成しセマフォID番号を割り当てる。具体的には、生成するセマフォに対して管理ブロックを割り付け、そのセマフォ資源数の初期値を isemcnt
、最大値(上限値)を maxsem
とする。なお、maxsem
には少なくとも32767が指定できなくてはならない。32768以上の値が指定できるかは実装に依存する。
exinf
は、対象セマフォに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_sem で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf
に入れる。カーネルでは exinf
の内容について関知しない。
sematr
は、下位側がシステム属性を表し、上位側が実装独自属性を表す。sematr
のシステム属性の部分では、次のような指定を行う。
sematr := (TA_TFIFO || TA_TPRI) | (TA_FIRST || TA_CNT) | [TA_DSNAME] | [TA_NODISWAI]
TA_TFIFO | 待ちタスクのキューイングはFIFO |
TA_TPRI | 待ちタスクのキューイングは優先度順 |
TA_FIRST | 待ち行列先頭のタスクを優先 |
TA_CNT | 要求数の少ないタスクを優先 |
TA_DSNAME | DSオブジェクト名称を指定する |
TA_NODISWAI | tk_dis_wai による待ち禁止を拒否する |
TA_TFIFO, TA_TPRI では、タスクがセマフォの待ち行列に並ぶ際の並び方を指定することができる。属性が TA_TFIFO であればタスクの待ち行列はFIFOとなり、属性が TA_TPRI であればタスクの待ち行列はタスクの優先度順となる。
TA_FIRST, TA_CNT では、資源獲得の優先順を指定する。TA_FIRST および TA_CNT の指定によって待ち行列の並び順が変わることはない。待ち行列の並び順は TA_TFIFO, TA_TPRI によってのみ決定される。
TA_FIRST では、要求するセマフォ資源数に関係なく待ち行列の先頭のタスクから順に資源を割り当てる。待ち行列の先頭のタスクが要求分の資源を獲得できない限り、待ち行列の後ろのタスクが資源を獲得することはない。
TA_CNT では、要求するセマフォ資源数の獲得できるタスクから順に割り当てる。具体的には、待ち行列の先頭のタスクから順に要求するセマフォ資源数を検査し、その資源数が割り当てられるタスクに割り当てる。要求するセマフォ資源数の少ない順に割り当てるわけではない。
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_FIRST 0x00000000 /* 待ち行列先頭のタスクを優先 */ #define TA_CNT 0x00000002 /* 要求数の少ないタスクを優先 */ #define TA_DSNAME 0x00000040 /* DSオブジェクト名称を指定 */ #define TA_NODISWAI 0x00000080 /* 待ち禁止拒否 */
semid
で示されたセマフォを削除する。
本システムコールの発行により、対象セマフォのID番号および管理ブロック用の領域は解放される。
対象セマフォにおいて条件成立を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。
semid
で示されたセマフォに対して、cnt
個の資源を返却する操作を行う。対象セマフォに対して既に待っているタスクがあれば、要求するセマフォ資源数を確認して可能であれば資源を割り当てる。資源を割り当てられたタスクを実行可能状態(READY)に移す。条件によっては、複数のタスクに資源が割り当てられ実行可能状態(READY)になる場合がある。
セマフォ資源数の増加により、その値がセマフォ資源数の最大値(maxsem
)を越えようとした場合は、E_QOVR のエラーとなる。この場合、資源の返却は一切行われず、セマフォ資源数(semcnt
)も変化しない。
セマフォ資源数(semcnt
)がその初期値(isemcnt
)を越えた場合にも、エラーとはならない。排他制御ではなく、同期の目的(tk_wup_tsk~tk_slp_tsk と同様)でセマフォを使用する場合には、セマフォ資源数(semcnt
)が初期値(isemcnt
)を越えることがある。一方、排他制御の目的でセマフォを使う場合は、セマフォ資源数の初期値(isemcnt
)と最大値(maxsem
)を等しい値にしておくことにより、セマフォ資源数の増加によるエラーをチェックすることができる。
E_OK | 正常終了 |
E_ID | 不正ID番号(semid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(semid のセマフォが存在しない) |
E_PAR | パラメータエラー(tmout ≦(-2), cnt ≦0) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象セマフォが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
semid
で示されたセマフォから、cnt
個の資源を獲得する操作を行う。資源が獲得できれば、本システムコールの発行タスクは待ち状態に入らず、実行を継続する。この場合、そのセマフォのセマフォ資源数(semcnt
)は cnt
分減算される。資源が獲得できなければ、本システムコールを発行したタスクは待ち状態に入る。すなわち、そのセマフォに対する待ち行列につながれる。この場合、そのセマフォのセマフォ資源数(semcnt
)は不変である。
tmout
により待ち時間の最大値(タイムアウト値)を指定することができる。tmout
の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。待ち解除の条件が満足されない(tk_sig_sem が実行されない)まま tmout
の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。
tmout
として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、資源を獲得できなくても待ちに入らず E_TMOUT を返す。また、tmout
として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずに資源が獲得できるまで待ち続ける。
E_OK | 正常終了 |
E_ID | 不正ID番号(semid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(semid のセマフォが存在しない) |
E_PAR | パラメータエラー(tmout_u ≦(-2), cnt ≦0) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象セマフォが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_wai_sem のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_wai_sem と同じである。詳細は tk_wai_sem の説明を参照のこと。
pk_rsem
の内容
semid
で示された対象セマフォの各種の状態を参照し、リターンパラメータとして現在のセマフォ資源数(semcnt
)、待ちタスクのID(wtsk
)、拡張情報(exinf
) を返す。
wtsk
は、このセマフォで待っているタスクのIDを示す。複数のタスクが待っている場合には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は wtsk
=0となる。
対象セマフォが存在しない場合には、エラー E_NOEXS となる。
イベントフラグは、イベントの有無をビット毎のフラグで表現することにより、同期を行うためのオブジェクトである。イベントフラグ機能には、イベントフラグを生成/削除する機能、イベントフラグをセット/クリアする機能、イベントフラグで待つ機能、イベントフラグの状態を参照する機能が含まれる。イベントフラグはID番号で識別されるオブジェクトである。イベントフラグのID番号をイベントフラグIDと呼ぶ。
イベントフラグは、対応するイベントの有無をビット毎に表現するビットパターンと、そのイベントフラグで待つタスクの待ち行列を持つ。イベントフラグのビットパターンを、単にイベントフラグと呼ぶ場合もある。イベントを知らせる側では、イベントフラグのビットパターンの指定したビットをセットないしはクリアすることが可能である。一方、イベントを待つ側では、イベントフラグのビットパターンの指定したビットのすべてまたはいずれかがセットされるまで、タスクをイベントフラグ待ち状態にすることができる。イベントフラグ待ち状態になったタスクは、そのイベントフラグの待ち行列につながれる。
pk_cflg
の内容
イベントフラグを生成しイベントフラグID番号を割り当てる。具体的には、生成するイベントフラグに対して管理ブロックを割り付け、その初期値を iflgptn
とする。一つのイベントフラグで、プロセッサの1ワード分のビットをグループ化して扱う。操作はすべて1ワード分を単位とする。
exinf
は、対象イベントフラグに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_flg で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf
に入れる。カーネルでは exinf
の内容について関知しない。
flgatr
は、下位側がシステム属性を表し、上位側が実装独自属性を表す。flgatr
のシステム属性の部分では、次のような指定を行う。
flgatr := (TA_TFIFO || TA_TPRI) | (TA_WMUL || TA_WSGL) | [TA_DSNAME] | [TA_NODISWAI]
TA_TFIFO | 待ちタスクのキューイングはFIFO |
TA_TPRI | 待ちタスクのキューイングは優先度順 |
TA_WSGL | 複数タスクの待ちを許さない(Wait Single Task) |
TA_WMUL | 複数タスクの待ちを許す(Wait Multiple Task) |
TA_DSNAME | DSオブジェクト名称を指定する |
TA_NODISWAI | tk_dis_wai による待ち禁止を拒否する |
TA_WSGL を指定した場合は、複数のタスクが同時に待ち状態になることを禁止する。TA_WMUL を指定した場合は、同時に複数のタスクが待ち状態となることが許される。
TA_TFIFO, TA_TPRI では、タスクがイベントフラグの待ち行列に並ぶ際の並び方を指定することができる。属性が TA_TFIFO であればタスクの待ち行列はFIFOとなり、属性が TA_TPRI であればタスクの待ち行列はタスクの優先度順となる。ただし、TA_WSGL を指定した場合は待ち行列を作らないため、TA_TFIFO, TA_TPRI のどちらを指定しても動作に変わりはない。
複数のタスクが待っている場合、待ち行列の先頭から順に待ち条件が成立しているか検査し、待ち条件が成立しているタスクの待ちを解除する。したがって、待ち行列の先頭のタスクが必ずしも最初に待ちが解除される訳ではない。また、待ち条件が成立したタスクが複数あれば、複数のタスクの待ちが解除される。
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_WSGL 0x00000000 /* 複数タスクの待ちを許さない */ #define TA_WMUL 0x00000008 /* 複数タスクの待ちを許す */ #define TA_DSNAME 0x00000040 /* DSオブジェクト名称を指定 */ #define TA_NODISWAI 0x00000080 /* 待ち禁止拒否 */
T_CFLGのiflgptn
メンバはUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。
flgid
で示されたイベントフラグを削除する。
本システムコールの発行により、対象イベントフラグのID番号および管理ブロック用の領域は解放される。
対象イベントフラグにおいて条件成立を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。
tk_set_flg では、flgid
で示される1ワードのイベントフラグのうち、setptn
で示されているビットがセットされる。すなわち、flgid
で示されるイベントフラグの値に対して、setptn
の値で論理和がとられる。(イベントフラグ値 flgptn
に対して flgptn
|= setptn
の処理を実行)
tk_set_flg によりイベントフラグの値が変更された結果、tk_wai_flg でそのイベントフラグを待っていたタスクの待ち解除の条件を満たすようになれば、そのタスクの待ち状態が解除され、実行状態(RUNNING)または実行可能状態(READY)(待っていたタスクが二重待ち状態(WAITING-SUSPENDED)であった場合には強制待ち状態(SUSPENDED))へと移行する。
tk_set_flg で setptn
の全ビットを0とした場合には、対象イベントフラグに対して何の操作も行わないことになる。ただし、この場合でもエラーとはならない。
TA_WMUL の属性を持つイベントフラグに対しては、同一のイベントフラグに対して複数のタスクが同時に待つことができる。したがって、イベントフラグでもタスクが待ち行列を作ることになる。この場合、一回の tk_set_flg で複数のタスクが待ち解除となることがある。
setptn
はUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。
tk_clr_flg では、flgid
で示される1ワードのイベントフラグのうち、対応する clrptn
の0になっているビットがクリアされる。すなわち、flgid
で示されるイベントフラグの値に対して、clrptn
の値で論理積がとられる。(イベントフラグ値 flgptn
に対して flgptn
&= clrptn
の処理を実行)
tk_clr_flg では、対象イベントフラグを待っているタスクが待ち解除となることはない。すなわち、ディスパッチは起らない。
tk_clr_flg で clrptn
の全ビットを1とした場合には、対象イベントフラグに対して何の操作も行わないことになる。ただし、この場合でもエラーとはならない。
clrptn
はUINT型であり、処理系によってビット幅が異なる可能性があるため注意が必要である。
E_OK | 正常終了 |
E_ID | 不正ID番号(flgid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(flgid のイベントフラグが存在しない) |
E_PAR | パラメータエラー(waiptn =0, wfmode が不正, tmout ≦(-2)) |
E_OBJ | オブジェクトの状態が不正(TA_WSGL 属性のイベントフラグに対する複数タスクの待ち) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象イベントフラグが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_wai_flg では、wfmode
で示される待ち解除の条件にしたがって、flgid
で示されるイベントフラグがセットされるのを待つ。
flgid
で示されるイベントフラグが、既に wfmode
で示される待ち解除条件を満たしている場合には、発行タスクは待ち状態にならずに実行を続ける。
wfmode
では、次のような指定を行う。
wfmode := (TWF_ANDW || TWF_ORW) | [TWF_CLR || TWF_BITCLR]
TWF_ORW を指定した場合には、flgid
で示されるイベントフラグのうち、waiptn
で指定したビットのいずれかがセットされるのを待つ(OR待ち)。また、TWF_ANDW を指定した場合には、flgid
で示されるイベントフラグのうち、waiptn
で指定したビットのすべてがセットされるのを待つ(AND待ち)。
TWF_CLR の指定が無い場合には、条件が満足されてこのタスクが待ち解除となった場合にも、イベントフラグの値はそのままである。TWF_CLR の指定がある場合には、条件が満足されてこのタスクが待ち解除となった場合、イベントフラグの値(全部のビット)が0にクリアされる。TWF_BITCLR の指定がある場合には、条件が満足されてこのタスクが待ち解除となった場合、イベントフラグの待ち解除条件に一致したビットのみが0クリアされる。(イベントフラグ値 &= ~待ち解除条件)
flgptn
は、本システムコールによる待ち状態が解除される時のイベントフラグの値(TWF_CLR または TWF_BITCLR 指定の場合は、イベントフラグがクリアされる前の値) を示すリターンパラメータである。flgptn
で返る値は、このシステムコールの待ち解除の条件を満たすものになっている。なお、タイムアウト等で待ちが解除された場合は、flgptn
の内容は不定となる。
tmout
により待ち時間の最大値(タイムアウト値)を指定することができる。tmout
の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。待ち解除の条件が満足されないまま tmout
の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。
tmout
として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、条件を満たしていなくても待ちに入らず E_TMOUT を返す。また、tmout
として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずに条件が成立するまで待ち続ける。
タイムアウトした場合は、TWF_CLR または TWF_BITCLR の指定があってもイベントフラグのクリアは行われない。
waiptn
を0とした場合は、パラメータエラー E_PAR になる。
既に待ちタスクの存在する TA_WSGL 属性のイベントフラグに対して、別のタスクが tk_wai_flg を実行することはできない。この場合は、後から tk_wai_flg を実行したタスクが待ち状態に入るかどうか(待ち解除条件が満たされているかどうか)にかかわらず、後から tk_wai_flg を実行したタスクは E_OBJ のエラーとなる。
一方、TA_WMUL の属性を持つイベントフラグに対しては、同一のイベントフラグに対して複数のタスクが同時に待つことができる。したがって、イベントフラグでもタスクが待ち行列を作ることになる。この場合、一回の tk_set_flg で複数のタスクが待ち解除となることがある。
TA_WMUL 属性を持つイベントフラグに対して複数のタスクが待ち行列を作った場合、次のような動作をする。
待ち行列の順番はFIFOまたはタスク優先度順である。(ただし、waiptn
や wfmode
との関係により、必ずしも行列先頭のタスクから待ち解除になるとは限らない。)
待ち行列中にクリア指定のタスクがあれば、そのタスクが待ち解除になる時に、フラグをクリアする。
クリア指定を行っていたタスクよりも後ろの待ち行列にあったタスクは、既にクリアされた後のイベントフラグを見ることになる。
tk_set_flg によって同じ優先度を持つ複数のタスクが同時に待ち解除となる場合、待ち解除後のタスクの優先順位は、元のイベントフラグの待ち行列の順序を保存する。
tk_wai_flg の待ち解除条件として全ビットの論理和を指定すれば、(waiptn
=0xfff...ff, wfmode
=TWF_ORW)、tk_set_flg と組み合わせることによって、1ワードのビットパターンによるメッセージ転送を行うことができる。ただし、この場合、全部のビットが0というメッセージを送ることはできない。また、前のメッセージが tk_wai_flg で読まれる前に tk_set_flg により次のメッセージが送られると、前のメッセージは消えてしまう。すなわち、メッセージのキューイングはできない。
waiptn
=0の指定は E_PAR のエラーになるので、イベントフラグで待つタスクの waiptn
は0でないことが保証されている。したがって、tk_set_flg で全ビットをセットすれば、どのような条件でイベントフラグを待つタスクであっても、待ち行列の先頭にあるタスクは必ず待ち解除となる。
イベントフラグに対する複数タスク待ちの機能は、次のような場合に有効である。例えば、タスクAが(1)の tk_set_flg を実行するまで、タスクB、タスクCを(2), (3)の tk_wai_flg で待たせておく場合に、イベントフラグの複数待ちが可能であれば、(1)(2)(3)のどのシステムコールが先に実行されても結果は同じになる[図1]。一方、イベントフラグの複数待ちができなければ、(2)→(3)→(1)の順でシステムコールが実行された場合に、(3)の tk_wai_flg が E_OBJ のエラーになる。
waiptn
=0の指定を E_PAR のエラーとしたのは、waiptn
=0の指定を許した場合に、それ以後イベントフラグがどのような値に変わっても待ち状態から抜けることができなくなるためである。
waiptn
とp_flgptn
の指す先の型がUINTであり、処理系によってビット幅が異なる可能性があるため注意が必要である。
E_OK | 正常終了 |
E_ID | 不正ID番号(flgid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(flgid のイベントフラグが存在しない) |
E_PAR | パラメータエラー(waiptn =0, wfmode が不正, tmout_u ≦(-2)) |
E_OBJ | オブジェクトの状態が不正(TA_WSGL 属性のイベントフラグに対する複数タスクの待ち) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象イベントフラグが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_wai_flg のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_wai_flg と同じである。詳細は tk_wai_flg の説明を参照のこと。
waiptn
とp_flgptn
の指す先の型がUINTであり、処理系によってビット幅が異なる可能性があるため注意が必要である。
pk_rflg
の内容
flgid
で示された対象イベントフラグの各種の状態を参照し、リターンパラメータとして現在のフラグ値(flgptn
)、待ちタスクのID(wtsk
)、拡張情報(exinf
) を返す。
wtsk
は、このイベントフラグで待っているタスクのIDを示す。このイベントフラグで複数のタスクが待っている場合(TA_WMUL属性のときのみ)には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は wtsk
=0となる。
対象イベントフラグが存在しない場合には、エラー E_NOEXS となる。
メールボックスは、共有メモリ上に置かれたメッセージを受渡しすることにより、同期と通信を行うためのオブジェクトである。メールボックス機能には、メールボックスを生成/削除する機能、メールボックスに対してメッセージを送信/受信する機能、メールボックスの状態を参照する機能が含まれる。メールボックスはID番号で識別されるオブジェクトである。メールボックスのID番号をメールボックスIDと呼ぶ。
メールボックスは、送信されたメッセージを入れるためのメッセージキューと、メッセージの受信を待つタスクの待ち行列を持つ。メッセージを送信する側(イベントを知らせる側)では、送信したいメッセージをメッセージキューに入れる。一方、メッセージを受信する側(イベントを待つ側)では、メッセージキューに入っているメッセージを一つ取り出す。メッセージキューにメッセージが入っていない場合は、次にメッセージが送られてくるまでメールボックスからの受信待ち状態になる。メールボックスからの受信待ち状態になったタスクは、そのメールボックスの待ち行列につながれる。
メールボックスによって実際に送受信されるのは、送信側と受信側で共有しているメモリ上に置かれたメッセージの先頭番地のみである。すなわち、送受信されるメッセージの内容のコピーは行わない。カーネルは、メッセージキューに入っているメッセージを、リンクリストにより管理する。アプリケーションプログラムは、送信するメッセージの先頭に、カーネルがリンクリストに用いるための領域を確保しなければならない。この領域をメッセージヘッダと呼ぶ。また、メッセージヘッダと、それに続くアプリケーションがメッセージを入れるための領域をあわせて、メッセージパケットと呼ぶ。メールボックスへメッセージを送信するシステムコールは、メッセージパケットの先頭番地(pk_msg
)をパラメータとする。
また、メールボックスからメッセージを受信するシステムコールは、メッセージパケットの先頭番地をリターンパラメータとして返す。
メッセージキューをメッセージの優先度順にする場合には、メッセージの優先度を入れるための領域(msgpri
)も、メッセージヘッダ中に持つ必要がある。(図2)
ユーザが実際にメッセージを入れることができるのは、メッセージ先頭アドレスの直後からではなく、メッセージヘッダの後の部分から(図のメッセージの内容の部分) である。
カーネルは、メッセージキューに入っている(ないしは、入れようとしている)メッセージのメッセージヘッダ(メッセージ優先度のための領域を除く)の内容を書き換える。一方、アプリケーションは、メッセージキューに入っているメッセージのメッセージヘッダ(メッセージ優先度のための領域を含む)の内容を書き換えてはならない。アプリケーションによってメッセージヘッダの内容が書き換えられた場合の振舞いは未定義である。この規定は、アプリケーションプログラムがメッセージヘッダの内容を直接書き換えた場合に加えて、メッセージヘッダの番地をカーネルに渡し、カーネルにメッセージヘッダの内容を書き換えさせた場合にも適用される。したがって、すでにメッセージキューに入っているメッセージを再度メールボックスに送信した場合の振舞いは未定義となる。
補足事項 | |
---|---|
メールボックス機能では、メッセージヘッダの領域をアプリケーションプログラムで確保することとしているため、メッセージキューに入れることができるメッセージの数には上限がない。また、メッセージを送信するシステムコールで待ち状態になることもない。 メッセージパケットとしては、固定長メモリプールまたは可変長メモリプールから動的に確保したメモリブロックを用いることも、静的に確保した領域を用いることも可能である。 一般的な使い方としては、送信側のタスクがメモリプールからメモリブロックを確保し、それをメッセージパケットとして送信し、受信側のタスクはメッセージの内容を取り出した後にそのメモリブロックを直接メモリプールに返却するという手順をとることが多い。 上記のような使い方をする場合のプログラム例を以下に示す。 /* メッセージの型定義 */ typedef struct { T_MSG msgque; /* メッセージヘッダ、T_MFIFO属性の場合 */ UB msgcont[MSG_SIZE]; /* メッセージ内容 */ } T_MSG_PACKET; /* メモリブロックの獲得とメッセージの送信を行うタスクの処理 */ T_MSG_PACKET *pk_msg; ... /* 固定長メモリプールからメモリブロックを獲得 */ /* 固定長メモリブロックサイズが sizeof(T_MSG_PACKET) 以上であること */ tk_get_mpf( mpfid, (void**)&pk_msg, TMO_FEVR ); /* pk_msg -> msgcont[] 以下にメッセージを作成 */ ... /* メッセージを送信 */ tk_snd_mbx( mbxid, (T_MSG*)pk_msg ); /* メッセージの受信とメモリブロックの解放を行うタスクの処理 */ T_MSG_PACKET *pk_msg; ... /* メッセージを受信 */ tk_rcv_mbx( mbxid, (T_MSG**)&pk_msg, TMO_FEVR ); /* pk_msg -> msgcont[] 以下のメッセージ内容の確認、それに応じた処理 */ ... /* 固定長メモリプールにメモリブロックを返却 */ tk_rel_mpf( mpfid, (void*)pk_msg ); |
pk_cmbx
の内容
メールボックスを生成しメールボックスID番号を割り当てる。具体的には、生成するメールボックスに対して管理ブロックなどを割り付ける。
exinf
は、対象メールボックスに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_mbx で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf
に入れる。カーネルでは exinf
の内容について関知しない。
mbxatr
は、下位側がシステム属性を表し、上位側が実装独自属性を表す。mbxatr
のシステム属性の部分では、次のような指定を行う。
mbxatr := (TA_TFIFO || TA_TPRI) | (TA_MFIFO || TA_MPRI) | [TA_DSNAME] | [TA_NODISWAI]
TA_TFIFO | 待ちタスクのキューイングはFIFO |
TA_TPRI | 待ちタスクのキューイングは優先度順 |
TA_MFIFO | メッセージのキューイングはFIFO |
TA_MPRI | メッセージのキューイングは優先度順 |
TA_DSNAME | DSオブジェクト名称を指定する |
TA_NODISWAI | tk_dis_wai による待ち禁止を拒否する |
TA_TFIFO, TA_TPRI では、メッセージを受信するタスクがメールボックスの待ち行列に並ぶ際の並び方を指定することができる。属性が TA_TFIFO であればタスクの待ち行列はFIFOとなり、属性が TA_TPRI であればタスクの待ち行列はタスクの優先度順となる。
一方、TA_MFIFO, TA_MPRI では、メッセージがメッセージキュー(受信されるのを待つメッセージの待ち行列) に入る際の並び方を指定することができる。属性が TA_MFIFO であればメッセージキューはFIFOとなり、属性が TA_MPRI であればメッセージキューはメッセージの優先度順となる。メッセージの優先度は、メッセージパケットの中の特定領域で指定する。メッセージ優先度は正の値で、1が最も優先度が高く、数値が大きくなるほど優先度は低くなる。PRI型で表せる最大の正の値が最も低い優先度となる。同一優先度の場合はFIFOとなる。
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_MFIFO 0x00000000 /* メッセージをFIFOで管理 */ #define TA_MPRI 0x00000002 /* メッセージを優先度順で管理 */ #define TA_DSNAME 0x00000040 /* DSオブジェクト名称を指定 */ #define TA_NODISWAI 0x00000080 /* 待ち禁止拒否 */
メールボックスで送受信されるメッセージの本体はメモリ上に置かれており、実際に送受信されるのはその先頭アドレスのみである。
mbxid
で示されたメールボックスを削除する。
本システムコールの発行により、対象メールボックスのID番号および管理ブロック用の領域などが解放される。
対象メールボックスにおいてメッセージを待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。また、対象メールボックスの中にメッセージが残っている場合でも、エラーとはならず、メールボックスの削除が行われる。
mbxid
で示された対象メールボックスに、pk_msg
を先頭アドレスとするメッセージパケットを送信する。
メッセージパケットの内容はコピーされず、受信時には先頭アドレス(pk_msg
の値)のみが渡される。したがって、このメッセージを受信したタスクがメッセージパケットの内容を取り出すまで、メッセージパケットの内容を書き換えてはいけない。
対象メールボックスで既にメッセージを待っているタスクがあった場合には、待ち行列の先頭のタスクの待ち状態が解除され、tk_snd_mbx で指定した pk_msg
がそのタスクに送信されて、tk_rcv_mbx のリターンパラメータとなる。一方、対象メールボックスでメッセージを待っているタスクが無ければ、送信されたメッセージは、メールボックスの中のメッセージキュー(メッセージの待ち行列)に入れられる。どちらの場合にも、tk_snd_mbx 発行タスクは待ち状態とはならない。
pk_msg
は、メッセージヘッダを含めたメッセージパケットの先頭アドレスである。メッセージヘッダは次の形式となる。
typedef struct t_msg { ? ? /* 内容は実装依存(ただし、固定長) */ } T_MSG; typedef struct t_msg_pri { T_MSG msgque; /* メッセージキューのためのエリア */ PRI msgpri; /* メッセージ優先度 */ } T_MSG_PRI;
メッセージヘッダは、TA_MFIFO の場合は T_MSG、TA_MPRI の場合は T_MSG_PRI となる。いずれの場合も、メッセージヘッダのサイズは固定長で、sizeof(T_MSG)またはsizeof(T_MSG_PRI)で取得する。
実際にメッセージを格納できるのは、メッセージヘッダより後ろの領域となる。メッセージ本体部分のサイズには制限はなく、可変長でもよい。
tk_snd_mbx によるメッセージ送信は、受信側のタスクの状態とは無関係に行われる。すなわち、非同期のメッセージ送信が行われる。待ち行列につながれるのは、そのタスクの発行したメッセージであって、タスクそのものではない。すなわち、メッセージの待ち行列(メッセージキュー)や受信タスクの待ち行列は存在するが、送信タスクの待ち行列は存在しない。
E_OK | 正常終了 |
E_ID | 不正ID番号(mbxid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mbxid のメールボックスが存在しない) |
E_PAR | パラメータエラー(tmout ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メールボックスが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_rcv_mbx では、mbxid
で示されたメールボックスからメッセージを受信する。
対象メールボックスにまだメッセージが送信されていない場合(メッセージキューが空の場合) には、本システムコールを発行したタスクは待ち状態となり、メッセージの到着を待つ待ち行列につながれる。一方、対象メールボックスに既にメッセージが入っている場合には、メッセージキューの先頭にあるメッセージを1つ取り出して、それをリターンパラメータ pk_msg
とする。
tmout
により待ち時間の最大値(タイムアウト値)を指定することができる。tmout
の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(メッセージが到着しない)まま tmout
の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。
tmout
として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、メッセージがない場合も待ちに入らず E_TMOUT を返す。また、tmout
として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにメッセージが到着するまで待ち続ける。
pk_msg
は、メッセージヘッダを含めたメッセージパケットの先頭アドレスである。メッセージヘッダは TA_MFIFO の場合は T_MSG、TA_MPRI の場合は T_MSG_PRI となる。
E_OK | 正常終了 |
E_ID | 不正ID番号(mbxid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mbxid のメールボックスが存在しない) |
E_PAR | パラメータエラー(tmout_u ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メールボックスが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_rcv_mbx のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_rcv_mbx と同じである。詳細は tk_rcv_mbx の説明を参照のこと。
pk_rmbx
の内容
mbxid
で示された対象メールボックスの各種の状態を参照し、リターンパラメータとして次に受信されるメッセージ(メッセージキューの先頭のメッセージ)、待ちタスクのID(wtsk
)、拡張情報(exinf
) を返す。
wtsk
は、このメールボックスで待っているタスクのIDを示す。このメールボックスで複数のタスクが待っている場合には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は wtsk
=0となる。
対象メールボックスが存在しない場合には、エラー E_NOEXS となる。
pk_msg
は、次に tk_rcv_mbx を実行した場合に受信されるメッセージである。メッセージキューにメッセージが無い時は、pk_msg
=NULL となる。また、どんな場合でも、pk_msg
=NULL と wtsk
=0の少なくとも一方は成り立つ。