2007-07-05  Roland McGrath  <roland@frob.com>

	* process.c [LINUX] (futexops): Add many new values.
	[LINUX] (futexwakeops, futexwakecmps): New tables.
	[LINUX] (sys_futex): Use them.
	From Ulrich Drepper <drepper@redhat.com>.
	Fixes RH#241467.
diff --git a/process.c b/process.c
index d478293..45f42b5 100644
--- a/process.c
+++ b/process.c
@@ -3067,12 +3067,75 @@
 #endif /* !SVR4 */
 
 #ifdef LINUX
+# ifndef FUTEX_CMP_REQUEUE
+#  define FUTEX_CMP_REQUEUE 4
+# endif
+# ifndef FUTEX_WAKE_OP
+#  define FUTEX_WAKE_OP 5
+# endif
+# ifndef FUTEX_LOCK_PI
+#  define FUTEX_LOCK_PI 6
+#  define FUTEX_UNLOCK_PI 7
+#  define FUTEX_TRYLOCK_PI 8
+# endif
+# ifndef FUTEX_CMP_REQUEUE_PI
+#  define FUTEX_CMP_REQUEUE_PI 9
+# endif
+# ifndef FUTEX_PRIVATE_FLAG
+#  define FUTEX_PRIVATE_FLAG 128
+# endif
 static const struct xlat futexops[] = {
-	{ FUTEX_WAIT,	"FUTEX_WAIT" },
-	{ FUTEX_WAKE,	"FUTEX_WAKE" },
-	{ FUTEX_FD,	"FUTEX_FD" },
-	{ FUTEX_REQUEUE,"FUTEX_REQUEUE" },
-	{ 0,		NULL }
+	{ FUTEX_WAIT,					"FUTEX_WAIT" },
+	{ FUTEX_WAKE,					"FUTEX_WAKE" },
+	{ FUTEX_FD,					"FUTEX_FD" },
+	{ FUTEX_REQUEUE,				"FUTEX_REQUEUE" },
+	{ FUTEX_CMP_REQUEUE,				"FUTEX_CMP_REQUEUE" },
+	{ FUTEX_WAKE_OP,				"FUTEX_WAKE_OP" },
+	{ FUTEX_LOCK_PI,				"FUTEX_LOCK_PI" },
+	{ FUTEX_UNLOCK_PI,				"FUTEX_UNLOCK_PI" },
+	{ FUTEX_TRYLOCK_PI,				"FUTEX_TRYLOCK_PI" },
+	{ FUTEX_CMP_REQUEUE_PI,				"FUTEX_CMP_REQUEUE_PI" },
+	{ FUTEX_WAIT|FUTEX_PRIVATE_FLAG,		"FUTEX_WAIT_PRIVATE" },
+	{ FUTEX_WAKE|FUTEX_PRIVATE_FLAG,		"FUTEX_WAKE_PRIVATE" },
+	{ FUTEX_FD|FUTEX_PRIVATE_FLAG,			"FUTEX_FD_PRIVATE" },
+	{ FUTEX_REQUEUE|FUTEX_PRIVATE_FLAG,		"FUTEX_REQUEUE_PRIVATE" },
+	{ FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG,		"FUTEX_CMP_REQUEUE_PRIVATE" },
+	{ FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG,		"FUTEX_WAKE_OP_PRIVATE" },
+	{ FUTEX_LOCK_PI|FUTEX_PRIVATE_FLAG,		"FUTEX_LOCK_PI_PRIVATE" },
+	{ FUTEX_UNLOCK_PI|FUTEX_PRIVATE_FLAG,		"FUTEX_UNLOCK_PI_PRIVATE" },
+	{ FUTEX_TRYLOCK_PI|FUTEX_PRIVATE_FLAG,		"FUTEX_TRYLOCK_PI_PRIVATE" },
+	{ FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG,	"FUTEX_CMP_REQUEUE_PI_PRIVATE" },
+	{ 0,						NULL }
+};
+#ifndef FUTEX_OP_SET
+# define FUTEX_OP_SET		0
+# define FUTEX_OP_ADD		1
+# define FUTEX_OP_OR		2
+# define FUTEX_OP_ANDN		3
+# define FUTEX_OP_XOR		4
+# define FUTEX_OP_CMP_EQ	0
+# define FUTEX_OP_CMP_NE	1
+# define FUTEX_OP_CMP_LT	2
+# define FUTEX_OP_CMP_LE	3
+# define FUTEX_OP_CMP_GT	4
+# define FUTEX_OP_CMP_GE	5
+#endif
+static const struct xlat futexwakeops[] = {
+	{ FUTEX_OP_SET,		"FUTEX_OP_SET" },
+	{ FUTEX_OP_ADD,		"FUTEX_OP_ADD" },
+	{ FUTEX_OP_OR,		"FUTEX_OP_OR" },
+	{ FUTEX_OP_ANDN,	"FUTEX_OP_ANDN" },
+	{ FUTEX_OP_XOR,		"FUTEX_OP_XOR" },
+	{ 0,			NULL }
+};
+static const struct xlat futexwakecmps[] = {
+	{ FUTEX_OP_CMP_EQ,	"FUTEX_OP_CMP_EQ" },
+	{ FUTEX_OP_CMP_NE,	"FUTEX_OP_CMP_NE" },
+	{ FUTEX_OP_CMP_LT,	"FUTEX_OP_CMP_LT" },
+	{ FUTEX_OP_CMP_LE,	"FUTEX_OP_CMP_LE" },
+	{ FUTEX_OP_CMP_GT,	"FUTEX_OP_CMP_GT" },
+	{ FUTEX_OP_CMP_GE,	"FUTEX_OP_CMP_GE" },
+	{ 0,			NULL }
 };
 
 int
@@ -3080,14 +3143,28 @@
 struct tcb *tcp;
 {
     if (entering(tcp)) {
+	long int cmd = tcp->u_arg[1] & ~FUTEX_PRIVATE_FLAG;
 	tprintf("%p, ", (void *) tcp->u_arg[0]);
 	printxval(futexops, tcp->u_arg[1], "FUTEX_???");
 	tprintf(", %ld", tcp->u_arg[2]);
-	if (tcp->u_arg[1] == FUTEX_WAIT) {
+	if (cmd == FUTEX_WAIT) {
 		tprintf(", ");
 		printtv(tcp, tcp->u_arg[3]);
-	} else if (tcp->u_arg[1] == FUTEX_REQUEUE)
+	} else if (cmd == FUTEX_REQUEUE)
 		tprintf(", %ld, %p", tcp->u_arg[3], (void *) tcp->u_arg[4]);
+	else if (cmd == FUTEX_CMP_REQUEUE)
+		tprintf(", %ld, %p, %ld", tcp->u_arg[3], (void *) tcp->u_arg[4], tcp->u_arg[5]);
+	else if (cmd == FUTEX_WAKE_OP) {
+		tprintf(", %ld, %p, {", tcp->u_arg[3], (void *) tcp->u_arg[4]);
+		if ((tcp->u_arg[5] >> 28) & 8)
+			tprintf("FUTEX_OP_OPARG_SHIFT|");
+		printxval(futexwakeops, (tcp->u_arg[5] >> 28) & 0x7, "FUTEX_OP_???");
+		tprintf(", %ld, ", (tcp->u_arg[5] >> 12) & 0xfff);
+		if ((tcp->u_arg[5] >> 24) & 8)
+			tprintf("FUTEX_OP_OPARG_SHIFT|");
+		printxval(futexwakecmps, (tcp->u_arg[5] >> 24) & 0x7, "FUTEX_OP_CMP_???");
+		tprintf(", %ld}", tcp->u_arg[5] & 0xfff);
+	}
     }
     return 0;
 }