PERFORCE change 103234 for review

Roman Divacky rdivacky at FreeBSD.org
Sat Aug 5 09:09:24 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=103234

Change 103234 by rdivacky at rdivacky_witten on 2006/08/05 09:09:22

	Fix the deadlock in futex_wake() which holds FUTEX_LOCK and calls futex_get()
	which wants to acquire FUTEX_LOCK as well. So I add flag which indicates wheter
	the lock should be acquired. I prefer this over a recursive mutex.

Affected files ...

.. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#17 edit

Differences ...

==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#17 (text+ko) ====

@@ -73,7 +73,10 @@
 #define FUTEX_LOCK mtx_lock(&futex_mtx)
 #define FUTEX_UNLOCK mtx_unlock(&futex_mtx)
 
-static struct futex *futex_get(void *);
+#define FUTEX_LOCKED	1
+#define FUTEX_UNLOCKED	0
+
+static struct futex *futex_get(void *, int);
 static void futex_put(struct futex *);
 static int futex_sleep(struct futex *, struct thread *, unsigned long);
 static int futex_wake(struct futex *, int, struct futex *);
@@ -144,7 +147,7 @@
                         timeout_hz = 1;
 
 
-		f = futex_get(args->uaddr);
+		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
 		ret = futex_sleep(f, td, timeout_hz);
 		futex_put(f);
 
@@ -191,7 +194,7 @@
    			printf("FUTEX_WAKE %d: uaddr = %p, val = %d\n", 
 		   		 td->td_proc->p_pid, args->uaddr, args->val); 
 #endif
-		f = futex_get(args->uaddr);
+		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
 		td->td_retval[0] = futex_wake(f, args->val, NULL);
 		futex_put(f);
 		break;
@@ -206,8 +209,8 @@
 		/* FALLTHROUGH */
 
 	case LINUX_FUTEX_REQUEUE:
-		f = futex_get(args->uaddr);
-		newf = futex_get(args->uaddr2);
+		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
+		newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
 		td->td_retval[0] = futex_wake(f, args->val, newf);
 		futex_put(f);
 		futex_put(newf);
@@ -225,8 +228,8 @@
    		   	printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, val = %d, uaddr2 = %p, val3 = %d\n",
 		      		td->td_proc->p_pid, args->uaddr, args->op, args->val, args->uaddr2, args->val3);
 #endif
-		f = futex_get(args->uaddr);
-		f2 = futex_get(args->uaddr2);
+		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
+		f2 = futex_get(args->uaddr2, FUTEX_UNLOCKED);
 
 		op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
 		if (op_ret < 0) {
@@ -267,28 +270,33 @@
 }
 
 static struct futex *
-futex_get(void *uaddr)
+futex_get(void *uaddr, int locked)
 {
 	struct futex *f;
 
-	FUTEX_LOCK;
+	if (locked == FUTEX_UNLOCKED)
+   	   	FUTEX_LOCK;
 	LIST_FOREACH(f, &futex_list, f_list) {
 		if (f->f_uaddr == uaddr) {
 			f->f_refcount++;
-			FUTEX_UNLOCK;
+			if (locked == FUTEX_UNLOCKED)
+   			   	FUTEX_UNLOCK;
 			return f;
 		}
 	}
-	FUTEX_UNLOCK;
+	if (locked == FUTEX_UNLOCKED)
+   	   	FUTEX_UNLOCK;
 
 	/* Not found, create it */
 	f = malloc(sizeof(*f), M_LINUX, M_WAITOK);
 	f->f_uaddr = uaddr;
 	f->f_refcount = 1;
 	TAILQ_INIT(&f->f_waiting_proc);
-	FUTEX_LOCK;
+	if (locked == FUTEX_UNLOCKED)
+   	   	FUTEX_LOCK;
 	LIST_INSERT_HEAD(&futex_list, f, f_list);
-	FUTEX_UNLOCK;
+	if (locked == FUTEX_UNLOCKED)
+   	   	FUTEX_UNLOCK;
 
 	return f;
 }
@@ -356,7 +364,7 @@
 		} else {
 			if (newf != NULL) {
 				/* futex_put called after tsleep */
-				wp->wp_new_futex = futex_get(newf->f_uaddr);
+				wp->wp_new_futex = futex_get(newf->f_uaddr, FUTEX_LOCKED);
 				wakeup(wp);
 			}
 		}


More information about the p4-projects mailing list