.\" .\" Copyright (C) 2001 Jason Evans . All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice(s), this list of conditions and the following disclaimer as .\" the first lines of this file unmodified other than the possible .\" addition of one or more copyright notices. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice(s), this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY .\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE .\" DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY .\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES .\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR .\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER .\" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH .\" DAMAGE. .\" .\" %FreeBSD: src/share/man/man9/sx.9,v 1.29.2.2 2005/01/17 11:34:57 keramida Exp % .\" .\" $FreeBSD$ .Dd August 14, 2001 .Dt SX 9 .Os .Sh 名称 .Nm sx , .Nm sx_init , .Nm sx_destroy , .Nm sx_slock , .Nm sx_xlock , .Nm sx_try_slock , .Nm sx_try_xlock , .Nm sx_sunlock , .Nm sx_xunlock , .Nm sx_try_upgrade , .Nm sx_downgrade , .Nm sx_assert , .Nm sx_unlock , .Nm SX_SYSINIT .Nd カーネルの共有/排他ロック .Sh 書式 .In sys/param.h .In sys/lock.h .In sys/sx.h .Ft void .Fn sx_init "struct sx *sx" "const char *description" .Ft void .Fn sx_destroy "struct sx *sx" .Ft void .Fn sx_slock "struct sx *sx" .Ft void .Fn sx_xlock "struct sx *sx" .Ft int .Fn sx_try_slock "struct sx *sx" .Ft int .Fn sx_try_xlock "struct sx *sx" .Ft void .Fn sx_sunlock "struct sx *sx" .Ft void .Fn sx_xunlock "struct sx *sx" .Ft int .Fn sx_try_upgrade "struct sx *sx" .Ft void .Fn sx_downgrade "struct sx *sx" .Ft void .Fn sx_assert "struct sx *sx" "int what" .\" .Ss Nm Ss ユーティリティマクロ .Fn sx_unlock "struct sx *sx" .Fn SX_SYSINIT "name" "struct sx *sx" "const char *description" .\" .Ss カーネルオプション .Cd "options INVARIANTS" .Cd "options INVARIANT_SUPPORT" .Sh 解説 共有/排他ロックは書き込まれるよりも、読み込まれる方が非常に多いデータを 保護するために使用されます。 mutex は本質的に共有/排他ロックよりも能率的なので、共有/排他ロックは 用心深く使用されるべきです。 .Pp 共有/排他ロックは .Fn sx_init を使用して作成されます。 ここで .Fa sx は .Vt struct sx のための領域へのポインタで、 .Fa description はその共有/排他ロックを説明するヌルで終端された文字列へのポインタです。 共有/排他ロックは .Fn sx_destroy を使用して破壊されます。 スレッドは .Fn sx_slock または .Fn sx_try_slock および .Fn sx_sunlock または .Fn sx_unlock の呼び出しによって共有ロックを獲得および解放します。 スレッドは .Fn sx_xlock または .Fn sx_try_xlock および .Fn sx_xunlock または .Fn sx_unlock の呼び出しによって排他ロックを獲得および解放します。 スレッドは .Fn sx_try_upgrade の呼び出しによって、現在保有している共有ロックから排他ロックへの アップグレードを試みることが可能です。 排他ロックを持っているスレッドは、 .Fn sx_downgrade の呼び出しによってその排他ロックから共有ロックへのダウングレードが可能です。 .Pp .Fn sx_try_slock および .Fn sx_try_xlock は共有/排他ロックがすぐに獲得できなかった場合には 0 を返し、 そうでない場合には共有/排他ロックが獲得され 0 ではない値が返されます。 .Pp .Fn sx_try_upgrade は共有ロックをすぐに排他ロックにアップグレードできない場合には 0 を返し、 そうでない場合には排他ロックが獲得され 0 ではない値が返されます。 .Pp .Cd "options INVARIANTS" および .Cd "options INVARIANT_SUPPORT" 付きでコンパイルされたときには、 .Fn sx_assert 関数は .Fa what に指定されたアサートのために .Fa sx をテストし、それらが合わなかった場合には panic します。 以下のアサートがサポートされています。 .Bl -tag -width ".Dv SX_UNLOCKED" .It Dv SX_LOCKED 現在のスレッドが、最初の引数によって指されている .Vt sx ロック上に、共有または排他ロックのいずれかを持っていることをアサートします。 .It Dv SX_SLOCKED 現在のスレッドが、最初の引数によって指されている .Vt sx ロック上に、共有ロックを持っていることをアサートします。 .It Dv SX_XLOCKED 現在のスレッドが、最初の引数によって指されている .Vt sx ロック上に、排他ロックを持っていることをアサートします。 .It Dv SX_UNLOCKED 現在のスレッドが、最初の引数によって指されている .Vt sx ロック上に、ロックを持っていないことをアサートします。 .El .Pp プログラミングを簡単にするために、 .Fn sx_sunlock および .Fn sx_xunlock 各々の関数へのフロントエンドマクロとして .Fn sx_unlock が提供されています。 ロックがどの状態になっているかを知っているアルゴリズムは、 小さなパフォーマンスの利益のために各々の 2 つの特定の関数を使用すべきです。 .Pp .Fn SX_SYSINIT マクロはシステムスタートアップ時に与えられた .Fa sx ロックを初期化するために .Fn sx_sysinit の呼び出しを生成します。 引数は .Fn sx_init と同様ですが、 そのロックと sysinit ルーチンに関連付けられた構造体に関連した唯一の 変数名を生成する際に使用される追加の引数として .Fa name を持ちます。 .Pp スレッドは同じロック上に共有ロックと排他ロックを同時には持つことができません。 同時に持つことはデッドロックを引き起こすことになるためです。 .Sh コンテキスト スリープしている間に .Nm ロック上に共有ロックまたは排他ロックを所有することは許可されます。 その結果、ミューテックスを保持している間、 .Nm ロックは獲得されないかもしれません。 そうでなければ、ミューテックスを獲得した後に同じ .Nm ロック上で別のスレッドがブロックされる間に、 一つのスレッドが .Nm ロックを保持している間にスリープするなら、 事実上、2 番目のスレッドは最後には許可されていないミューテックスを 保持している間にスリープすることになるでしょう。 .Sh 関連項目 .Xr condvar 9 , .Xr mtx_pool 9 , .Xr mutex 9 , .Xr panic 9 , .Xr sema 9 .Sh バグ 現在、ロックが保持されていないことをアサートする方法がありません。 .Dv WITNESS ではない場合には、このスレッドが共有ロックを保持していないことを アサートすることは不可能です。 .Dv WITNESS ではない場合には、 .Dv SX_LOCKED および .Dv SX_SLOCKED のアサートは、あるスレッドが共有ロックを保持していることを 単にチェックするに過ぎません。 これらは、現在のスレッドが共有ロックを保持していることを保証しません。