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.11 (Berkeley) 05/17/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 * These flags may be set in lock_init to set their mode permanently, 78 * or passed in as arguments to the lock manager. 79 */ 80 #define LK_EXTFLG_MASK 0x000000f0 /* mask of external flags */ 81 #define LK_NOWAIT 0x00000010 /* do not sleep to await lock */ 82 #define LK_SLEEPFAIL 0x00000020 /* sleep, then return failure */ 83 #define LK_CANRECURSE 0x00000040 /* allow recursive exclusive lock */ 84 /* 85 * Internal lock flags. 86 * 87 * These flags are used internally to the lock manager. 88 */ 89 #define LK_WANT_UPGRADE 0x00000100 /* waiting for share-to-excl upgrade */ 90 #define LK_WANT_EXCL 0x00000200 /* exclusive lock sought */ 91 #define LK_HAVE_EXCL 0x00000400 /* exclusive lock obtained */ 92 #define LK_WAITDRAIN 0x00000800 /* process waiting for lock to drain */ 93 #define LK_DRAINING 0x00004000 /* lock is being drained */ 94 #define LK_DRAINED 0x00008000 /* lock has been decommissioned */ 95 /* 96 * Control flags 97 * 98 * Non-persistent external flags. 99 */ 100 #define LK_INTERLOCK 0x00010000 /* unlock passed simple lock after 101 getting lk_interlock */ 102 #define LK_RETRY 0x00020000 /* vn_lock: retry until locked */ 103 104 /* 105 * Lock return status. 106 * 107 * Successfully obtained locks return 0. Locks will always succeed 108 * unless one of the following is true: 109 * LK_FORCEUPGRADE is requested and some other process has already 110 * requested a lock upgrade (returns EBUSY). 111 * LK_WAIT is set and a sleep would be required (returns EBUSY). 112 * LK_SLEEPFAIL is set and a sleep was done (returns ENOLCK). 113 * PCATCH is set in lock priority and a signal arrives (returns 114 * either EINTR or ERESTART if system calls is to be restarted). 115 * Non-null lock timeout and timeout expires (returns EWOULDBLOCK). 116 * A failed lock attempt always returns a non-zero error value. No lock 117 * is held after an error return (in particular, a failed LK_UPGRADE 118 * or LK_FORCEUPGRADE will have released its shared access lock). 119 */ 120 121 /* 122 * Indicator that no process holds exclusive lock 123 */ 124 #define LK_KERNPROC ((pid_t) -2) 125 #define LK_NOPROC ((pid_t) -1) 126 127 struct proc; 128 129 void lockinit __P((struct lock *, int prio, char *wmesg, int timo, 130 int flags)); 131 int lockmgr __P((__volatile struct lock *, u_int flags, 132 struct simplelock *, struct proc *p)); 133 int lockstatus __P((struct lock *)); 134 135 #ifdef DEBUG 136 void _simple_unlock __P((__volatile struct simplelock *alp, const char *, int)); 137 #define simple_unlock(alp) _simple_unlock(alp, __FILE__, __LINE__) 138 int _simple_lock_try __P((__volatile struct simplelock *alp, const char *, int)); 139 #define simple_lock_try(alp) _simple_lock_try(alp, __FILE__, __LINE__) 140 void _simple_lock __P((__volatile struct simplelock *alp, const char *, int)); 141 #define simple_lock(alp) _simple_lock(alp, __FILE__, __LINE__) 142 void simple_lock_init __P((struct simplelock *alp)); 143 #else /* !DEBUG */ 144 #if NCPUS == 1 /* no multiprocessor locking is necessary */ 145 #define simple_lock_init(alp) 146 #define simple_lock(alp) 147 #define simple_lock_try(alp) (1) /* always succeeds */ 148 #define simple_unlock(alp) 149 #endif /* NCPUS == 1 */ 150 #endif /* !DEBUG */ 151 152 #endif /* !_LOCK_H_ */ 153