LOCK(9)

名称
lockinit, lockdestroy, lockcount, lockmgr, lockstatus, lockmgr_printinfo - lockmgr ファミリの関数

書式
<sys/types.h> <sys/lockmgr.h> void lockinit(struct lock *lkp, int prio, const char *wmesg, int timo, int flags) void lockdestroy(struct lock *lkp) int lockcount(struct lock *lkp) int lockmgr(struct lock *lkp, u_int flags, struct mtx *interlkp, struct thread *td) int lockstatus(struct lock *lkp, struct thread *td) void lockmgr_printinfo(struct lock *lkp)

解説
lockinit() 関数はロックを初期化するために使用されます。 これはロックに関する実行されることが可能なあらゆる操作の前に、 呼び出されなければなりません。 引数は以下の通りです。

lkp 初期化されるべきロックへのポインタです。

prio
    msleep(9) に渡される優先度です。

wmesg
    ロックのメッセージです。 これはデバッグ出力と msleep(9) の両方のために使用されます。

timo
    msleep(9) に渡されるタイムアウト値です。

flags
    ロックを初期化するために使用されるべきフラグです。

    LK_NOWAIT
        ロックを獲得するとき、スリープしません。

    LK_SLEEPFAIL
        スリープした後に失敗します。

    LK_CANRECURSE
        再帰的な排他ロックを許可します。

    LK_REENABLE
        ロックをドレインした後、そのロックを再度有効化します。

    LK_NOPAUSE
        ロックを獲得するとき、スピンロックを使用しません。

    LK_TIMELOCK
        スリープしている間 timo を使用します。そうでなければ 0 が使用されます。

lockdestroy() 関数はロックを破壊するために使用され、カーネル内のいくつかの場所で 呼び出されますが、現在は何もしません。

lockcount() 関数はロック lkp に対する排他ロックと共有ロックのカウント数を返します。

lockmgr() 関数は共有ロックと排他ロックおよび再帰のサポートを含む、 カーネル内部の一般的なロック機能を取り扱います。 lockmgr() はロックのアップグレードとダウングレードも可能です。

引数は以下の通りです。

lkp 操作するべきロックへのポインタです。

flags
    行なわれるべき操作を示しているフラグです。

    LK_SHARED
        共有ロックを獲得します。 現在排他ロックが保持されている場合には、ダウングレードされます。

    LK_EXCLUSIVE
        排他ロックを獲得します。 既に排他ロックが保持されていて、 LK_CANRECURSE が設定されていない場合には、システムは panic(9) します。

    LK_DOWNGRADE
        排他ロックから共有ロックにダウングレードします。 共有ロックのダウングレードは許可されていません。 排他ロックが既に再帰している場合には、全ての参照がダウングレードされます。

    LK_EXCLUPGRADE
        共有ロックから排他ロックにアップグレードします。 他の誰かが先にアップグレードを待っている最中の場合には、 EBUSY で失敗します。 この呼び出しが失敗した場合には、その共有ロックは失われます。 排他ロックのアップグレードの試みは panic(9) を引き起こします。

    LK_UPGRADE
        共有ロックから排他ロックにアップグレードします。 この呼び出しが失敗した場合には、その共有ロックは失われます。 排他ロックのアップグレードの試みは panic(9) を引き起こします。

    LK_RELEASE
        ロックを解放します。 保持していないロックの解放は、 panic(9) を引き起こすことがあります。

    LK_DRAIN
        ロック上の全ての行動の終了を待ち、それから役割を終えた印を付けます。 今にも解放されようとしているメモリの一部分のロックを解放する前に使用されます。 <(> sys/lockmgr.h に解説されています。)

    LK_SLEEPFAIL
        操作がスリープした場合には、失敗します。

    LK_NOWAIT
        この呼び出しがスリープすることを認めません。 これはロックをテストするために使用することが可能です。

    LK_CANRECURSE
        排他ロック上の再帰を認めます。 それぞれのロックに対し、解放が存在しなければなりません。

    LK_INTERLOCK
        (既にロックされているべき) 相互ロックをロック解除します。

interlkp
    ロックへのグループアクセスを制御するための相互ロック mutex です。 LK_INTERLOCK が指定された場合には、 lockmgr() は interlkp は現在所有されていて再帰していないと仮定し、ロック解除されて返します。 mtx_assert(9) を参照してください。

td  この呼び出しに責任があるレッドです。 NULL は LK_KERNPROC になります。

lockstatus() 関数は渡された thread に関するロックの状態を返します。 td が NULL で排他ロックが保持されている場合には、 LK_EXCLUSIVE が返されます。

lockmgr_printinfo() 関数はロックについてのデバッグ情報を出力します。 これは主に VOP_PRINT(9) 関数によって使用されます。

戻り値
lockcount() 関数は 0 以上の整数を返します。

lockmgr() 関数は成功時には 0 を、失敗時には 0 ではない値を返します。

lockstatus() 関数は以下の値を返します。

LK_EXCLUSIVE
    スレッド td によって排他ロックが保持されています。

LK_EXCLOTHER
    スレッド td ではない他の誰かよって排他ロックが保持されています。

LK_SHARED
    共有ロックが保持されています。

0   だれもロックを保持していません。

エラー
lockmgr() は次の場合に失敗します。

[EBUSY]
    LK_FORCEUPGRADE が要求されて、ほかのスレッドが既にロックのアップグレードを要求しています。

[EBUSY]
    LK_NOWAIT が設定されて、スリープが要求されていました。

[ENOLCK]
    LK_SLEEPFAIL が設定されて、 lockmgr() は既にスリープしました。

[EINTR]
    ロックの優先度に PCATCH が設定されて、スリープしている間にシグナルが配送されました。 下記の ERESTART エラーに注意してください。

[ERESTART]
    ロックの優先度に PCATCH が設定されて、スリープしている間にシグナルが配送され、システムコールが 再スタートされました。

[EWOULDBLOCK]
    0 でないタイムアウトが与えられ、そのタイムアウトが満了しました。

ロック
lockmgr() への flags 引数に LK_INTERLOCK が渡された場合には、 interlkp は lockmgr() を呼び出すために以前に保持されていなければならず、ロック解除されて返されます。

失敗するアップグレードの試みは、現在保持しているロックを失わせる 結果になります。 また、排他ロックのアップグレードは無効で、試行の結果として panic(9) を引き起こします。

関連項目
msleep(9), mtx_assert(9), panic(9), VOP_PRINT(9)

作者
このマニュアルページは Chad David <davidc@acns.ab.ca> が書きました。