git: 07d108932ab5 - main - linux(4): Return native error from futex_atomic_op to avoid conversion by the caller.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Mon, 09 May 2022 18:17:11 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=07d108932ab5b5bc25221be4916ebf8874cd256f

commit 07d108932ab5b5bc25221be4916ebf8874cd256f
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-09 18:16:31 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-05-09 18:16:31 +0000

    linux(4): Return native error from futex_atomic_op to avoid conversion by the caller.
    
    MFC after:              2 weeks
---
 sys/amd64/linux/linux_support.s     |  2 +-
 sys/amd64/linux32/linux32_support.s |  2 +-
 sys/compat/linux/linux_futex.c      | 31 +++++++++++++------------------
 sys/i386/linux/linux_copyout.c      | 10 +++++-----
 4 files changed, 20 insertions(+), 25 deletions(-)

diff --git a/sys/amd64/linux/linux_support.s b/sys/amd64/linux/linux_support.s
index 79e361867f1d..1e9ad45b9623 100644
--- a/sys/amd64/linux/linux_support.s
+++ b/sys/amd64/linux/linux_support.s
@@ -39,7 +39,7 @@ futex_fault:
 	je	1f
 	clac
 1:	movq	$0,PCB_ONFAULT(%r8)
-	movl	$-EFAULT,%eax
+	movl	$EFAULT,%eax
 	ret
 
 ENTRY(futex_xchgl_nosmap)
diff --git a/sys/amd64/linux32/linux32_support.s b/sys/amd64/linux32/linux32_support.s
index 2e2dbca4e24b..c92cb48e2d1a 100644
--- a/sys/amd64/linux32/linux32_support.s
+++ b/sys/amd64/linux32/linux32_support.s
@@ -39,7 +39,7 @@ futex_fault:
 	je	1f
 	clac
 1:	movq	$0,PCB_ONFAULT(%r8)
-	movl	$-EFAULT,%eax
+	movl	$EFAULT,%eax
 	ret
 
 ENTRY(futex_xchgl_nosmap)
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index 1b4ef9e8efe8..2bcaabf2d972 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
 
 #define	GET_SHARED(a)	(a->flags & FUTEX_SHARED) ? AUTO_SHARE : THREAD_SHARE
 
-static int futex_atomic_op(struct thread *, int, uint32_t *);
+static int futex_atomic_op(struct thread *, int, uint32_t *, int *);
 static int handle_futex_death(struct thread *td, struct linux_emuldata *,
     uint32_t *, unsigned int, bool);
 static int fetch_robust_entry(struct linux_robust_list **,
@@ -130,7 +130,8 @@ futex_wake_pi(struct thread *td, uint32_t *uaddr, bool shared)
 }
 
 static int
-futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr)
+futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr,
+    int *res)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -158,34 +159,34 @@ futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr)
 		ret = futex_xorl(oparg, uaddr, &oldval);
 		break;
 	default:
-		ret = -ENOSYS;
+		ret = ENOSYS;
 		break;
 	}
 
-	if (ret)
+	if (ret != 0)
 		return (ret);
 
 	switch (cmp) {
 	case FUTEX_OP_CMP_EQ:
-		ret = (oldval == cmparg);
+		*res = (oldval == cmparg);
 		break;
 	case FUTEX_OP_CMP_NE:
-		ret = (oldval != cmparg);
+		*res = (oldval != cmparg);
 		break;
 	case FUTEX_OP_CMP_LT:
-		ret = (oldval < cmparg);
+		*res = (oldval < cmparg);
 		break;
 	case FUTEX_OP_CMP_GE:
-		ret = (oldval >= cmparg);
+		*res = (oldval >= cmparg);
 		break;
 	case FUTEX_OP_CMP_LE:
-		ret = (oldval <= cmparg);
+		*res = (oldval <= cmparg);
 		break;
 	case FUTEX_OP_CMP_GT:
-		ret = (oldval > cmparg);
+		*res = (oldval > cmparg);
 		break;
 	default:
-		ret = -ENOSYS;
+		ret = ENOSYS;
 	}
 
 	return (ret);
@@ -635,13 +636,7 @@ linux_futex_wakeop(struct thread *td, struct linux_futex_args *args)
 	umtxq_lock(&key);
 	umtxq_busy(&key);
 	umtxq_unlock(&key);
-	op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
-	if (op_ret < 0) {
-		if (op_ret == -ENOSYS)
-			error = ENOSYS;
-		else
-			error = EFAULT;
-	}
+	error = futex_atomic_op(td, args->val3, args->uaddr2, &op_ret);
 	umtxq_lock(&key);
 	umtxq_unbusy(&key);
 	if (error != 0)
diff --git a/sys/i386/linux/linux_copyout.c b/sys/i386/linux/linux_copyout.c
index bf4c874c3cf2..6dc98bc8bf5d 100644
--- a/sys/i386/linux/linux_copyout.c
+++ b/sys/i386/linux/linux_copyout.c
@@ -72,7 +72,7 @@ futex_xchgl(int oparg, uint32_t *uaddr, int *oldval)
 	st.oldval = oldval;
 	if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
 	    futex_xchgl_slow0, &st) != 0)
-		return (-EFAULT);
+		return (EFAULT);
 	return (0);
 }
 
@@ -94,7 +94,7 @@ futex_addl(int oparg, uint32_t *uaddr, int *oldval)
 	st.oldval = oldval;
 	if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
 	    futex_addl_slow0, &st) != 0)
-		return (-EFAULT);
+		return (EFAULT);
 	return (0);
 }
 
@@ -120,7 +120,7 @@ futex_orl(int oparg, uint32_t *uaddr, int *oldval)
 	st.oldval = oldval;
 	if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
 	    futex_orl_slow0, &st) != 0)
-		return (-EFAULT);
+		return (EFAULT);
 	return (0);
 }
 
@@ -146,7 +146,7 @@ futex_andl(int oparg, uint32_t *uaddr, int *oldval)
 	st.oldval = oldval;
 	if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
 	    futex_andl_slow0, &st) != 0)
-		return (-EFAULT);
+		return (EFAULT);
 	return (0);
 }
 
@@ -172,6 +172,6 @@ futex_xorl(int oparg, uint32_t *uaddr, int *oldval)
 	st.oldval = oldval;
 	if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
 	    futex_xorl_slow0, &st) != 0)
-		return (-EFAULT);
+		return (EFAULT);
 	return (0);
 }