PERFORCE change 114791 for review

Roman Divacky rdivacky at FreeBSD.org
Wed Feb 21 11:13:38 UTC 2007


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

Change 114791 by rdivacky at rdivacky_witten on 2007/02/21 11:12:41

	o	revert the previous change. linux wakes up N threads for all
		operations BUT requeue ones. mimic this by checking for newf
		being non-NULL and setting count accordingly.
	o	introduce one more param to futex_wake which mimics the nr_requeue
		in linux thats wake up N+1 threads then requeue upto N2 on the
		new futex. note that the code doing the requeueing is likely to
		be rewritten (pending discussion with the original author).

Affected files ...

.. //depot/projects/linuxolator/src/sys/compat/linux/linux_futex.c#12 edit

Differences ...

==== //depot/projects/linuxolator/src/sys/compat/linux/linux_futex.c#12 (text+ko) ====

@@ -88,7 +88,7 @@
 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 *);
+static int futex_wake(struct futex *, int, struct futex *, int);
 static int futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr);
 static int futex_orl(int oparg, caddr_t uaddr, int *oldval);
 static int futex_andl(int oparg, caddr_t uaddr, int *oldval);
@@ -218,7 +218,7 @@
 			    td->td_proc->p_pid, args->uaddr, args->val);
 #endif
 		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
-		td->td_retval[0] = futex_wake(f, args->val, NULL);
+		td->td_retval[0] = futex_wake(f, args->val, NULL, 0);
 		futex_put(f);
 
 		FUTEX_SYSTEM_UNLOCK;
@@ -240,7 +240,7 @@
 
 		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
 		newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
-		td->td_retval[0] = futex_wake(f, args->val, newf);
+		td->td_retval[0] = futex_wake(f, args->val, newf, (int)(unsigned long)args->timeout);
 		futex_put(f);
 		futex_put(newf);
 
@@ -252,7 +252,7 @@
 
 		f = futex_get(args->uaddr, FUTEX_UNLOCKED);
 		newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
-		td->td_retval[0] = futex_wake(f, args->val, newf);
+		td->td_retval[0] = futex_wake(f, args->val, newf, (int)(unsigned long)args->timeout);
 		futex_put(f);
 		futex_put(newf);
 
@@ -299,7 +299,7 @@
 
 		}
 
-		ret = futex_wake(f, args->val, NULL);
+		ret = futex_wake(f, args->val, NULL, 0);
 		futex_put(f);
 		if (op_ret > 0) {
 			op_ret = 0;
@@ -307,7 +307,7 @@
 			 * Linux abuses the address of the timespec parameter
 			 * as the number of retries.
 			 */
-			op_ret += futex_wake(f2, (int) (unsigned long) args->timeout, NULL);
+			op_ret += futex_wake(f2, (int) (unsigned long) args->timeout, NULL, 0);
 			ret += op_ret;
 		}
 		futex_put(f2);
@@ -406,14 +406,24 @@
 }
 
 static int
-futex_wake(struct futex *f, int n, struct futex *newf)
+futex_wake(struct futex *f, int n, struct futex *newf, int n2)
 {
 	struct waiting_proc *wp;
-	int count = 0;
+	int count;
+
+	/*
+	 * Linux is very strange it wakes up N threads for
+	 * all operations BUT requeue ones where its N+1
+	 * mimic this.
+	 */
+	if (newf)
+		count = 0;
+	else
+		count = 1;
 
 	FUTEX_LOCK;
 	TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) {
-		if (count < n) {
+		if (count <= n) {
 			wakeup_one(wp);
 			count++;
 		} else {
@@ -421,6 +431,8 @@
 				/* futex_put called after tsleep */
 				wp->wp_new_futex = futex_get(newf->f_uaddr, FUTEX_LOCKED);
 				wakeup_one(wp);
+				if (count - n >= n2)
+					break;
 			}
 		}
 	}


More information about the p4-projects mailing list