Oracle Solaris Studio 12.4 Man Pages

印刷ビューの終了

更新: January 2015
 
 

lock_lint(1)

名前

lock_lint - マルチスレッドプログラムでロックの使用法を検証する

形式

lock_lint subcommand

説明

LockLint は ANSI C のソースコードを静的に解析することによって、一貫していない相互排他ロックや読み取り/書き込みロックによるデータ競合やデッドロックを検出するためのツールです。LockLint は Oracle Solaris の libthread API 機能を使用している ANSI C のプログラマをサポートします。

LockLint には、次の 2 つのインタフェースがあります。

サブコマンド

コマンド行 (またはスクリプト) から次の書式で指定します。

lock_lint subcommand
ソースコード注釈

ソースコードに直接入力します。サブコマンドよりソースコード注釈数は少ないですが、サブコマンドより望ましい場合が多くあります。

LockLint セッションを開始するには、次のように入力します。

lock_lint start

これは、ユーザー指定のサブシェルを、確立された適切な LockLint コンテキストで起動します。(詳細は、下記の start サブコマンドを参照してください。)

LockLint でソースコードを解析するには、最初に C コンパイラの -Zll オプションを使用してそのコードをコンパイルしておく必要があります。次に C コンパイラは、コンパイル済みの各 .c ファイルに 1 つずつ LockLint のデータベースファイル (.ll ファイル) を生成します。.ll ファイルは、あとで load サブコマンドによって LockLint にロードされます。

サブコマンド

LockLint セッションの実行中に、LockLint サブコマンドについてすばやく調べるには、LockLint の help サブコマンドを使用します (下記を参照)。

サブコマンドにはわかりやすい別名を付けることができます (使用しているシェルで可能な場合)。また、サブコマンドをスクリプトファイルに入れて、そのスクリプトを実行することも可能です。

analyze [-hv]

ロードされたファイルについて、データ競合およびデッドロックを引き起こす可能性のあるロックの不整合を解析します。このサブコマンドは大量の出力を生成することがあるため、出力をファイルにリダイレクトするとよいでしょう。この指令は、保存された各状態に対して一度だけ実行することができます (save を参照)。

この解析が終了したあとは、「vars」および「order」サブコマンドの出力の中に、潜在的な問題をさらに見つけることができます。たとえば、コマンド

lock_lint vars -h | fgrep *

いずれのロックによっても適切に保護されていない変数が表示されます。

assert side effect mutex acquired in func ...
assert side effect rwlock [read] acquired in func ...
assert side effect mutex|rwlock released in func ...
assert side effect rwlock upgraded|downgraded in func ...
assert mutex|rwlock protects var ...
assert mutex protects func ...
assert rwlock protects [reads in] func ...
assert order lock lock ...
assert read only var ...
assert rwlock covers lock ...

ロックの使用に関する表明を LockLint に提供します。解析中 LockLint は、これらの表明に対する違反があれば報告します。

declare mutex mutex ...
declare rwlocks rwlock ...
declare func_ptr targets func ...
declare nonreturning func ...
declare one tag ...
declare readable var ...
declare root func ...

プログラム内のロック、関数、および変数についてさまざまな属性を宣言します。

disallows

disallow サブコマンドを使用して指定された、禁止された呼び出しシーケンスを一覧表示します。

exit

LockLint を終了するには、使用中のシェルの終了コマンドを実行してください。lock_lint start コマンドで起動されたサブシェルが終了すると、LockLint も終了します。

files

load サブコマンドを介してロードされる .ll ファイルで表されたソースコードファイルを一覧表示します。

funcptrs [-botu] func_ptr ...
funcptrs [-blotuz]
funcptrs [-botu] func_ptr ...
funcptrs [-blotuz]

ロードされたファイル内で使用されている関数ポインタの情報を一覧表示します。

funcs [-adehou] func ...
funcs [-adehilou]
funcs [-adehlou] [directly] called by func ...
funcs [-adehlou] [directly] calling func ...
funcs [-adehlou] [directly] reading var ...
funcs [-adehlou] [directly] writing var ...
funcs [-adehlou] [directly] accessing var ...
funcs [-adehlou] [directly] affecting lock ...
funcs [-adehlou] [directly] inverting lock ...

ロードされたファイル内で定義または呼び出し、あるいはその両方が行われている関数の情報を一覧表示します。

help [subcommand]

help サブコマンドをトピックなしで指定すると、サブコマンドの一覧とそのオプションおよび一般的なヘルプ情報を表示できます。次の構文でサブコマンドを指定すると、その詳細なヘルプ情報を表示できます。

lock_lint help サブコマンドの最初の 1 語

次のキーワードに関するヘルプも用意されています。

 
condvars       inversions        names
example        limitations       overview
exit              locking           shell
ifdef             makefile
shell
ignore func|var ... [in func ... ]

特定の関数と変数を解析から除外するよう LockLint に指示します。除外する対象は、「in func ...」句を使用して特定の関数に限定することができます。それ以外の場合は、すべての関数が除外の対象となります。

load file ...

指定された .ll ファイルをロードします。拡張子は省略してかまいませんが、指定する場合は必ず .ll にしてください。パスは絶対パスと相対パスのどちらでもかまいません。次の指定は正当です (ただしシェルの機能によります)。

 
lock_lint load *.ll
lock_lint load ../foo/abcdef{1,2}
lock_lint load `find . -name ll
locks [-co] lock ...
locks [-clo]
locks [-clo] [directly] affected by func ...
locks [-clo] [directly] inverted by func ...

ロードされたファイルのロックに関する情報を一覧表示します。ロックを操作するルーチンで実際に使用されている変数だけが表示されます。宣言されただけで操作されないロックは表示されません。

members struct_tag

指定されたタグのある構造体のメンバーを 1 行に 1 つずつ一覧表示します。タグが割り当てられていない構造体に対しては、「ファイル@行番号」(「x.c@29」など) という表記が使用されます。ファイルと行番号は、構造体が宣言されているソースの位置です。

order [lock [lock]].

解析中のコードによって獲得されるロックの順序に関する情報を一覧表示します。これは解析が完了したあとでのみ実行できます。

pointer calls

ロードされたファイル内の関数ポインタによって行われた呼び出しを一覧表示します。

reallow func ...

disallow サブコマンドの例外を許可します。

reallows

reallow サブコマンドを使用して指定された、ふたたび許可された呼び出しシーケンスを一覧表示します。

refresh

状態保存スタックをポップして、LockLint を状態保存スタックのいちばん上の状態に戻します。その状態に関連付けられている説明が出力されます。次に、同じ説明を使用して状態を再保存 (プッシュ) します (そのため、restore または refresh で再度利用できます)。

restore

状態保存スタックをポップして、LockLint を状態保存スタックのいちばん上の状態に戻します。その状態に関連付けられている説明が出力されます。

save description

スタック上にツールの現在の状態を保存します。指定された説明が状態に関連付けられます。状態は LIFO (後入れ先出し) スタックに保存されるため、最後に保存された状態が最初に復元されます。

saves

save サブコマンドによってスタックに保存された状態の説明を一覧表示します。説明は上から下へ順に表示されます。つまり、最後に保存されてまだ復元されていない状態の説明が最初に表示されます。最初に保存されてまだ復元されていない状態の説明が最後に表示されます。

start cmd

LockLint セッションを開始します。LockLint セッションは、ほかの LockLint サブコマンドを使用する前に開始されなければなりません。デフォルトでは、start サブコマンドは LockLint のコンテキストを確立し、そのコンテキスト内で、$SHELL によって指定されたユーザー用サブシェルを起動します。サブシェルにエクスポートされる LockLint コンテキストの唯一の部分は、環境変数 LL_CONTEXT です。LL_CONTEXT は、LockLint セッションを維持するために使用されるファイルの一時ディレクトリのパスを含んでいます。

sym name ...

ロードされたファイル内で指定した名前 name で参照できるものを一覧表示します。たとえば、コンテキストによって、「foo」は変数である「x.c:func1/foo」を表す場合と、関数である「y.c:foo」を表す場合の両方があります。

unassert vars var ...

指定の変数を保護するロックに関する表明を取り消します。関数を保護するロックに関する表明は削除できません。

vars [-aho] var ...
vars [-ahilo]
vars [-ahlo] protected by lock
vars [-ahlo] [directly] read by func...
vars [-ahlo] [directly] written by func ...
vars [-ahlo] [directly] accessed by func ...

ロードされたファイルの変数に関する情報を一覧表示します。実際に使用される変数だけが表示されます。プログラム内で宣言されただけでアクセスされない変数は表示されません。

ソースコード注釈

ソースコード注釈
ASSERT(NO_LOCKS_HELD);
assert(NO_LOCKS_HELD);

コードのこの位置に到達した時点でこの判定を実行しているスレッドによって保持されているロックはないはずであると LockLint に知らせます。違反がある場合は、解析中に報告されます。

ASSERT(NO_COMPETING_THREADS);
assert(NO_COMPETING_THREADS);

コードのこの位置に到達した時点でこのコードを実行しているスレッドと競合するほかのスレッドはないはずであると LockLint に知らせます。違反がある (NOTE 形式の何らかの表明によって得られる情報に基づいて判断) 場合は、解析中に報告されます。

ASSERT(MUTEX_HELD(lock_expr) && ...);
assert(MUTEX_HELD(lock_expr) && ...);

実行中のスレッドが記述どおりのロックを保持していない場合に、エラーが報告されます。

NOTE(MUTEX_PROTECTS_DATA(Mutex, DataNameList));
NOTE(RWLOCK_PROTECTS_DATA(Rwlock, DataNameList));
NOTE(SCHEME_PROTECTS_DATA("description", DataNameList));

最初の 2 つの注釈は、指定のデータがアクセスされるときは常にロックが保持されているはずであると LockLint に知らせます。

3 番目の注釈 SCHEME_PROTECTS_DATA は、相互排他または読み取り/書き込みロックでは保護されないデータをどのように保護するかを記述したものです。このスキームで指定する description は単なるテキストです。

NOTE(READ_ONLY_DATA(DataNameList));

データが読み取り専用であり、書き込まれるべきではないと LockLint に知らせます。

NOTE(DATA_READABLE_WITHOUT_LOCK(DataNameList));

保護ロックを保持せずに指定のデータを読み取れることを LockLint に知らせます。

NOTE(RWLOCK_COVERS_LOCKS(RwlockName, LockNameList));

読み取り/書き込みロックとほかのロックの集合との間に階層的な関係があることを LockLint に知らせます。

NOTE(MUTEX_ACQUIRED_AS_SIDE_EFFECT(MutexExpr));
NOTE(READ_LOCK_ACQUIRED_AS_SIDE_EFFECT(RwlockExpr));
NOTE(WRITE_LOCK_ACQUIRED_AS_SIDE_EFFECT(RwlockExpr));
NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(LockExpr));
NOTE(LOCK_UPGRADED_AS_SIDE_EFFECT(RwlockExpr));
NOTE(LOCK_DOWNGRADED_AS_SIDE_EFFECT(RwlockExpr));
NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT);
NOTE(COMPETING_THREADS_AS_SIDE_EFFECT);

関数が指定のロックに対して指定の副作用を持つことを LockLint に知らせます。つまり、関数が、終了時のロック状態を入り口でのロック状態とは意図的に異なる状態にするということです。これらの注釈のうち最後の 2 つの副作用は、ロックではなく並行性に関するものです。

NOTE(COMPETING_THREADS_NOW);
NOTE(NO_COMPETING_THREADS_NOW);

最初の注釈は、コードのこの位置以降ではこのスレッドがアクセスするのと同じデータにアクセスしようとするほかのスレッドが存在することを LockLint に知らせます。2 番目の関数は、この状況が終了したこと、つまり実行中のほかのスレッドがないか、または実行中のどのスレッドもこのスレッドがアクセスするデータにはアクセスしないことを示します。

NOTE(NOT_REACHED);

コードの特定の位置に到達できないこと、したがってその位置で保持されているロックの状況を無視するべきであることを LockLint に知らせます。ロックの順序

NOTE(LOCK_ORDER(LockNameList));

ロックが獲得されるべき順序を指定します。

NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(DataExpr, ...));
NOTE(NOW_VISIBLE_TO_OTHER_THREADS(DataExpr, ...));

指定の式で表現される変数がほかのスレッドから可視であるかどうか、つまりほかのスレッドがその変数にアクセスできるかどうかを LockLint に知らせます。

NOTE(ASSUMING_PROTECTED(DataExpr, ...));

指定の式によって表現される変数が保護されていると見なすことを LockLint に知らせます。保護の方法は、各変数に対して適切なロックが保持されているか、変数がほかのスレッドから不可視であるか、呼び出し時に競合するスレッドがないか、のいずれかです。

環境変数

LL_CONTEXT

コンテキストディレクトリへのパスが含まれています

SHELL

デフォルトのシェルとして使用されます

TMPDIR

デフォルトの一時ディレクトリのパスとして使用されます

関連項目

Oracle Solaris Studio の完全なドキュメントについては、http://www.oracle.com/technetwork/server-storage/solarisstudio/documentation を参照してください

注意事項

注意事項

現在、LockLint は .ll ファイルがソースファイルに対して古くなっているかどうかを検査しません。

ファイル

file.ll

cc からの LockLint 用データベースファイル

lock_lint

lock_lint コマンド

lock_lint_server

LockLint エンジン

help

ヘルプファイルのディレクトリ

cmd.ll_help

cmd に関するヘルプトピック

エラー

lock_lint コマンドの終了ステータスは次のとおりです。

0

正常

1

システムエラー

2

ユーザーエラー (オプションが正しくない、未定義の名前など)

3

複数の種類のエラー

5

Lock_lint がエラーを検出した (表明違反、データ競合やデッドロックの可能性を検出した、保護されていないデータを参照した、など)。

10

ライセンスエラー