NAME
lock_lint - verify use of locks in multi-threaded programs
SYNOPSIS
lock_lint subcommand
DESCRIPTION
LockLint is a tool that statically analyzes ANSI C source
code to aid in the detection of data races and deadlocks
caused by inconsistent usages of mutex and readers-writer
locks. LockLint supports the ANSI C programmer using
Solaris's libthread API.
There are two interfaces for LockLint:
subcommands
These are entered from a command line (or from a
script) and take the form:
lock_lint subcommand
source code annotations
These are entered directly into your source code.
Although there are fewer source code annotations than
subcommands, they are often preferable to subcommands.
To start a LockLint session, type:
lock_lint start
This starts a user-specifiable subshell with an appropriate
LockLint context established. (See the start subcommand,
below, for more information.)
For LockLint to analyze your source code, the code must
first be compiled using the -Zll option of the C compiler.
The C compiler then produces the LockLint database files
(.ll files), one for each .c file compiled. The .ll files
will later be loaded into LockLint via the load subcommand.
SUBCOMMANDS
For quick information on any LockLint subcommand while
you're in a LockLint session, use the LockLint help subcom-
mand (see below).
For efficiency and ease, you can alias subcommands (if your
shell allows it); you can also put subcommands into a script
file and run that script.
analyze [-hv]
Analyze the loaded files for lock inconsistencies which
may lead to data races and deadlocks. This subcommand
may produce a great deal of output, so you may want to
redirect the output to a file. This directive can only
be run once for each saved state (see save).
Once the analysis is done, you can find still more
potential problems in the output of the "vars" and
"order" subcommands. For example, the command
lock_lint vars -h | fgrep *
will show variables which are not properly protected by
any lock.
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 ...
Provide LockLint with assertions about how locks are
being used. During analysis LockLint reports on any
violations of these assertions.
declare mutex mutex ...
declare rwlocks rwlock ...
declare func_ptr targets func ...
declare nonreturning func ...
declare one tag ...
declare readable var ...
declare root func ...
Declare various attributes about locks, functions and
variables in the program.
disallows
List the calling sequences which are disallowed, as
specified using the disallow subcommand.
exit To exit LockLint, use the exit command of the shell you
are using. When the subshell started by the lock_lint
start command exits, LockLint exits.
files
List the source code files as represented by the .ll
files loaded via the load subcommand.
funcptrs [-botu] func_ptr ...
funcptrs [-blotuz]
funcptrs [-botu] func_ptr ...
funcptrs [-blotuz]
List information about the function pointers used in
the loaded files.
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 ...
List information about the functions defined and/or
called in the loaded files.
help [subcommand]
The help subcommand with no topic specified gives a
list of subcommands with their options and some general
help information. Detailed help on a subcommand can be
specified via the syntax:
lock_lint help first word of subcommand
Help is also available on the following keywords:
condvars inversions names
example limitations overview
exit locking shell
ifdef makefile
shell
ignore func|var ... [in func ... ]
Tell LockLint to exclude certain functions and vari-
ables from the analysis. This exclusion may be limited
to specific functions using the "in func ..." clause;
otherwise the exclusion applies to all functions.
load file ...
Load the specified .ll files. The extension may be
omitted, but if an extension is specified, it must be
.ll. Absolute and relative paths are allowed. The
following are legal (depending upon your shell's capa-
bilities):
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 ...
List information about the locks of the loaded files.
Note that only those variables which are actually used
in lock manipulation routines are shown; locks which
are simply declared but never manipulated will not be
shown.
members struct_tag
List the members of the struct with the specified tag,
one per line. For structures which were not assigned a
tag, the notation "file@line is used (e.g. "x.c@29"),
where the file and line number are the source location
of the struct's declaration.
order [lock [lock]].
List information about the order in which locks are
acquired by the code being analyzed. It may only be
run after analysis is complete.
pointer calls
List calls made through function pointers in the loaded
files.
reallow func ...
Allow exceptions to disallow subcommands.
reallows
List the calling sequences which are reallowed, as
specified using the reallow subcommand.
refresh
Pop the saved state stack restoring LockLint to the
state of the top of the saved state stack. The
description associated with that state is printed.
Then save the state again with the same description (so
that it may be restored/refreshed again).
restore
Pop the saved state stack restoring LockLint to the
state of the top of the saved state stack. The
description associated with that state is printed.
save description
Save the current state of the tool on a stack. The
specified description is attached to the state. Saved
states form a LIFO (Last-In-First-Out) stack, so that
the last state saved is the first one restored.
saves
List the descriptions of the states saved on the saved
stack via the save subcommand. The descriptions are
shown from top to bottom with the first description
being the most recently saved state that has not been
restored. And the last description being the oldest
state saved that has not been restored.
start cmd
Start a LockLint session. A LockLint session must be
started prior to using any other LockLint subcommand.
By default the start subcommand establishes LockLint
context and starts a subshell for the user - as speci-
fied via $SHELL - within that context. The only piece
of the LockLint context exported to the subshell is the
LL_CONTEXT environment variable. LL_CONTEXT contains
the path to the temporary directory of files used to
maintain a LockLint session.
sym name ...
List the various things the specified names could refer
to within the loaded files. For example, "foo" might
refer both to variable "x.c:func1/foo" and to function
y.c:foo, depending on context.
unassert vars var ...
Undo any assertion about locks protecting the specified
variables. Note that there is no way to remove an
assertion about a lock protecting a function.
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 ...
List information about the variables of the loaded
files. Note that only those variables which are actu-
ally *used* are shown; variables which are simply
declared in the program but never accessed will not be
shown.
SOURCE CODE ANNOTATIONS
ASSERT(NO_LOCKS_HELD);
assert(NO_LOCKS_HELD);
Tell LockLint that when this point in the code is
reached, no locks should be held by the thread execut-
ing this test. Violations will be reported during
analysis.
ASSERT(NO_COMPETING_THREADS);
assert(NO_COMPETING_THREADS);
Tell LockLint that when this point in the code is
reached, no other threads should be competing with the
one running this code. Violations (based on info pro-
vided by certain NOTE-style assertions) are reported
during analysis.
ASSERT(MUTEX_HELD(lock_expr) && ...);
assert(MUTEX_HELD(lock_expr) && ...);
Cause an error to be reported if the executing thread
does not hold the lock as described.
NOTE(MUTEX_PROTECTS_DATA(Mutex, DataNameList));
NOTE(RWLOCK_PROTECTS_DATA(Rwlock, DataNameList));
NOTE(SCHEME_PROTECTS_DATA(description, DataNameList));
The first two annotations tell LockLint that the lock
should be held whenever the specified data are
accessed.
The third annotation, SCHEME_PROTECTS_DATA, describes
how data which are not protected by a mutex or
readers/writer lock are protected. The description
supplied for the scheme is simply text.
NOTE(READ_ONLY_DATA(DataNameList));
Tell LockLint that the data should only be read, and
not written.
NOTE(DATA_READABLE_WITHOUT_LOCK(DataNameList));
Tell LockLint that the specified data may be read
without protecting locks being held on them.
NOTE(RWLOCK_COVERS_LOCKS(RwlockName, LockNameList));
Tell LockLint that a hierarchical relationship exists
between a readers/writer lock and a set of other locks.
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);
Tell LockLint that the function has the specified side
effect on the specified lock - that is, that the func-
tion deliberately leaves the lock in a different state
on exit than it was in when the function was entered.
In the case of the last two of these annotations, the
side effect is not about a lock but rather about the
state of concurrency.
NOTE(COMPETING_THREADS_NOW);
NOTE(NO_COMPETING_THREADS_NOW);
The first annotation tells LockLint that after this
point in the code, other threads exist which might try
to access the same data that this thread will access.
The second function specifies that this is no longer
the case, that either no other threads are running, or
whatever threads are running will not be accessing data
that this thread will access.
NOTE(NOT_REACHED);
Tell LockLint that a particular point in the code can-
not be reached, and therefore LockLint should ignore
the condition of locks held at that point. Lock Order
NOTE(LOCK_ORDER(LockNameList));
Specify the order in which locks should be acquired.
NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(DataExpr, ...));
NOTE(NOW_VISIBLE_TO_OTHER_THREADS(DataExpr, ...));
Tell LockLint whether or not the variables represented
by the specified expressions are visible to other
threads - that is, whether or not other threads could
access the variables.
NOTE(ASSUMING_PROTECTED(DataExpr, ...));
Tell LockLint that this function assumes that the vari-
ables represented by the specified expressions are pro-
tected - that is, either the appropriate lock is held
for each variable; or the variables are invisible to
other threads; or there are no competing threads when
the call is made.
ENVIRONMENT
LL_CONTEXT contains path to context directory
SHELL used as default shell
TMPDIR used as default tmp directory path
SEE ALSO
For information on product man pages, HTML versions of
readmes and manuals, see /opt/SUNWspro/docs/index.html. If
your compiler collection software has not been installed in
the default /opt directory, ask your system admininstrator
for the equivalent path on your system.
CAVEATS
Currently, LockLint does not check to see if a .ll is out of
date with respect to its source file.
FILES
file.ll LockLint database file from cc
lock_lint lock_lint command
lock_lint_server LockLint engine
help directory of help files
cmd.ll_help help topic on cmd
ERRORS
Exit status from a lock_lint command is as follows:
0 Normal
1 System error
2 User caused error, like incorrect options or undefined name
3 Multiple types of errors
5 Lock_lint detected error: violation of an assertion,
potential data race or deadlock may have been found,
unprotected data references, etc.
10 Licensing error