Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Jul 2003 19:52:22 -0400
From:      Mike Makonnen <mtm@identd.net>
To:        Kai Mosebach <kai.mosebach@freshx.de>
Cc:        freebsd-threads@freebsd.org
Subject:   Re: LinuxThreads replacement
Message-ID:  <20030709235221.GA10504@kokeb.ambesa.net>
In-Reply-To: <001b01c3463a$0f907a00$0100a8c0@alpha>
References:  <Pine.GSO.4.10.10307091234350.3409-100000@pcnet5.pcnet.com> <001b01c3463a$0f907a00$0100a8c0@alpha>

next in thread | previous in thread | raw e-mail | index | archive | help

--oyUTqETQ0mS9luUI
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Jul 09, 2003 at 06:49:25PM +0200, Kai Mosebach wrote:
> 
> Would you more likely use libthr or libkse, 
> as kse is not complete yet, isnt it ?
> 

Either one should work just as well. There is currently a race
in the kernel code for libthr that can lead to deadlocks. I have
a fix for this and I am waiting for jeff to review it before I
commit it. In the mean time you can get the patch here:
http://people.freebsd.org/~mtm/patches/libthr.kern.diff

(also attached)


Cheers.
-- 
Mike Makonnen  | GPG-KEY: http://www.identd.net/~mtm/mtm.asc
mtm@identd.net | D228 1A6F C64E 120A A1C9  A3AA DAE1 E2AF DBCC 68B9
mtm@FreeBSD.Org| FreeBSD - Unleash the Daemon!

--oyUTqETQ0mS9luUI
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="umtx3.diff"

Index: sys/kern/kern_umtx.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_umtx.c,v
retrieving revision 1.7
diff -u -r1.7 kern_umtx.c
--- sys/kern/kern_umtx.c	4 Jul 2003 23:28:42 -0000	1.7
+++ sys/kern/kern_umtx.c	5 Jul 2003 05:53:02 -0000
@@ -181,7 +181,7 @@
 				return (EFAULT);
 
 			if (owner == UMTX_CONTESTED)
-				return (0);
+				goto out;
 
 			/* If this failed the lock has changed, restart. */
 			continue;
@@ -190,7 +190,6 @@
 
 		UMTX_LOCK();
 		uq = umtx_insert(td, umtx);
-		UMTX_UNLOCK();
 
 		/*
 		 * Set the contested bit so that a release in user space
@@ -203,7 +202,6 @@
 
 		/* The address was invalid. */
 		if (old == -1) {
-			UMTX_LOCK();
 			umtx_remove(uq, td);
 			UMTX_UNLOCK();
 			return (EFAULT);
@@ -213,7 +211,6 @@
 		 * We set the contested bit, sleep. Otherwise the lock changed
 		 * and we need to retry.
 		 */
-		UMTX_LOCK();
 		if (old == owner)
 			error = msleep(td, &umtx_lock,
 			    td->td_priority | PCATCH, "umtx", 0);
@@ -230,8 +227,37 @@
 		if (error)
 			return (error);
 	}
-
-	return (0);
+out:
+	/*
+	 * We reach here only if we just acquired a contested umtx.
+	 *
+	 * If there are no other threads on this umtx's queue
+	 * clear the contested bit. However, we cannot hold
+	 * a lock across casuptr().  So after we unset it we
+	 * have to recheck, and set it again if another thread has
+	 * put itself on the queue in the mean time.
+	 */
+	error = 0;
+	UMTX_LOCK();
+	uq = umtx_lookup(td, umtx);
+	UMTX_UNLOCK();
+	if (uq == NULL)
+		old = casuptr((intptr_t *)&umtx->u_owner,
+		    ((intptr_t)td | UMTX_CONTESTED), (intptr_t)td);
+	if (uq == NULL && old == ((intptr_t)td | UMTX_CONTESTED)) {
+		UMTX_LOCK();
+		uq = umtx_lookup(td, umtx);
+		UMTX_UNLOCK();
+		if (uq != NULL) {
+			old = casuptr((intptr_t *)&umtx->u_owner,
+			    (intptr_t)td, ((intptr_t)td | UMTX_CONTESTED));
+			if (old == -1)
+				error = EFAULT;
+			else if (old != (intptr_t)td)
+				error = EINVAL;
+		}
+	}
+	return (error);
 }
 
 int
@@ -257,25 +283,9 @@
 
 	if ((struct thread *)(owner & ~UMTX_CONTESTED) != td)
 		return (EPERM);
-	/*
-	 * If we own it but it isn't contested then we can just release and
-	 * return.
-	 */
-	if ((owner & UMTX_CONTESTED) == 0) {
-		owner = casuptr((intptr_t *)&umtx->u_owner,
-		    (intptr_t)td, UMTX_UNOWNED);
 
-		if (owner == -1)
-			return (EFAULT);
-		/*
-		 * If this failed someone modified the memory without going
-		 * through this api.
-		 */
-		if (owner != (intptr_t)td)
-			return (EINVAL);
-
-		return (0);
-	}
+	/* We should only ever be in here for contested locks */
+	KASSERT((owner & UMTX_CONTESTED) != 0, ("contested umtx is not."));
 
 	old = casuptr((intptr_t *)&umtx->u_owner, owner, UMTX_CONTESTED);
 
@@ -296,6 +306,7 @@
 	uq = umtx_lookup(td, umtx);
 	if (uq != NULL) {
 		blocked = TAILQ_FIRST(&uq->uq_tdq);
+		KASSERT(blocked != NULL, ("umtx_q with no waiting threads."));
 		wakeup(blocked);
 	}
 

--oyUTqETQ0mS9luUI--



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