--- /usr/src/sys/kern/kern_sx.c	Thu Apr 12 05:27:25 2007
+++ kern_sx.c	Fri May  4 23:11:35 2007
@@ -210,6 +210,21 @@
 }
 
 int
+_sx_slock_sig(struct sx *sx, const char *file, int line)
+{
+	int error;
+
+	MPASS(curthread != NULL);
+	WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line);
+	if (!(error = _sx_slock_hard(sx, SX_INTERRUPTIBLE, file, line))) {
+		LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line);
+		WITNESS_LOCK(&sx->lock_object, 0, file, line);
+		curthread->td_locks++;
+	}
+	return (error);
+}
+
+int
 _sx_try_slock(struct sx *sx, const char *file, int line)
 {
 	uintptr_t x;
@@ -241,6 +256,24 @@
 }
 
 int
+_sx_xlock_sig(struct sx *sx, const char *file, int line)
+{
+	int error;
+
+	MPASS(curthread != NULL);
+	WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
+	    line);
+	if (!(error = _sx_xlock_hard(sx, (uintptr_t)curthread, SX_INTERRUPTIBLE,
+	    file, line))) {
+		LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse,
+		    file, line);
+		WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
+		curthread->td_locks++;
+	}
+	return (error);
+}
+
+int
 _sx_try_xlock(struct sx *sx, const char *file, int line)
 {
 	int rval;
@@ -384,15 +417,16 @@
  * that ideally this would be a static function, but it needs to be
  * accessible from at least sx.h.
  */
-void
-_sx_xlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
+int
+_sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
+    int line)
 {
 	GIANT_DECLARE;
 #ifdef ADAPTIVE_SX
 	volatile struct thread *owner;
 #endif
 	uintptr_t x;
-	int contested = 0;
+	int contested = 0, error = 0;
 	uint64_t waitstart = 0;
 
 	/* If we already hold an exclusive lock, then recurse. */
@@ -401,7 +435,7 @@
 		atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p recursing", __func__, sx);
-		return;
+		return (0);
 	}
 	lock_profile_obtain_lock_failed(&(sx)->lock_object,
 	    &contested, &waitstart);
@@ -515,8 +549,17 @@
 
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
-		    SLEEPQ_SX, SQ_EXCLUSIVE_QUEUE);
-		sleepq_wait(&sx->lock_object);
+		    SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ?
+		    SLEEPQ_INTERRUPTIBLE : 0), SQ_EXCLUSIVE_QUEUE);
+		if (!(opts & SX_INTERRUPTIBLE))
+			sleepq_wait(&sx->lock_object);
+		else if ((error = sleepq_wait_sig(&sx->lock_object))) {
+			if (LOCK_LOG_TEST(&sx->lock_object, 0))
+				CTR3(KTR_LOCK, "%s: interruptible sleep by "
+				    "%p suspended by signal with %d errno",
+				    __func__, sx, error);
+			break;
+		}
 
 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
@@ -524,8 +567,10 @@
 	}
 	
 	GIANT_RESTORE();
-	lock_profile_obtain_lock_success(&(sx)->lock_object, contested,
-	    waitstart, file, line);
+	if (!error)
+		lock_profile_obtain_lock_success(&(sx)->lock_object, contested,
+		    waitstart, file, line);
+	return (error);
 }
 
 /*
@@ -585,8 +630,8 @@
  * that ideally this would be a static function, but it needs to be
  * accessible from at least sx.h.
  */
-void
-_sx_slock_hard(struct sx *sx, const char *file, int line)
+int
+_sx_slock_hard(struct sx *sx, int opts, const char *file, int line)
 {
 	GIANT_DECLARE;
 #ifdef ADAPTIVE_SX
@@ -594,7 +639,7 @@
 #endif
 	uintptr_t x;
 	uint64_t waitstart = 0;
-	int contested = 0;
+	int contested = 0, error = 0;
 	/*
 	 * As with rwlocks, we don't make any attempt to try to block
 	 * shared locks once there is an exclusive waiter.
@@ -716,8 +761,17 @@
 		
 		GIANT_SAVE();
 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
-		    SLEEPQ_SX, SQ_SHARED_QUEUE);
-		sleepq_wait(&sx->lock_object);
+		    SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ?
+		    SLEEPQ_INTERRUPTIBLE : 0), SQ_SHARED_QUEUE);
+		if (!(opts & SX_INTERRUPTIBLE))
+			sleepq_wait(&sx->lock_object);
+		else if ((error = sleepq_wait_sig(&sx->lock_object))) {
+			if (LOCK_LOG_TEST(&sx->lock_object, 0))
+				CTR3(KTR_LOCK, "%s: interruptible sleep by "
+				    "%p suspended by signal with %d errno",
+				    __func__, sx, error);
+			break;
+		}
 
 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
 			CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
@@ -725,6 +779,7 @@
 	}
 
 	GIANT_RESTORE();
+	return (error);
 }
 
 /*
--- /usr/src/sys/sys/sx.h	Thu Apr 12 05:27:40 2007
+++ sx.h	Fri May  4 23:10:59 2007
@@ -100,7 +100,7 @@
 									\
 	if (!atomic_cmpset_acq_ptr(&(sx)->sx_lock, SX_LOCK_UNLOCKED,	\
 	    _tid)) {							\
-		_sx_xlock_hard((sx), _tid, (file), (line));		\
+		_sx_xlock_hard((sx), _tid, 0, (file), (line));		\
 	} else								\
 		lock_profile_obtain_lock_success(&(sx)->lock_object, 0,	\
 		    0, (file), (line));					\
@@ -122,7 +122,7 @@
 	if (!(x & SX_LOCK_SHARED) ||					\
 	    !atomic_cmpset_acq_ptr(&(sx)->sx_lock, x,			\
 	    x + SX_ONE_SHARER)) {					\
-		_sx_slock_hard((sx), (file), (line));			\
+		_sx_slock_hard((sx), 0, (file), (line));		\
 	} else								\
 		lock_profile_obtain_lock_success(&(sx)->lock_object, 0,	\
 		    0, (file), (line));					\
@@ -152,16 +152,18 @@
 void	sx_init_flags(struct sx *sx, const char *description, int opts);
 void	sx_destroy(struct sx *sx);
 void	_sx_slock(struct sx *sx, const char *file, int line);
+int	_sx_slock_sig(struct sx *sx, const char *file, int line);
 void	_sx_xlock(struct sx *sx, const char *file, int line);
+int	_sx_xlock_sig(struct sx *sx, const char *file, int line);
 int	_sx_try_slock(struct sx *sx, const char *file, int line);
 int	_sx_try_xlock(struct sx *sx, const char *file, int line);
 void	_sx_sunlock(struct sx *sx, const char *file, int line);
 void	_sx_xunlock(struct sx *sx, const char *file, int line);
 int	_sx_try_upgrade(struct sx *sx, const char *file, int line);
 void	_sx_downgrade(struct sx *sx, const char *file, int line);
-void	_sx_xlock_hard(struct sx *sx, uintptr_t tid, const char *file, int
-	    line);
-void	_sx_slock_hard(struct sx *sx, const char *file, int line);
+int	_sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts,
+	    const char *file, int line);
+int	_sx_slock_hard(struct sx *sx, int opts, const char *file, int line);
 void	_sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int
 	    line);
 void	_sx_sunlock_hard(struct sx *sx, const char *file, int line);
@@ -195,15 +197,22 @@
 #endif
 #if	(LOCK_DEBUG > 0) || defined(SX_NOINLINE)
 #define	sx_xlock(sx)		_sx_xlock((sx), LOCK_FILE, LOCK_LINE)
+#define	sx_xlock_sig(sx)	_sx_xlock_sig((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_xunlock(sx)		_sx_xunlock((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_slock(sx)		_sx_slock((sx), LOCK_FILE, LOCK_LINE)
+#define	sx_slock_sig(sx)	_sx_slock_sig((sx), LOCK_FILE, LOCK_LINE)
 #define	sx_sunlock(sx)		_sx_sunlock((sx), LOCK_FILE, LOCK_LINE)
 #else
 #define	sx_xlock(sx)							\
 	__sx_xlock((sx), curthread, LOCK_FILE, LOCK_LINE)
+#define	sx_xlock_sig(sx)						\
+	_sx_xlock_hard((sx), (uintptr_t)curthread, SX_INTERRUPTIBLE,	\
+	    LOCK_FILE, LOCK_LINE)
 #define	sx_xunlock(sx)							\
 	__sx_xunlock((sx), curthread, LOCK_FILE, LOCK_LINE)
 #define	sx_slock(sx)		__sx_slock((sx), LOCK_FILE, LOCK_LINE)
+#define	sx_slock_sig(sx)						\
+	_sx_slock_hard((sx), SX_INTERRUPTIBLE, LOCK_FILE, LOCK_LINE)
 #define	sx_sunlock(sx)		__sx_sunlock((sx), LOCK_FILE, LOCK_LINE)
 #endif	/* LOCK_DEBUG > 0 || SX_NOINLINE */
 #define	sx_try_slock(sx)	_sx_try_slock((sx), LOCK_FILE, LOCK_LINE)
@@ -233,6 +242,11 @@
 #define	SX_NOWITNESS		0x04
 #define	SX_QUIET		0x08
 #define	SX_ADAPTIVESPIN		0x10
+
+/*
+ * Options passed to _sx_*lock_hard().
+ */
+#define	SX_INTERRUPTIBLE	0x01
 
 /*
  * XXX: These options should be renamed as SA_*
