svn commit: r218117 - head/sys/compat/linux

Dmitry Chagin dchagin at FreeBSD.org
Mon Jan 31 05:59:06 UTC 2011


Author: dchagin
Date: Mon Jan 31 05:59:05 2011
New Revision: 218117
URL: http://svn.freebsd.org/changeset/base/218117

Log:
  Implement a futex BITSET op.
  
  Submitted by:	arundel
  MFC after:	1 month.

Modified:
  head/sys/compat/linux/linux_futex.c
  head/sys/compat/linux/linux_futex.h

Modified: head/sys/compat/linux/linux_futex.c
==============================================================================
--- head/sys/compat/linux/linux_futex.c	Mon Jan 31 00:29:11 2011	(r218116)
+++ head/sys/compat/linux/linux_futex.c	Mon Jan 31 05:59:05 2011	(r218117)
@@ -79,6 +79,7 @@ struct futex {
 	struct sx	f_lck;
 	uint32_t	*f_uaddr;
 	uint32_t	f_refcount;
+	uint32_t	f_bitset;
 	LIST_ENTRY(futex) f_list;
 	TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc;
 };
@@ -264,15 +265,25 @@ futex_sleep(struct futex *f, struct wait
 }
 
 static int
-futex_wake(struct futex *f, int n)
+futex_wake(struct futex *f, int n, uint32_t bitset)
 {
 	struct waiting_proc *wp, *wpt;
 	int count = 0;
 
+	if (bitset == 0)
+		return (EINVAL);
+
 	FUTEX_ASSERT_LOCKED(f);
 	TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) {
 		LINUX_CTR3(sys_futex, "futex_wake uaddr %p wp %p ref %d",
 		    f->f_uaddr, wp, f->f_refcount);
+		/*
+		 * Unless we find a matching bit in
+		 * the bitset, continue searching.
+		 */
+		if (!(wp->wp_futex->f_bitset & bitset))
+			continue;
+
 		wp->wp_flags |= FUTEX_WP_REMOVED;
 		TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
 		wakeup_one(wp);
@@ -325,13 +336,18 @@ futex_requeue(struct futex *f, int n, st
 }
 
 static int
-futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts)
+futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts,
+    uint32_t bitset)
 {
 	struct l_timespec timeout;
 	struct timeval tv;
 	int timeout_hz;
 	int error;
 
+	if (bitset == 0)
+		return (EINVAL);
+	f->f_bitset = bitset;
+
 	if (ts != NULL) {
 		error = copyin(ts, &timeout, sizeof(timeout));
 		if (error)
@@ -445,13 +461,18 @@ linux_sys_futex(struct thread *td, struc
 
 	switch (args->op) {
 	case LINUX_FUTEX_WAIT:
+		args->val3 = FUTEX_BITSET_MATCH_ANY;
+		/* FALLTHROUGH */
+
+	case LINUX_FUTEX_WAIT_BITSET:
 
-		LINUX_CTR2(sys_futex, "WAIT val %d uaddr %p",
-		    args->val, args->uaddr);
+		LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d val3 %d",
+		    args->uaddr, args->val, args->val3);
 #ifdef DEBUG
 		if (ldebug(sys_futex))
-			printf(ARGS(sys_futex, "futex_wait val %d uaddr %p"),
-			    args->val, args->uaddr);
+			printf(ARGS(sys_futex,
+			    "futex_wait uaddr %p val %d val3 %d"),
+			    args->uaddr, args->val, args->val3);
 #endif
 		error = futex_get(args->uaddr, &wp, &f, FUTEX_CREATE_WP);
 		if (error)
@@ -464,19 +485,24 @@ linux_sys_futex(struct thread *td, struc
 			return (error);
 		}
 		if (val != args->val) {
-			LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d != uval %d",
-			    args->uaddr, args->val, val);
+			LINUX_CTR4(sys_futex,
+			    "WAIT uaddr %p val %d != uval %d val3 %d",
+			    args->uaddr, args->val, val, args->val3);
 			futex_put(f, wp);
 			return (EWOULDBLOCK);
 		}
 
-		error = futex_wait(f, wp, args->timeout);
+		error = futex_wait(f, wp, args->timeout, args->val3);
 		break;
 
 	case LINUX_FUTEX_WAKE:
+		args->val3 = FUTEX_BITSET_MATCH_ANY;
+		/* FALLTHROUGH */
+
+	case LINUX_FUTEX_WAKE_BITSET:
 
-		LINUX_CTR2(sys_futex, "WAKE val %d uaddr %p",
-		    args->val, args->uaddr);
+		LINUX_CTR3(sys_futex, "WAKE uaddr %p val % d val3 %d",
+		    args->uaddr, args->val, args->val3);
 
 		/*
 		 * XXX: Linux is able to cope with different addresses
@@ -485,8 +511,8 @@ linux_sys_futex(struct thread *td, struc
 		 */
 #ifdef DEBUG
 		if (ldebug(sys_futex))
-			printf(ARGS(sys_futex, "futex_wake val %d uaddr %p"),
-			    args->val, args->uaddr);
+			printf(ARGS(sys_futex, "futex_wake uaddr %p val %d val3 %d"),
+			    args->uaddr, args->val, args->val3);
 #endif
 		error = futex_get(args->uaddr, NULL, &f, FUTEX_DONTCREATE);
 		if (error)
@@ -495,7 +521,7 @@ linux_sys_futex(struct thread *td, struc
 			td->td_retval[0] = 0;
 			return (error);
 		}
-		td->td_retval[0] = futex_wake(f, args->val);
+		td->td_retval[0] = futex_wake(f, args->val, args->val3);
 		futex_put(f, NULL);
 		break;
 
@@ -603,16 +629,16 @@ linux_sys_futex(struct thread *td, struc
 			return (EFAULT);
 		}
 
-		ret = futex_wake(f, args->val);
+		ret = futex_wake(f, args->val, args->val3);
 
 		if (op_ret > 0) {
 			op_ret = 0;
 			nrwake = (int)(unsigned long)args->timeout;
 
 			if (f2 != NULL)
-				op_ret += futex_wake(f2, nrwake);
+				op_ret += futex_wake(f2, nrwake, args->val3);
 			else
-				op_ret += futex_wake(f, nrwake);
+				op_ret += futex_wake(f, nrwake, args->val3);
 			ret += op_ret;
 
 		}
@@ -660,13 +686,6 @@ linux_sys_futex(struct thread *td, struc
 		}
 		return (EINVAL);
 
-	case LINUX_FUTEX_WAIT_BITSET:
-		/* not yet implemented */
-		linux_msg(td,
-			  "linux_sys_futex: "
-			  "op FUTEX_WAIT_BITSET not implemented\n");
-		return (ENOSYS);
-
 	case LINUX_FUTEX_WAIT_REQUEUE_PI:
 		/* not yet implemented */
 		linux_msg(td,
@@ -775,7 +794,7 @@ retry:
 			if (error)
 				return (error);
 			if (f != NULL) {
-				futex_wake(f, 1);
+				futex_wake(f, 1, FUTEX_BITSET_MATCH_ANY);
 				futex_put(f, NULL);
 			}
 		}

Modified: head/sys/compat/linux/linux_futex.h
==============================================================================
--- head/sys/compat/linux/linux_futex.h	Mon Jan 31 00:29:11 2011	(r218116)
+++ head/sys/compat/linux/linux_futex.h	Mon Jan 31 05:59:05 2011	(r218117)
@@ -49,6 +49,7 @@ extern struct mtx futex_mtx;
 #define LINUX_FUTEX_UNLOCK_PI		 7
 #define LINUX_FUTEX_TRYLOCK_PI		 8
 #define LINUX_FUTEX_WAIT_BITSET		 9
+#define LINUX_FUTEX_WAKE_BITSET		10
 #define LINUX_FUTEX_WAIT_REQUEUE_PI	11
 
 #define LINUX_FUTEX_PRIVATE_FLAG	128
@@ -72,6 +73,7 @@ extern struct mtx futex_mtx;
 #define	FUTEX_WAITERS		0x80000000
 #define	FUTEX_OWNER_DIED	0x40000000
 #define	FUTEX_TID_MASK		0x3fffffff
+#define	FUTEX_BITSET_MATCH_ANY	0xffffffff
 
 void	release_futexes(struct proc *);
 


More information about the svn-src-all mailing list