1 /* 2 * Copyright (c) 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code contains ideas from software contributed to Berkeley by 6 * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating 7 * System project at Carnegie-Mellon University. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)lock.h 8.12 (Berkeley) 05/19/95 12 */ 13 14 #ifndef _LOCK_H_ 15 #define _LOCK_H_ 16 17 /* 18 * The general lock structure. Provides for multiple shared locks, 19 * upgrading from shared to exclusive, and sleeping until the lock 20 * can be gained. The simple locks are defined in <machine/param.h>. 21 */ 22 struct lock { 23 struct simplelock lk_interlock; /* lock on remaining fields */ 24 u_int lk_flags; /* see below */ 25 int lk_sharecount; /* # of accepted shared locks */ 26 int lk_waitcount; /* # of processes sleeping for lock */ 27 short lk_exclusivecount; /* # of recursive exclusive locks */ 28 short lk_prio; /* priority at which to sleep */ 29 char *lk_wmesg; /* resource sleeping (for tsleep) */ 30 int lk_timo; /* maximum sleep time (for tsleep) */ 31 pid_t lk_lockholder; /* pid of exclusive lock holder */ 32 }; 33 /* 34 * Lock request types: 35 * LK_SHARED - get one of many possible shared locks. If a process 36 * holding an exclusive lock requests a shared lock, the exclusive 37 * lock(s) will be downgraded to shared locks. 38 * LK_EXCLUSIVE - stop further shared locks, when they are cleared, 39 * grant a pending upgrade if it exists, then grant an exclusive 40 * lock. Only one exclusive lock may exist at a time, except that 41 * a process holding an exclusive lock may get additional exclusive 42 * locks if it explicitly sets the LK_CANRECURSE flag in the lock 43 * request, or if the LK_CANRECUSE flag was set when the lock was 44 * initialized. 45 * LK_UPGRADE - the process must hold a shared lock that it wants to 46 * have upgraded to an exclusive lock. Other processes may get 47 * exclusive access to the resource between the time that the upgrade 48 * is requested and the time that it is granted. 49 * LK_EXCLUPGRADE - the process must hold a shared lock that it wants to 50 * have upgraded to an exclusive lock. If the request succeeds, no 51 * other processes will have gotten exclusive access to the resource 52 * between the time that the upgrade is requested and the time that 53 * it is granted. However, if another process has already requested 54 * an upgrade, the request will fail (see error returns below). 55 * LK_DOWNGRADE - the process must hold an exclusive lock that it wants 56 * to have downgraded to a shared lock. If the process holds multiple 57 * (recursive) exclusive locks, they will all be downgraded to shared 58 * locks. 59 * LK_RELEASE - release one instance of a lock. 60 * LK_DRAIN - wait for all activity on the lock to end, then mark it 61 * decommissioned. This feature is used before freeing a lock that 62 * is part of a piece of memory that is about to be freed. 63 * 64 * These are flags that are passed to the lockmgr routine. 65 */ 66 #define LK_TYPE_MASK 0x0000000f /* type of lock sought */ 67 #define LK_SHARED 0x00000001 /* shared lock */ 68 #define LK_EXCLUSIVE 0x00000002 /* exclusive lock */ 69 #define LK_UPGRADE 0x00000003 /* shared-to-exclusive upgrade */ 70 #define LK_EXCLUPGRADE 0x00000004 /* first shared-to-exclusive upgrade */ 71 #define LK_DOWNGRADE 0x00000005 /* exclusive-to-shared downgrade */ 72 #define LK_RELEASE 0x00000006 /* release any type of lock */ 73 #define LK_DRAIN 0x00000007 /* wait for all lock activity to end */ 74 /* 75 * External lock flags. 76 * 77 * The first three flags may be set in lock_init to set their mode permanently, 78 * or passed in as arguments to the lock manager. The LK_REENABLE flag may be 79 * set only at the release of a lock obtained by drain. 80 */ 81 #define LK_EXTFLG_MASK 0x00000070 /* mask of external flags */ 82 #define LK_NOWAIT 0x00000010 /* do not sleep to await lock */ 83 #define LK_SLEEPFAIL 0x00000020 /* sleep, then return failure */ 84 #define LK_CANRECURSE 0x00000040 /* allow recursive exclusive lock */ 85 #define LK_REENABLE 0x00000080 /* lock is be reenabled after drain */ 86 /* 87 * Internal lock flags. 88 * 89 * These flags are used internally to the lock manager. 90 */ 91 #define LK_WANT_UPGRADE 0x00000100 /* waiting for share-to-excl upgrade */ 92 #define LK_WANT_EXCL 0x00000200 /* exclusive lock sought */ 93 #define LK_HAVE_EXCL 0x00000400 /* exclusive lock obtained */ 94 #define LK_WAITDRAIN 0x00000800 /* process waiting for lock to drain */ 95 #define LK_DRAINING 0x00004000 /* lock is being drained */ 96 #define LK_DRAINED 0x00008000 /* lock has been decommissioned */ 97 /* 98 * Control flags 99 * 100 * Non-persistent external flags. 101 */ 102 #define LK_INTERLOCK 0x00010000 /* unlock passed simple lock after 103 getting lk_interlock */ 104 #define LK_RETRY 0x00020000 /* vn_lock: retry until locked */ 105 106 /* 107 * Lock return status. 108 * 109 * Successfully obtained locks return 0. Locks will always succeed 110 * unless one of the following is true: 111 * LK_FORCEUPGRADE is requested and some other process has already 112 * requested a lock upgrade (returns EBUSY). 113 * LK_WAIT is set and a sleep would be required (returns EBUSY). 114 * LK_SLEEPFAIL is set and a sleep was done (returns ENOLCK). 115 * PCATCH is set in lock priority and a signal arrives (returns 116 * either EINTR or ERESTART if system calls is to be restarted). 117 * Non-null lock timeout and timeout expires (returns EWOULDBLOCK). 118 * A failed lock attempt always returns a non-zero error value. No lock 119 * is held after an error return (in particular, a failed LK_UPGRADE 120 * or LK_FORCEUPGRADE will have released its shared access lock). 121 */ 122 123 /* 124 * Indicator that no process holds exclusive lock 125 */ 126 #define LK_KERNPROC ((pid_t) -2) 127 #define LK_NOPROC ((pid_t) -1) 128 129 struct proc; 130 131 void lockinit __P((struct lock *, int prio, char *wmesg, int timo, 132 int flags)); 133 int lockmgr __P((__volatile struct lock *, u_int flags, 134 struct simplelock *, struct proc *p)); 135 int lockstatus __P((struct lock *)); 136 137 #ifdef DEBUG 138 void _simple_unlock __P((__volatile struct simplelock *alp, const char *, int)); 139 #define simple_unlock(alp) _simple_unlock(alp, __FILE__, __LINE__) 140 int _simple_lock_try __P((__volatile struct simplelock *alp, const char *, int)); 141 #define simple_lock_try(alp) _simple_lock_try(alp, __FILE__, __LINE__) 142 void _simple_lock __P((__volatile struct simplelock *alp, const char *, int)); 143 #define simple_lock(alp) _simple_lock(alp, __FILE__, __LINE__) 144 void simple_lock_init __P((struct simplelock *alp)); 145 #else /* !DEBUG */ 146 #if NCPUS == 1 /* no multiprocessor locking is necessary */ 147 #define simple_lock_init(alp) 148 #define simple_lock(alp) 149 #define simple_lock_try(alp) (1) /* always succeeds */ 150 #define simple_unlock(alp) 151 #endif /* NCPUS == 1 */ 152 #endif /* !DEBUG */ 153 154 #endif /* !_LOCK_H_ */ 155