Man Page lock_lint.1
























































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   complete   Sun    Studio    documentation,	 go    to
     http://developers.sun.com/sunstudio/documentation/



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