Oracle Solaris Studio 12.4 Man Pages

Exit Print View

Updated: January 2015
 
 

lock_lint(1)

Name

lock_lint - 验证多线程程序中锁的使用

Synopsis

lock_lint subcommand

Description

LockLint 工具可静态分析 ANSI C 源代码,帮助检测由于互斥锁和读取器-写入器锁使用不一致而引起的数据争用和死锁。LockLint 使用 Oracle Solaris libthread API 功能支持 ANSI C 程序员。

LockLint 有两个界面:

子命令

这些从命令行(或从脚本)输入,采用格式:

lock_lint subcommand
源代码注释

这些直接输入到源代码中。尽管源代码注释比子命令要少,但是它们通常比子命令更可取。

要启动 LockLint 会话,请键入:

lock_lint start

这样将启动用户可指定的子 shell,并建立相应的 LockLint 上下文。(有关更多信息,请参见下文的 start 子命令。)

要使 LockLint 分析源代码,必须首先使用 C 编译器的 -Zll 选项编译代码。然后,C 编译器将生成 LockLint 数据库文件(.ll 文件),为编译的每个 .c 文件生成一个。.ll 文件随后将通过 load 子命令装入到 LockLint 中。

Sub Commands

要在 LockLint 会话期间查看有关任何 LockLint 子命令的快速信息,请使用 LockLint help 子命令(请参见下文)。

为了简便高效,您可以为子命令创建别名(如果 shell 允许);您还能将子命令放入脚本文件并运行该脚本。

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,请使用您正在使用的 shell 的退出命令。由 lock_lint start 命令启动的子 shell 退出时,LockLint 即会退出。

files

列出由通过装入子命令装入的 .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 first word of subcommand

还提供关于以下关键字的帮助:

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

告知 LockLint 从分析中排除某些函数和变量。可使用 "in func ..." 子句将这种排除限制到特定函数;否则,排除将应用于所有函数。

load file ...

装入指定的 .ll 文件。扩展名可省略,但是如果指定了扩展名,它必须是 .ll。允许使用绝对路径和相对路径。以下内容合法(取决于 shell 的功能):

 
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

列出带有指定标记的结构的成员,每行一个。对于未分配标记的结构,使用 "file@line" 表示法(例如 "x.c@29"),其中文件和行号是结构声明的源位置。

order [lock [lock]]

列出关于分析的代码获取锁的顺序的信息。只有分析完成后才能运行。

pointer calls

列出通过已装入文件中的函数指针进行的调用。

reallow func ...

允许对 disallow 子命令破例。

reallows

列出重新允许的调用序列,如使用 reallow 子命令所指定。

refresh

弹出保存的状态堆栈,将 LockLint 恢复到保存的状态堆栈顶部的状态。将输出与该状态关联的描述。然后以相同的描述再次保存该状态(以便重新恢复/刷新)。

restore

弹出保存的状态堆栈,将 LockLint 恢复到保存的状态堆栈顶部的状态。将输出与该状态关联的描述。

save description

保存堆栈上工具的当前状态。指定的描述将附着于这种状态。保存的状态构成 LIFO(Last-In-First-Out,后进先出)堆栈,所以保存的最后一种状态将最先恢复。

saves

列出通过 save 子命令在保存的堆栈上保存的状态的描述。描述从上到下显示,第一条描述是最近保存的尚未恢复的状态。最后一条描述是最早保存的尚未恢复的状态。

start cmd

启动 LockLint 会话。在使用其他任何 LockLint 子命令之前,必须启动 LockLint 会话。缺省情况下,start 子命令会建立 LockLint 上下文,并在此上下文中为用户启动子 shell,如通过 $SHELL 所指定。导出到子 shell 的唯一的 LockLint 上下文是 LL_CONTEXT 环境变量。LL_CONTEXT 包含用于维护 LockLint 会话的临时文件目录的路径。

sym 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,到达代码中的这一点时,其他任何线程都不得与运行此代码的线程竞争。分析期间会报告违规行为(根据某些附注样式的断言提供的信息)。

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));

前两个注释告知 LockLint,只要访问指定的数据就应该保持锁。

第三个注释 SCHEME_PROTECTS_DATA 描述如何保护未受互斥锁或读取器/写入器锁保护的数据。为方案提供的描述只是文本。

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,函数对指定的锁有指定的副作用-即,函数在退出时会故意将锁置于不同于函数输入时的状态。对于这些注释中的最后两个,副作用不是关于锁,而是关于并发性的状态。

NOTE(COMPETING_THREADS_NOW);
NOTE(NO_COMPETING_THREADS_NOW);

第一个注释告知 LockLint,在代码中这一点后面,存在的其他线程可能尝试访问与此线程将访问的数据相同的数据。第二个函数指定不再是这种情况,要么是没有其他线程正在运行,要么是正在运行的任何线程都不会访问此线程将访问的数据。

NOTE(NOT_REACHED);

告知 LockLint,无法到达代码中的特定点,因此 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,此函数假定由指定表达式表示的变量受保护-即,为每个变量保持相应的锁;或者这些变量对其他线程不可见;或者进行调用时没有竞争性线程。

Environment Variables

LL_CONTEXT

包含上下文目录的路径

SHELL

用作缺省 shell

TMPDIR

用作缺省临时目录路径

See also

有关完整的 Oracle Solaris Studio 文档,请访问 http://www.oracle.com/technetwork/server-storage/solarisstudio/documentation

忠告

忠告

目前,LockLint 不会就源文件检查 .ll 是否已过期。

Files

file.ll

来自 cc 的 LockLint 数据库文件

lock_lint

lock_lint 命令

lock_lint_server

LockLint 引擎

help

帮助文件的目录

cmd.ll_help

关于 cmd 的帮助主题

Errors

lock_lint 命令的退出状态如下所示:

0

正常

1

系统错误

2

用户导致的错误,例如错误选项或未定义的名称

3

多种类型的错误

5

Lock_lint 检测到错误:可能发现断言潜在数据争用或死锁违规行为、数据引用未受保护等等。

10

许可错误