The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sys/lock.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: lock.h,v 1.52.2.1 2004/07/02 18:18:27 he Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center.
   10  *
   11  * This code is derived from software contributed to The NetBSD Foundation
   12  * by Ross Harvey.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. All advertising materials mentioning features or use of this software
   23  *    must display the following acknowledgement:
   24  *      This product includes software developed by the NetBSD
   25  *      Foundation, Inc. and its contributors.
   26  * 4. Neither the name of The NetBSD Foundation nor the names of its
   27  *    contributors may be used to endorse or promote products derived
   28  *    from this software without specific prior written permission.
   29  *
   30  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   31  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   32  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   33  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   34  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   35  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   36  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   37  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   38  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   39  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   40  * POSSIBILITY OF SUCH DAMAGE.
   41  */
   42 
   43 /* 
   44  * Copyright (c) 1995
   45  *      The Regents of the University of California.  All rights reserved.
   46  *
   47  * This code contains ideas from software contributed to Berkeley by
   48  * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
   49  * System project at Carnegie-Mellon University.
   50  *
   51  * Redistribution and use in source and binary forms, with or without
   52  * modification, are permitted provided that the following conditions
   53  * are met:
   54  * 1. Redistributions of source code must retain the above copyright
   55  *    notice, this list of conditions and the following disclaimer.
   56  * 2. Redistributions in binary form must reproduce the above copyright
   57  *    notice, this list of conditions and the following disclaimer in the
   58  *    documentation and/or other materials provided with the distribution.
   59  * 3. Neither the name of the University nor the names of its contributors
   60  *    may be used to endorse or promote products derived from this software
   61  *    without specific prior written permission.
   62  *
   63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   73  * SUCH DAMAGE.
   74  *
   75  *      @(#)lock.h      8.12 (Berkeley) 5/19/95
   76  */
   77 
   78 #ifndef _SYS_LOCK_H_
   79 #define _SYS_LOCK_H_
   80 
   81 #if defined(_KERNEL_OPT)
   82 #include "opt_lockdebug.h"
   83 #include "opt_multiprocessor.h"
   84 #endif
   85 
   86 #include <sys/queue.h>
   87 #include <machine/lock.h>
   88 
   89 /*
   90  * The simple lock.  Provides a simple spinning mutex.  Note the
   91  * member which is used in atomic operations must be aligned in
   92  * order for it to work on the widest range of processor types.
   93  */
   94 struct simplelock {
   95         __cpu_simple_lock_t lock_data;
   96 #ifdef LOCKDEBUG
   97         const char *lock_file;
   98         const char *unlock_file;
   99         short lock_line;
  100         short unlock_line;
  101         TAILQ_ENTRY(simplelock) list;
  102         cpuid_t lock_holder;            /* CPU ID */
  103 #endif
  104 };
  105 
  106 #ifdef LOCKDEBUG
  107 #define SIMPLELOCK_INITIALIZER  { __SIMPLELOCK_UNLOCKED, NULL, NULL, 0, \
  108                                   0, { NULL, NULL }, LK_NOCPU }
  109 #else
  110 #define SIMPLELOCK_INITIALIZER  { __SIMPLELOCK_UNLOCKED }
  111 #endif
  112 
  113 /*
  114  * The general lock structure.  Provides for multiple shared locks,
  115  * upgrading from shared to exclusive, and sleeping/spinning until the
  116  * lock can be gained.
  117  */
  118 struct lock {
  119         struct  simplelock lk_interlock; /* lock on remaining fields */
  120         u_int   lk_flags;               /* see below */
  121         int     lk_sharecount;          /* # of accepted shared locks */
  122         short   lk_exclusivecount;      /* # of recursive exclusive locks */
  123         short   lk_recurselevel;        /* lvl above which recursion ok */
  124         int     lk_waitcount;           /* # of sleepers/spinners */
  125 
  126         /*
  127          * This is the sleep message for sleep locks, and a simple name
  128          * for spin locks.
  129          */
  130         const char *lk_wmesg;
  131 
  132         union {
  133                 struct {
  134                         /* pid of exclusive lock holder */
  135                         pid_t lk_sleep_lockholder;
  136                         lwpid_t lk_sleep_locklwp;
  137 
  138                         /* priority at which to sleep */
  139                         int lk_sleep_prio;
  140 
  141                         /* maximum sleep time (for tsleep) */
  142                         int lk_sleep_timo;
  143                 } lk_un_sleep;
  144                 struct {
  145                         /* CPU ID of exclusive lock holder */
  146                         cpuid_t lk_spin_cpu;
  147 #if defined(LOCKDEBUG)
  148                         TAILQ_ENTRY(lock) lk_spin_list;
  149 #endif
  150                 } lk_un_spin;
  151         } lk_un;
  152 
  153 #define lk_lockholder   lk_un.lk_un_sleep.lk_sleep_lockholder
  154 #define lk_locklwp      lk_un.lk_un_sleep.lk_sleep_locklwp
  155 #define lk_prio         lk_un.lk_un_sleep.lk_sleep_prio
  156 #define lk_timo         lk_un.lk_un_sleep.lk_sleep_timo
  157 
  158 #define lk_cpu          lk_un.lk_un_spin.lk_spin_cpu
  159 #if defined(LOCKDEBUG)
  160 #define lk_list         lk_un.lk_un_spin.lk_spin_list
  161 #endif
  162 
  163 #if defined(LOCKDEBUG)
  164         const char *lk_lock_file;
  165         const char *lk_unlock_file;
  166         int lk_lock_line;
  167         int lk_unlock_line;
  168 #endif
  169 };
  170 
  171 #define LOCK_INITIALIZER(prio, wmesg, timo, flags)                      \
  172         { SIMPLELOCK_INITIALIZER,                                       \
  173           (flags),                                                      \
  174           0,                                                            \
  175           0,                                                            \
  176           0,                                                            \
  177           0,                                                            \
  178           (wmesg),                                                      \
  179           { .lk_un_sleep = { 0, 0, (prio), (timo) } }                   \
  180         }
  181 
  182 /*
  183  * Lock request types:
  184  *   LK_SHARED - get one of many possible shared locks. If a process
  185  *      holding an exclusive lock requests a shared lock, the exclusive
  186  *      lock(s) will be downgraded to shared locks.
  187  *   LK_EXCLUSIVE - stop further shared locks, when they are cleared,
  188  *      grant a pending upgrade if it exists, then grant an exclusive
  189  *      lock. Only one exclusive lock may exist at a time, except that
  190  *      a process holding an exclusive lock may get additional exclusive
  191  *      locks if it explicitly sets the LK_CANRECURSE flag in the lock
  192  *      request, or if the LK_CANRECUSE flag was set when the lock was
  193  *      initialized.
  194  *   LK_UPGRADE - the process must hold a shared lock that it wants to
  195  *      have upgraded to an exclusive lock. Other processes may get
  196  *      exclusive access to the resource between the time that the upgrade
  197  *      is requested and the time that it is granted.
  198  *   LK_EXCLUPGRADE - the process must hold a shared lock that it wants to
  199  *      have upgraded to an exclusive lock. If the request succeeds, no
  200  *      other processes will have gotten exclusive access to the resource
  201  *      between the time that the upgrade is requested and the time that
  202  *      it is granted. However, if another process has already requested
  203  *      an upgrade, the request will fail (see error returns below).
  204  *   LK_DOWNGRADE - the process must hold an exclusive lock that it wants
  205  *      to have downgraded to a shared lock. If the process holds multiple
  206  *      (recursive) exclusive locks, they will all be downgraded to shared
  207  *      locks.
  208  *   LK_RELEASE - release one instance of a lock.
  209  *   LK_DRAIN - wait for all activity on the lock to end, then mark it
  210  *      decommissioned. This feature is used before freeing a lock that
  211  *      is part of a piece of memory that is about to be freed.
  212  *
  213  * These are flags that are passed to the lockmgr routine.
  214  */
  215 #define LK_TYPE_MASK    0x0000000f      /* type of lock sought */
  216 #define LK_SHARED       0x00000001      /* shared lock */
  217 #define LK_EXCLUSIVE    0x00000002      /* exclusive lock */
  218 #define LK_UPGRADE      0x00000003      /* shared-to-exclusive upgrade */
  219 #define LK_EXCLUPGRADE  0x00000004      /* first shared-to-exclusive upgrade */
  220 #define LK_DOWNGRADE    0x00000005      /* exclusive-to-shared downgrade */
  221 #define LK_RELEASE      0x00000006      /* release any type of lock */
  222 #define LK_DRAIN        0x00000007      /* wait for all lock activity to end */
  223 /*
  224  * External lock flags.
  225  *
  226  * The first three flags may be set in lock_init to set their mode permanently,
  227  * or passed in as arguments to the lock manager. The LK_REENABLE flag may be
  228  * set only at the release of a lock obtained by drain.
  229  */
  230 #define LK_EXTFLG_MASK  0x00700070      /* mask of external flags */
  231 #define LK_NOWAIT       0x00000010      /* do not sleep to await lock */
  232 #define LK_SLEEPFAIL    0x00000020      /* sleep, then return failure */
  233 #define LK_CANRECURSE   0x00000040      /* this may be recursive lock attempt */
  234 #define LK_REENABLE     0x00000080      /* lock is be reenabled after drain */
  235 #define LK_SETRECURSE   0x00100000      /* other locks while we have it OK */
  236 #define LK_RECURSEFAIL  0x00200000      /* attempt at recursive lock fails */
  237 #define LK_SPIN         0x00400000      /* lock spins instead of sleeps */
  238 /*
  239  * Internal lock flags.
  240  *
  241  * These flags are used internally to the lock manager.
  242  */
  243 #define LK_WANT_UPGRADE 0x00000100      /* waiting for share-to-excl upgrade */
  244 #define LK_WANT_EXCL    0x00000200      /* exclusive lock sought */
  245 #define LK_HAVE_EXCL    0x00000400      /* exclusive lock obtained */
  246 #define LK_WAITDRAIN    0x00000800      /* process waiting for lock to drain */
  247 #define LK_DRAINING     0x00004000      /* lock is being drained */
  248 #define LK_DRAINED      0x00008000      /* lock has been decommissioned */
  249 /*
  250  * Internal state flags corresponding to lk_sharecount, and lk_waitcount
  251  */
  252 #define LK_SHARE_NONZERO 0x00040000     /* lk_sharecount != 0 */
  253 #define LK_WAIT_NONZERO 0x00080000      /* lk_waitcount != 0 */
  254 /*
  255  * Control flags
  256  *
  257  * Non-persistent external flags.
  258  */
  259 #define LK_INTERLOCK    0x00010000      /* unlock passed simple lock after
  260                                            getting lk_interlock */
  261 #define LK_RETRY        0x00020000      /* vn_lock: retry until locked */
  262 
  263 /*
  264  * Lock return status.
  265  *
  266  * Successfully obtained locks return 0. Locks will always succeed
  267  * unless one of the following is true:
  268  *      LK_FORCEUPGRADE is requested and some other process has already
  269  *          requested a lock upgrade (returns EBUSY).
  270  *      LK_WAIT is set and a sleep would be required (returns EBUSY).
  271  *      LK_SLEEPFAIL is set and a sleep was done (returns ENOLCK).
  272  *      PCATCH is set in lock priority and a signal arrives (returns
  273  *          either EINTR or ERESTART if system calls is to be restarted).
  274  *      Non-null lock timeout and timeout expires (returns EWOULDBLOCK).
  275  * A failed lock attempt always returns a non-zero error value. No lock
  276  * is held after an error return (in particular, a failed LK_UPGRADE
  277  * or LK_FORCEUPGRADE will have released its shared access lock).
  278  */
  279 
  280 /*
  281  * Indicator that no process/cpu holds exclusive lock
  282  */
  283 #define LK_KERNPROC     ((pid_t) -2)
  284 #define LK_NOPROC       ((pid_t) -1)
  285 #define LK_NOCPU        ((cpuid_t) -1)
  286 
  287 #ifdef _KERNEL
  288 
  289 struct proc;
  290 
  291 void    lockinit(struct lock *, int, const char *, int, int);
  292 #if defined(LOCKDEBUG)
  293 int     _lockmgr(__volatile struct lock *, u_int, struct simplelock *,
  294             const char *, int);
  295 #define lockmgr(l, f, i)        _lockmgr((l), (f), (i), __FILE__, __LINE__)
  296 #else
  297 int     lockmgr(__volatile struct lock *, u_int flags, struct simplelock *);
  298 #endif /* LOCKDEBUG */
  299 int     lockstatus(struct lock *);
  300 void    lockmgr_printinfo(__volatile struct lock *);
  301 
  302 #if defined(LOCKDEBUG) || defined(DIAGNOSTIC)
  303 void    spinlock_switchcheck(void);
  304 #endif
  305 
  306 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
  307 #define spinlockinit(lkp, name, flags)                                  \
  308         lockinit((lkp), 0, (name), 0, (flags) | LK_SPIN)
  309 #define spinlockmgr(lkp, flags, intrlk)                                 \
  310         lockmgr((lkp), (flags) | LK_SPIN, (intrlk))
  311 #else
  312 #define spinlockinit(lkp, name, flags)          (void)(lkp)
  313 #define spinlockmgr(lkp, flags, intrlk)         (0)
  314 #endif
  315 
  316 #if defined(LOCKDEBUG)
  317 int     _spinlock_release_all(__volatile struct lock *, const char *, int);
  318 void    _spinlock_acquire_count(__volatile struct lock *, int, const char *,
  319             int);
  320 
  321 #define spinlock_release_all(l) _spinlock_release_all((l), __FILE__, __LINE__)
  322 #define spinlock_acquire_count(l, c) _spinlock_acquire_count((l), (c),  \
  323                                         __FILE__, __LINE__)
  324 #else
  325 int     spinlock_release_all(__volatile struct lock *);
  326 void    spinlock_acquire_count(__volatile struct lock *, int);
  327 #endif
  328 
  329 #if defined(LOCKDEBUG)
  330 void    _simple_lock(__volatile struct simplelock *, const char *, int);
  331 int     _simple_lock_try(__volatile struct simplelock *, const char *, int);
  332 void    _simple_unlock(__volatile struct simplelock *, const char *, int);
  333 int     _simple_lock_held(__volatile struct simplelock *);
  334 void    simple_lock_only_held(__volatile struct simplelock *, const char *);
  335 
  336 #define simple_lock(alp)        _simple_lock((alp), __FILE__, __LINE__)
  337 #define simple_lock_try(alp)    _simple_lock_try((alp), __FILE__, __LINE__)
  338 #define simple_unlock(alp)      _simple_unlock((alp), __FILE__, __LINE__)
  339 #define simple_lock_held(alp)   _simple_lock_held((alp))
  340 
  341 #define LOCK_ASSERT(x)          KASSERT(x)
  342 
  343 void    simple_lock_init(struct simplelock *);
  344 void    simple_lock_dump(void);
  345 void    simple_lock_freecheck(void *, void *);
  346 void    simple_lock_switchcheck(void);
  347 #elif defined(MULTIPROCESSOR)
  348 #define simple_lock_init(alp)   __cpu_simple_lock_init(&(alp)->lock_data)
  349 #define simple_lock(alp)        __cpu_simple_lock(&(alp)->lock_data)
  350 #define simple_lock_try(alp)    __cpu_simple_lock_try(&(alp)->lock_data)
  351 #define simple_unlock(alp)      __cpu_simple_unlock(&(alp)->lock_data)
  352 #define LOCK_ASSERT(x)          /* nothing */
  353 #define simple_lock_only_held(x,y)              /* nothing */
  354 #else
  355 #define simple_lock_try(alp)    (1)
  356 #ifndef __lint__
  357 #define simple_lock_init(alp)   (void)(alp)
  358 #define simple_lock(alp)        (void)(alp)
  359 #define simple_unlock(alp)      (void)(alp)
  360 #else /* __lint__ */
  361 #define simple_lock_init(alp)   /* nothing */
  362 #define simple_lock(alp)        /* nothing */
  363 #define simple_unlock(alp)      /* nothing */
  364 #define simple_lock_only_held(x,y)              /* nothing */
  365 #endif /* __lint__ */
  366 #define LOCK_ASSERT(x)          /* nothing */
  367 #endif
  368 
  369 #if defined(MULTIPROCESSOR)
  370 extern struct lock kernel_lock;
  371 #endif
  372 
  373 #endif /* _KERNEL */
  374 
  375 #endif /* _SYS_LOCK_H_ */

Cache object: fc194d9f928785a33f498b0b25159854


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.