1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Windowsシミュレータで学ぶuITRON (4) - ミューテックス

Last updated at Posted at 2019-11-21

はじめに

uITRON(FreeRTOSベース)Windowsシミュレータ - Qiita
https://qiita.com/imagou/items/42c687402e6e58fccddb

今回のお題は、排他の仕組みであるミューテックスです。

本編

1. 環境

こちらの記事を参照ください。

2. 動かしてみる

2-1. (おさらい)受信タスクにメッセージを飛ばす

コンソールで「10」と入力してみましょう(入力後にEnterを押してください)。

[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms
10
[SendTask]: RECV EVENT (00000400)
[RecvTask]: RECV MESSAGE (10,1)

RecvTaskが「10」を受信していることがわかるかと思います(2つ目の「1」は受信回数です)。

2-2. 受信タスクのロック~メッセージ送信

次に、コンソールで「lock」と入力してみましょう。

[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms
lock
[SendTask]: RECV EVENT (00800000)

特にコンソールには出てきませんが、この時点で受信タスクはロックしています。

※ただしTimerTaskまで止まってしまうのが謎なので、追って調査します・・・
(2019/11/22) 解決させました。

その後、「11」「12」を入力してみます。

11
[SendTask]: RECV EVENT (00000800)
12
[SendTask]: RECV EVENT (00001000)

受信タスクがロックしているため、RecvTaskうんぬんのログが出ません。

2-3. 受信タスクのアンロック

「unlock」を入力し、受信タスクをアンロックしてやります。

unlock
[RecvTask]: RECV MESSAGE (11,3)
[RecvTask]: RECV MESSAGE (12,4)
[TimerTask]: DELAY 3000ms
[TimerTask]: DELAY 3000ms

解放されたRecvTaskが、「11」「12」を順に受信していることがわかるかと思います。

3. 解説

3-1. 概要

ミューテックスは、RTOSに限らずよく利用されている、排他の仕組みです。

主たる利用方法は、**「共通のリソースを複数のタスクで触りたい」**場合かと思います。
(今回の例はあくまで動作確認用のため、タスクの停止・再開用途ですが、実用的ではないかと・・・)

3-2. コードによる説明

以降は、プログラムコード - main.cを引用して説明します。

3-2-1. ミューテックス生成

cre_mtx()で生成します。

    T_CMTX cmtx;
    cmtx.mtxatr = TA_TFIFO;
    cre_mtx(MTX_ID(RECV), &cmtx);

このパラメータは下表:

パラメータ番号 名称 説明
第1パラメータ ミューテックスID 単なるID。
以降はこのIDでもってロック・アンロックを実施。
第2パラメータ T_CMTX構造体変数 下表で説明。

T_CMTXのメンバは下表:

名称 指定可能な値 説明
mtxatr TA_TFIFO | TA_TPRI ミューテックス属性。
それぞれ、待ちキューの順序をFIFO順とするか、優先度順とするか。

※なお、mtxatrはこれ以外の値も指定可能(だが、上記のみで必要十分と考える)。

3-2-2. ミューテックスのロック

loc_mtx()を使います(以下は受信タスクのコード)。
資源がロックされていればアンロックまで待ちますし、そうでなければ即抜けます。

        /* Lock/Unlock Mutex */
        loc_mtx(MTX_ID(RECV));
        unl_mtx(MTX_ID(RECV));

以下(コマンドタスク)ではploc_mtx()を使っています。
pはポーリングを意味し、こちらは待ちに入りません。

すなわち、資源がロックされていれば即エラーE_TMOUTを返し、そうでなければ即E_OKを返します。
(コメントの通り、コマンドタスクでの多重ロックを避けるために使用しています)

        /* Lock */
        else if (EQUALS_(lock)) {
            /* 多重ロックを避けるためポーリングとする。 */
            if (ploc_mtx(MTX_ID(RECV)) == E_OK) {
                /* ダミーメッセージを投げ、ロック待ちに遷移させる。 */
                set_flg(FLAG_ID(SEND), EVENT_DUMMY);
            }
        }

3-2-3. ミューテックスのアンロック

unl_mtx()を使います。
資源がロックされていたらアンロック(解放)します。この関数は待ちません。

ざっくり書くと
コマンドタスクのアンロックにより、受信タスクのロックが解除されて動き出す
というカラクリです。

        /* Unlock */
        else if (EQUALS_(unlock)) {
            unl_mtx(MTX_ID(RECV));
        }

おわりに

複数の資源を扱えるセマフォという輩もいますが、概ねミューテックスで事足りると思います。

根本的には、排他不要な設計がベストと思いますが、どうしようもない場合(笑)に利用ください!

参考

Micro-ITRON4.0 Specification (in Japanese)
http://www.ertl.jp/ITRON/SPEC/mitron4-j.html

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?