git: 9fd86dde8377 - stable/13 - linux(4): Implement semtimedop syscalls.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Fri, 17 Jun 2022 19:39:59 UTC
The branch stable/13 has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=9fd86dde8377d11992924c74bf6dabb81081d0fc

commit 9fd86dde8377d11992924c74bf6dabb81081d0fc
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-06 17:02:59 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:34:53 +0000

    linux(4): Implement semtimedop syscalls.
    
    On i386 are two semtimedop. The old one is called via multiplexor and
    uses 32-bit timespec, and new semtimedop_tim64, which is uses 64-bit
    timespec.
    
    MFC after:              2 weeks
    
    (cherry picked from commit 3245a2ecea21ace3d97cec1266fbe29c88ba1a59)
---
 sys/amd64/linux/linux_dummy_machdep.c     |  1 -
 sys/amd64/linux32/linux32_dummy_machdep.c |  1 -
 sys/amd64/linux32/linux32_machdep.c       |  9 +++++++
 sys/arm64/linux/linux_dummy_machdep.c     |  1 -
 sys/compat/linux/linux_ipc.c              | 45 +++++++++++++++++++++++++++++++
 sys/compat/linux/linux_ipc.h              | 13 +++++++++
 sys/i386/linux/linux_dummy_machdep.c      |  1 -
 sys/i386/linux/linux_machdep.c            |  9 +++++++
 8 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/sys/amd64/linux/linux_dummy_machdep.c b/sys/amd64/linux/linux_dummy_machdep.c
index 4e4d0f9c0d8b..3ce407af291c 100644
--- a/sys/amd64/linux/linux_dummy_machdep.c
+++ b/sys/amd64/linux/linux_dummy_machdep.c
@@ -68,6 +68,5 @@ DUMMY(mq_notify);
 DUMMY(mq_getsetattr);
 DUMMY(readahead);
 DUMMY(restart_syscall);
-DUMMY(semtimedop);
 /* Linux 3.15: */
 DUMMY(kexec_file_load);
diff --git a/sys/amd64/linux32/linux32_dummy_machdep.c b/sys/amd64/linux32/linux32_dummy_machdep.c
index a5c61e252f9d..f3bd8717524a 100644
--- a/sys/amd64/linux32/linux32_dummy_machdep.c
+++ b/sys/amd64/linux32/linux32_dummy_machdep.c
@@ -71,4 +71,3 @@ DUMMY(clock_adjtime64);
 DUMMY(io_pgetevents_time64);
 DUMMY(mq_timedsend_time64);
 DUMMY(mq_timedreceive_time64);
-DUMMY(semtimedop_time64);
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index baa567339689..e1d7742d0a21 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -279,6 +279,15 @@ linux_ipc(struct thread *td, struct linux_ipc_args *args)
 			return (error);
 		return (linux_semctl(td, &a));
 	}
+	case LINUX_SEMTIMEDOP: {
+		struct linux_semtimedop_args a;
+
+		a.semid = args->arg1;
+		a.tsops = PTRIN(args->ptr);
+		a.nsops = args->arg2;
+		a.timeout = PTRIN(args->arg5);
+		return (linux_semtimedop(td, &a));
+	}
 	case LINUX_MSGSND: {
 		struct linux_msgsnd_args a;
 
diff --git a/sys/arm64/linux/linux_dummy_machdep.c b/sys/arm64/linux/linux_dummy_machdep.c
index 0b722c632709..22ad39a84eeb 100644
--- a/sys/arm64/linux/linux_dummy_machdep.c
+++ b/sys/arm64/linux/linux_dummy_machdep.c
@@ -59,5 +59,4 @@ DUMMY(mq_timedsend);
 DUMMY(mq_timedreceive);
 DUMMY(mq_notify);
 DUMMY(mq_getsetattr);
-DUMMY(semtimedop);
 DUMMY(kexec_file_load);
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
index 3e810c303a2c..51bf18dcd097 100644
--- a/sys/compat/linux/linux_ipc.c
+++ b/sys/compat/linux/linux_ipc.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #endif
 #include <compat/linux/linux_ipc.h>
 #include <compat/linux/linux_ipc64.h>
+#include <compat/linux/linux_timer.h>
 #include <compat/linux/linux_util.h>
 
 /*
@@ -504,6 +505,50 @@ linux_shminfo_pushdown(l_int ver, struct l_shminfo64 *linux_shminfo64,
 	}
 }
 
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+int
+linux_semtimedop_time64(struct thread *td, struct linux_semtimedop_time64_args *args)
+{
+	struct timespec ts, *tsa;
+	struct l_timespec64 lts;
+	int error;
+
+	if (args->timeout) {
+		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
+			return (error);
+		error = linux_to_native_timespec64(&ts, &lts);
+		if (error != 0)
+			return (error);
+		tsa = &ts;
+	} else
+		tsa = NULL;
+
+	return (kern_semop(td, args->semid, PTRIN(args->tsops),
+	    args->nsops, tsa));
+}
+#endif /* __i386__) || (__amd64__ && COMPAT_LINUX32) */
+
+int
+linux_semtimedop(struct thread *td, struct linux_semtimedop_args *args)
+{
+	struct timespec ts, *tsa;
+	struct l_timespec lts;
+	int error;
+
+	if (args->timeout) {
+		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
+			return (error);
+		error = linux_to_native_timespec(&ts, &lts);
+		if (error != 0)
+			return (error);
+		tsa = &ts;
+	} else
+		tsa = NULL;
+
+	return (kern_semop(td, args->semid, PTRIN(args->tsops),
+	    args->nsops, tsa));
+}
+
 int
 linux_semget(struct thread *td, struct linux_semget_args *args)
 {
diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h
index beef18a09507..a148814b8273 100644
--- a/sys/compat/linux/linux_ipc.h
+++ b/sys/compat/linux/linux_ipc.h
@@ -37,6 +37,7 @@
 #define	LINUX_SEMOP		1
 #define	LINUX_SEMGET		2
 #define	LINUX_SEMCTL		3
+#define	LINUX_SEMTIMEDOP	4
 #define	LINUX_MSGSND		11
 #define	LINUX_MSGRCV		12
 #define	LINUX_MSGGET		13
@@ -82,4 +83,16 @@
 #define	LINUX_IPC_64	0x0100	/* New version (support 32-bit UIDs, bigger
 				   message sizes, etc. */
 
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+struct linux_semtimedop_args
+{
+	l_int		semid;
+	struct sembuf	*tsops;
+	l_uint		nsops;
+	struct l_timespec *timeout;
+};
+
+int linux_semtimedop(struct thread *, struct linux_semtimedop_args *);
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+
 #endif /* _LINUX_IPC_H_ */
diff --git a/sys/i386/linux/linux_dummy_machdep.c b/sys/i386/linux/linux_dummy_machdep.c
index dd89444537d0..0e41a4b3fc56 100644
--- a/sys/i386/linux/linux_dummy_machdep.c
+++ b/sys/i386/linux/linux_dummy_machdep.c
@@ -73,4 +73,3 @@ DUMMY(clock_adjtime64);
 DUMMY(io_pgetevents_time64);
 DUMMY(mq_timedsend_time64);
 DUMMY(mq_timedreceive_time64);
-DUMMY(semtimedop_time64);
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index 09d4eb42c772..1e665eb9f505 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -154,6 +154,15 @@ linux_ipc(struct thread *td, struct linux_ipc_args *args)
 			return (error);
 		return (linux_semctl(td, &a));
 	}
+	case LINUX_SEMTIMEDOP: {
+		struct linux_semtimedop_args a;
+
+		a.semid = args->arg1;
+		a.tsops = PTRIN(args->ptr);
+		a.nsops = args->arg2;
+		a.timeout = PTRIN(args->arg5);
+		return (linux_semtimedop(td, &a));
+	}
 	case LINUX_MSGSND: {
 		struct linux_msgsnd_args a;