Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Mar 2015 09:29:26 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r279583 - stable/10/sys/kern
Message-ID:  <201503040929.t249TQvT048286@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Mar  4 09:29:25 2015
New Revision: 279583
URL: https://svnweb.freebsd.org/changeset/base/279583

Log:
  MFC r279282:
  When unlocking a contested PI pthread mutex, if the queue of waiters
  is empty, look up the umtx_pi and disown it if the current thread owns it.

Modified:
  stable/10/sys/kern/kern_umtx.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/kern_umtx.c
==============================================================================
--- stable/10/sys/kern/kern_umtx.c	Wed Mar  4 09:17:03 2015	(r279582)
+++ stable/10/sys/kern/kern_umtx.c	Wed Mar  4 09:29:25 2015	(r279583)
@@ -1810,6 +1810,19 @@ umtx_pi_setowner(struct umtx_pi *pi, str
 	TAILQ_INSERT_TAIL(&uq_owner->uq_pi_contested, pi, pi_link);
 }
 
+
+/*
+ * Disown a PI mutex, and remove it from the owned list.
+ */
+static void
+umtx_pi_disown(struct umtx_pi *pi)
+{
+
+	mtx_assert(&umtx_lock, MA_OWNED);
+	TAILQ_REMOVE(&pi->pi_owner->td_umtxq->uq_pi_contested, pi, pi_link);
+	pi->pi_owner = NULL;
+}
+
 /*
  * Claim ownership of a PI mutex.
  */
@@ -2226,8 +2239,7 @@ do_unlock_pi(struct thread *td, struct u
 			return (EPERM);
 		}
 		uq_me = curthread->td_umtxq;
-		pi->pi_owner = NULL;
-		TAILQ_REMOVE(&uq_me->uq_pi_contested, pi, pi_link);
+		umtx_pi_disown(pi);
 		/* get highest priority thread which is still sleeping. */
 		uq_first = TAILQ_FIRST(&pi->pi_blocked);
 		while (uq_first != NULL && 
@@ -2248,6 +2260,25 @@ do_unlock_pi(struct thread *td, struct u
 		mtx_unlock_spin(&umtx_lock);
 		if (uq_first)
 			umtxq_signal_thread(uq_first);
+	} else {
+		pi = umtx_pi_lookup(&key);
+		/*
+		 * A umtx_pi can exist if a signal or timeout removed the
+		 * last waiter from the umtxq, but there is still
+		 * a thread in do_lock_pi() holding the umtx_pi.
+		 */
+		if (pi != NULL) {
+			/*
+			 * The umtx_pi can be unowned, such as when a thread
+			 * has just entered do_lock_pi(), allocated the
+			 * umtx_pi, and unlocked the umtxq.
+			 * If the current thread owns it, it must disown it.
+			 */
+			mtx_lock_spin(&umtx_lock);
+			if (pi->pi_owner == td)
+				umtx_pi_disown(pi);
+			mtx_unlock_spin(&umtx_lock);
+		}
 	}
 	umtxq_unlock(&key);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503040929.t249TQvT048286>