« 自前のセマフォは案外たいへん(3) | トップページ | セマフォとミューテックス(1) »

2018年7月16日 (月)

自前のセマフォは案外たいへん(おまけ)

自前セマフォの説明は前回までの3回で一通り終わりですが、おまけを少々書きたいと思います。

このセマフォに関する一連の記事を書き始める前は、「セマフォはキュー」というタイトルで簡単に書けると思っていました。しかし、昔考えていたコードに不備が有り、久し振りと言うこともあって修正に手こずりました。それで、タイトルが「自前のセマフォは案外たいへん」となりました。

前回までに説明したコードで、修正したい箇所が有ります。1つは mtx_lock() 内でのプロセス ID 取得に関することです。 mtx_lock() 内でセマフォ獲得の度に ID 取得のためのシステムコールを発行していますが、これは前もって獲得しておいた方が良かったと思います。なお、その場合は、セマフォを即刻に獲得出来る場合にダミーの ID である DMYID を使わずに本当の ID を使うことが出来るようにもなります。

2つ目の修正個所は que->firstque->last の進行方向についてです。これらは 0 から開始して増加させていますが、 que->size - 1 から開始して減少させた方が良いでしょう。そうすれば、これらインデックスが配列の端に到達したことの確認を下記 (7-1) のように 0 との比較で実行出来ます。その方が、アセンブラのレベルで考えると (7-2) よりもお得です。


    if (que->last < 0){        /* (7-1) */
        ・・・
    }
	・・・
    if (que->last == que->size){        /* (7-2) */
		・・・
    }

ところで、2つ目の修正個所にも関連するのですが、 que->firstque->last(que->first+1)%que->size などと剰余計算にすべきかどうか迷いました。++(que->first) の後で、条件分岐するのと剰余計算にするのとどっちがお得か判らなかったのですが、条件分岐の方が良いような気がしたので、そちらを選びました。

重大な問題が1つ。2進セマフォとミューテックスは同じものだと思っていたのですが、 Wikipedia によると、ロックしたものだけがアンロック出来るという制限を付けたものがミューテックスだとあります。これは今まで知りませんでした。実は、 mtx_unlock() など mtx_ としているのは、 mutex を意識してのことでした。しかし、今回作成したものは、ロックしたものだけがアンロック出来るという制限を設けていません。今回の実装は、ロックしていないものがアンロックすることを想定していなかったので、そのような想定外の使用をされるとマズイことになりそうです。 Wikipedia の意味でのミューテックスへの変更、もしくは、セマフォとしての設計変更が必要でしょう。

ミューテックスへの変更は簡単です。アンロックしようとしているのがロックしたスレッドであることを保証すれば良いのです(que->id[que->first] をチェックすれば良い)。それに対して、セマフォとして正当化するのは難しそうです。それこそ、今シリーズのタイトル「自前のセマフォは案外たいへん」ということでオチが付きました。

このアンロックの制限に関連して mtx_unlick() 内の spinunlock() の位置に問題が有ることも分りました。


void mtx_unlock(queue_t *que)
{
    process_id id_next;

    spinlock(&(que->lock));
    que->id[que->first] = 0;
    if (++(que->first) == que->size)
        que->first = 0;
    id_next = que->id[que->first];
    spinunlock(&(que->lock));        /* (8-1) */
    if (id_next != 0){
        _os_send(id_next, que->signal);    /* (8-2) */
    }
/*  spinunlock(&(que->lock));*/          /* (8-3) */
} /* end of mtx_unlock() */

(8-1) でスピンロックを解除したら、 (8-2) でシグナルを送る前に他のスレッドによって待ち行列を操作される可能性が有ります。したがって、スピンロックの解除は (8-3) にしなければなりません。しかし、そうしたとしても、今回の実装では、アンロック出来るのはロックしたスレッドだけという保証を設けていないので問題は残ります。

Udegishiki

最後に、セマフォの写真を載せておきます。鉄道の腕木式信号です。

« 自前のセマフォは案外たいへん(3) | トップページ | セマフォとミューテックス(1) »

プログラミング」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/584699/66945548

この記事へのトラックバック一覧です: 自前のセマフォは案外たいへん(おまけ):

« 自前のセマフォは案外たいへん(3) | トップページ | セマフォとミューテックス(1) »