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 SunSoft ANSI
     C compiler.  The SunSoft ANSI C compiler will  then  produce
     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

     Sun WorkShop: Command Line Utilities

     Read the file /opt/SUNWspro/README for last  minute  release
     notes    or    product    notes.     (The   file   will   be
     $(INSTALL)/SUNWspro/README if SPARCCompilers  are  installed
     someplace other than /opt.)


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