From 3245a2ecea21ace3d97cec1266fbe29c88ba1a59 Mon Sep 17 00:00:00 2001 From: Dmitry Chagin Date: Fri, 6 May 2022 20:02:59 +0300 Subject: [PATCH] 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 --- 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 #include +#include #include /* @@ -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, <s, sizeof(lts)))) + return (error); + error = linux_to_native_timespec64(&ts, <s); + 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, <s, sizeof(lts)))) + return (error); + error = linux_to_native_timespec(&ts, <s); + 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;