summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_lock.c')
-rw-r--r--sys/kern/kern_lock.c162
1 files changed, 85 insertions, 77 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index d119c57..ff1b252 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
* @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
- * $Id: kern_lock.c,v 1.10 1997/08/19 00:27:07 dyson Exp $
+ * $Id: kern_lock.c,v 1.11 1997/08/22 07:16:46 phk Exp $
*/
#include <sys/param.h>
@@ -70,7 +70,12 @@
#define LOCK_INLINE inline
#endif
+#define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \
+ LK_SHARE_NONZERO | LK_WAIT_NONZERO)
+
static int acquire(struct lock *lkp, int extflags, int wanted);
+static int apause(struct lock *lkp, int flags);
+static int acquiredrain(struct lock *lkp, int extflags) ;
static LOCK_INLINE void
sharelock(struct lock *lkp, int incr) {
@@ -94,6 +99,11 @@ shareunlock(struct lock *lkp, int decr) {
lkp->lk_flags &= ~LK_SHARE_NONZERO;
}
+/*
+ * This is the waitloop optimization, and note for this to work
+ * simple_lock and simple_unlock should be subroutines to avoid
+ * optimization troubles.
+ */
static int
apause(struct lock *lkp, int flags) {
int lock_wait;
@@ -115,7 +125,6 @@ apause(struct lock *lkp, int flags) {
return 1;
}
-
static int
acquire(struct lock *lkp, int extflags, int wanted) {
int error;
@@ -125,9 +134,11 @@ acquire(struct lock *lkp, int extflags, int wanted) {
return EBUSY;
}
- error = apause(lkp, wanted);
- if (error == 0)
- return 0;
+ if (((lkp->lk_flags | extflags) & LK_NOPAUSE) == 0) {
+ error = apause(lkp, wanted);
+ if (error == 0)
+ return 0;
+ }
while ((lkp->lk_flags & wanted) != 0) {
lkp->lk_flags |= LK_WAIT_NONZERO;
@@ -147,78 +158,6 @@ acquire(struct lock *lkp, int extflags, int wanted) {
return 0;
}
-#define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \
- LK_SHARE_NONZERO | LK_WAIT_NONZERO)
-
-static int
-acquiredrain(struct lock *lkp, int extflags) {
- int error;
- int lock_wait;
-
- if ((extflags & LK_NOWAIT) && (lkp->lk_flags & LK_ALL)) {
- return EBUSY;
- }
-
- error = apause(lkp, LK_ALL);
- if (error == 0)
- return 0;
-
- while (lkp->lk_flags & LK_ALL) {
- lkp->lk_flags |= LK_WAITDRAIN;
- simple_unlock(&lkp->lk_interlock);
- error = tsleep(&lkp->lk_flags, lkp->lk_prio,
- lkp->lk_wmesg, lkp->lk_timo);
- simple_lock(&lkp->lk_interlock);
- if (error)
- return error;
- if (extflags & LK_SLEEPFAIL) {
- return ENOLCK;
- }
- }
- return 0;
-}
-
-/*
- * Initialize a lock; required before use.
- */
-void
-lockinit(lkp, prio, wmesg, timo, flags)
- struct lock *lkp;
- int prio;
- char *wmesg;
- int timo;
- int flags;
-{
-
- simple_lock_init(&lkp->lk_interlock);
- lkp->lk_flags = (flags & LK_EXTFLG_MASK);
- lkp->lk_sharecount = 0;
- lkp->lk_waitcount = 0;
- lkp->lk_exclusivecount = 0;
- lkp->lk_prio = prio;
- lkp->lk_wmesg = wmesg;
- lkp->lk_timo = timo;
- lkp->lk_lockholder = LK_NOPROC;
-}
-
-/*
- * Determine the status of a lock.
- */
-int
-lockstatus(lkp)
- struct lock *lkp;
-{
- int lock_type = 0;
-
- simple_lock(&lkp->lk_interlock);
- if (lkp->lk_exclusivecount != 0)
- lock_type = LK_EXCLUSIVE;
- else if (lkp->lk_sharecount != 0)
- lock_type = LK_SHARED;
- simple_unlock(&lkp->lk_interlock);
- return (lock_type);
-}
-
/*
* Set, change, or release a lock.
*
@@ -441,6 +380,75 @@ lockmgr(lkp, flags, interlkp, p)
return (error);
}
+static int
+acquiredrain(struct lock *lkp, int extflags) {
+ int error;
+ int lock_wait;
+
+ if ((extflags & LK_NOWAIT) && (lkp->lk_flags & LK_ALL)) {
+ return EBUSY;
+ }
+
+ error = apause(lkp, LK_ALL);
+ if (error == 0)
+ return 0;
+
+ while (lkp->lk_flags & LK_ALL) {
+ lkp->lk_flags |= LK_WAITDRAIN;
+ simple_unlock(&lkp->lk_interlock);
+ error = tsleep(&lkp->lk_flags, lkp->lk_prio,
+ lkp->lk_wmesg, lkp->lk_timo);
+ simple_lock(&lkp->lk_interlock);
+ if (error)
+ return error;
+ if (extflags & LK_SLEEPFAIL) {
+ return ENOLCK;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Initialize a lock; required before use.
+ */
+void
+lockinit(lkp, prio, wmesg, timo, flags)
+ struct lock *lkp;
+ int prio;
+ char *wmesg;
+ int timo;
+ int flags;
+{
+
+ simple_lock_init(&lkp->lk_interlock);
+ lkp->lk_flags = (flags & LK_EXTFLG_MASK);
+ lkp->lk_sharecount = 0;
+ lkp->lk_waitcount = 0;
+ lkp->lk_exclusivecount = 0;
+ lkp->lk_prio = prio;
+ lkp->lk_wmesg = wmesg;
+ lkp->lk_timo = timo;
+ lkp->lk_lockholder = LK_NOPROC;
+}
+
+/*
+ * Determine the status of a lock.
+ */
+int
+lockstatus(lkp)
+ struct lock *lkp;
+{
+ int lock_type = 0;
+
+ simple_lock(&lkp->lk_interlock);
+ if (lkp->lk_exclusivecount != 0)
+ lock_type = LK_EXCLUSIVE;
+ else if (lkp->lk_sharecount != 0)
+ lock_type = LK_SHARED;
+ simple_unlock(&lkp->lk_interlock);
+ return (lock_type);
+}
+
/*
* Print out information about state of a lock. Used by VOP_PRINT
* routines to display status about contained locks.
OpenPOWER on IntegriCloud