From: Eric Gao <eric.tech@foxmail.com> To: catalin.marinas@arm.com, will@kernel.org, geert@linux-m68k.org, monstr@monstr.eu, tsbogend@alpha.franken.de, James.Bottomley@HansenPartnership.com, deller@gmx.de, mpe@ellerman.id.au, hca@linux.ibm.com, gor@linux.ibm.com, borntraeger@de.ibm.com, ysato@users.sourceforge.jp, dalias@libc.org, davem@davemloft.net, luto@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, chris@zankel.net, jcmvbkbc@gmail.com, arnd@arndb.de, benh@kernel.crashing.org, paulus@samba.org, hpa@zytor.com, eric.tech@foxmail.com Cc: linux-arch@vger.kernel.org, linux-api@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-alpha@vger.kernel.org Subject: [PATCH] ipc/msg: add msgsnd_timed and msgrcv_timed syscall for system V message queue Date: Sat, 27 Feb 2021 14:52:02 +0800 [thread overview] Message-ID: <tencent_30362DDFFEE04E6CDACB6F803734A8DC7B06@qq.com> (raw) sometimes, we need the msgsnd or msgrcv syscall can return after a limited time, so that the business thread do not be blocked here all the time. In this case, I add the msgsnd_timed and msgrcv_timed syscall that with time parameter, which has a unit of ms. Signed-off-by: Eric Gao <eric.tech@foxmail.com> --- arch/alpha/kernel/syscalls/syscall.tbl | 2 + arch/arm/tools/syscall.tbl | 2 + arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/include/asm/unistd32.h | 4 ++ arch/ia64/kernel/syscalls/syscall.tbl | 2 + arch/m68k/kernel/syscalls/syscall.tbl | 2 + arch/microblaze/kernel/syscalls/syscall.tbl | 2 + arch/mips/kernel/syscalls/syscall_n32.tbl | 2 + arch/mips/kernel/syscalls/syscall_n64.tbl | 2 + arch/mips/kernel/syscalls/syscall_o32.tbl | 2 + arch/parisc/kernel/syscalls/syscall.tbl | 2 + arch/powerpc/kernel/syscalls/syscall.tbl | 2 + arch/s390/kernel/syscalls/syscall.tbl | 2 + arch/sh/kernel/syscalls/syscall.tbl | 2 + arch/sparc/kernel/syscalls/syscall.tbl | 2 + arch/x86/entry/syscalls/syscall_32.tbl | 2 + arch/x86/entry/syscalls/syscall_64.tbl | 2 + arch/xtensa/kernel/syscalls/syscall.tbl | 2 + include/linux/compat.h | 4 ++ include/linux/syscalls.h | 4 ++ include/uapi/asm-generic/unistd.h | 6 +- ipc/msg.c | 87 ++++++++++++++++++++++++++--- kernel/sys_ni.c | 4 ++ 23 files changed, 133 insertions(+), 10 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 02f0244..eed8cc6 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -482,3 +482,5 @@ 550 common process_madvise sys_process_madvise 551 common epoll_pwait2 sys_epoll_pwait2 552 common mount_setattr sys_mount_setattr +553 common msgrcv_timed sys_msgrcv_timed +554 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index dcc1191..c16baa6 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -456,3 +456,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 949788f..64ebdc1e 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -38,7 +38,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 443 +#define __NR_compat_syscalls 445 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 3d874f6..705676a 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -893,6 +893,10 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise) __SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2) #define __NR_mount_setattr 442 __SYSCALL(__NR_mount_setattr, sys_mount_setattr) +#define __NR_msgrcv_timed 443 +__SYSCALL(__NR_msgrcv_timed, sys_msgrcv_timed) +#define __NR_msgsnd_timed 444 +__SYSCALL(__NR_msgsnd_timed, sys_msgsnd_timed) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index d892311..ad57e6d 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -363,3 +363,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index 72bde67..1d33825 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -442,3 +442,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index d603a5e..38d7f7a 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -448,3 +448,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 8fd8c17..42b7db5 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -381,3 +381,5 @@ 440 n32 process_madvise sys_process_madvise 441 n32 epoll_pwait2 compat_sys_epoll_pwait2 442 n32 mount_setattr sys_mount_setattr +443 n32 msgrcv_timed sys_msgrcv_timed +444 n32 msgsnd_timed sys_msgsnd_timed diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index 169f214..060208b 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -357,3 +357,5 @@ 440 n64 process_madvise sys_process_madvise 441 n64 epoll_pwait2 sys_epoll_pwait2 442 n64 mount_setattr sys_mount_setattr +443 n64 msgrcv_timed sys_msgrcv_timed +444 n64 msgsnd_timed sys_msgsnd_timed diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 090d29c..0f1f6ee 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -430,3 +430,5 @@ 440 o32 process_madvise sys_process_madvise 441 o32 epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 o32 mount_setattr sys_mount_setattr +443 o32 msgrcv_timed sys_msgrcv_timed +444 o32 msgsnd_timed sys_msgsnd_timed diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 271a925..fef5544 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -440,3 +440,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 0b2480c..115217c 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -522,3 +522,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 3abef21..863b992 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -445,3 +445,5 @@ 440 common process_madvise sys_process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index d08eeba..24245c0 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -445,3 +445,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index 84403a9..d35e062 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -488,3 +488,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index a1c9f496f..6adc251 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -447,3 +447,5 @@ 440 i386 process_madvise sys_process_madvise 441 i386 epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 i386 mount_setattr sys_mount_setattr +443 i386 msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 i386 msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 7bf01cb..44e4c63 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -364,6 +364,8 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 365a9b8..12bdd62 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -413,3 +413,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/include/linux/compat.h b/include/linux/compat.h index 6e65be7..e2fd2ac 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -743,6 +743,10 @@ asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg); asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, int msgflg); +asmlinkage long compat_sys_msgrcv_timed(int msqid, compat_uptr_t msgp, + compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg, compat_long_t timeoutms); +asmlinkage long compat_sys_msgsnd_timed(int msqid, compat_uptr_t msgp, + compat_ssize_t msgsz, int msgflg, compat_long_t timeoutms); /* ipc/sem.c */ asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 2839dc9..369cc19 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -808,6 +808,10 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg); asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg); +asmlinkage long sys_msgrcv_timed(int msqid, struct msgbuf __user *msgp, + size_t msgsz, long msgtyp, int msgflg, long timeoutms); +asmlinkage long sys_msgsnd_timed(int msqid, struct msgbuf __user *msgp, + size_t msgsz, int msgflg, long timeoutms); /* ipc/sem.c */ asmlinkage long sys_semget(key_t key, int nsems, int semflg); diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index ce58cff..ef3cfad 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -561,6 +561,10 @@ __SC_COMP(__NR_msgctl, sys_msgctl, compat_sys_msgctl) __SC_COMP(__NR_msgrcv, sys_msgrcv, compat_sys_msgrcv) #define __NR_msgsnd 189 __SC_COMP(__NR_msgsnd, sys_msgsnd, compat_sys_msgsnd) +#define __NR_msgrcv_timed 443 +__SC_COMP(__NR_msgrcv_timed, sys_msgrcv_timed, compat_sys_msgrcv_timed) +#define __NR_msgsnd_timed 444 +__SC_COMP(__NR_msgsnd_timed, sys_msgsnd_timed, compat_sys_msgsnd_timed) /* ipc/sem.c */ #define __NR_semget 190 @@ -865,7 +869,7 @@ __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) __SYSCALL(__NR_mount_setattr, sys_mount_setattr) #undef __NR_syscalls -#define __NR_syscalls 443 +#define __NR_syscalls 445 /* * 32 bit systems traditionally used different diff --git a/ipc/msg.c b/ipc/msg.c index acd1bc7..88167c0 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -838,13 +838,14 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg, } static long do_msgsnd(int msqid, long mtype, void __user *mtext, - size_t msgsz, int msgflg) + size_t msgsz, int msgflg, long timeoutms) { struct msg_queue *msq; struct msg_msg *msg; int err; struct ipc_namespace *ns; DEFINE_WAKE_Q(wake_q); + bool timeoutflag = false; ns = current->nsproxy->ipc_ns; @@ -905,7 +906,15 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, ipc_unlock_object(&msq->q_perm); rcu_read_unlock(); - schedule(); + + /* sometimes, we need msgsnd syscall return after a given time */ + if (timeoutms <= 0) { + schedule(); + } else { + timeoutms = schedule_timeout(timeoutms); + if (timeoutms == 0) + timeoutflag = true; + } rcu_read_lock(); ipc_lock_object(&msq->q_perm); @@ -918,6 +927,11 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, } ss_del(&s); + if (true == timeoutflag) { + err = -ETIME; + goto out_unlock0; + } + if (signal_pending(current)) { err = -ERESTARTNOHAND; goto out_unlock0; @@ -957,7 +971,7 @@ long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, if (get_user(mtype, &msgp->mtype)) return -EFAULT; - return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); + return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg, 0); } SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, @@ -966,6 +980,18 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, return ksys_msgsnd(msqid, msgp, msgsz, msgflg); } +SYSCALL_DEFINE5(msgsnd_timed, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, + int, msgflg, long, timeoutms) +{ + long mtype; + + timeoutms = (timeoutms + 9) / 10; + + if (get_user(mtype, &msgp->mtype)) + return -EFAULT; + return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg, timeoutms); +} + #ifdef CONFIG_COMPAT struct compat_msgbuf { @@ -981,7 +1007,7 @@ long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp, if (get_user(mtype, &up->mtype)) return -EFAULT; - return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg); + return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg, 0); } COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, @@ -989,6 +1015,20 @@ COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, { return compat_ksys_msgsnd(msqid, msgp, msgsz, msgflg); } + +COMPAT_SYSCALL_DEFINE5(msgsnd_timed, int, msqid, compat_uptr_t, msgp, + compat_ssize_t, msgsz, int, msgflg, compat_long_t, timeoutms) +{ + struct compat_msgbuf __user *up = compat_ptr(msgp); + compat_long_t mtype; + + timeoutms = (timeoutms + 9) / 10; + + if (get_user(mtype, &up->mtype)) + return -EFAULT; + + return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg, (long)timeoutms); +} #endif static inline int convert_mode(long *msgtyp, int msgflg) @@ -1088,13 +1128,14 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) } static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, - long (*msg_handler)(void __user *, struct msg_msg *, size_t)) + long (*msg_handler)(void __user *, struct msg_msg *, size_t), long timeoutms) { int mode; struct msg_queue *msq; struct ipc_namespace *ns; struct msg_msg *msg, *copy = NULL; DEFINE_WAKE_Q(wake_q); + bool timeoutflag = false; ns = current->nsproxy->ipc_ns; @@ -1187,7 +1228,15 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in ipc_unlock_object(&msq->q_perm); rcu_read_unlock(); - schedule(); + + /* sometimes, we need msgrcv syscall return after a given time */ + if (timeoutms <= 0) { + schedule(); + } else { + timeoutms = schedule_timeout(timeoutms); + if (timeoutms == 0) + timeoutflag = true; + } /* * Lockless receive, part 1: @@ -1229,6 +1278,12 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in goto out_unlock0; list_del(&msr_d.r_list); + + if (true == timeoutflag) { + msg = ERR_PTR(-ETIME); + goto out_unlock0; + } + if (signal_pending(current)) { msg = ERR_PTR(-ERESTARTNOHAND); goto out_unlock0; @@ -1256,7 +1311,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg) { - return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill, 0); } SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, @@ -1265,6 +1320,13 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, return ksys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); } +SYSCALL_DEFINE6(msgrcv_timed, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, + long, msgtyp, int, msgflg, long, timeoutms) +{ + timeoutms = (timeoutms + 9) / 10; + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill, timeoutms); +} + #ifdef CONFIG_COMPAT static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) { @@ -1284,7 +1346,7 @@ long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg) { return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp, - msgflg, compat_do_msg_fill); + msgflg, compat_do_msg_fill, 0); } COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, @@ -1293,6 +1355,15 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, { return compat_ksys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); } + +COMPAT_SYSCALL_DEFINE6(msgrcv_timed, int, msqid, compat_uptr_t, msgp, + compat_ssize_t, msgsz, compat_long_t, msgtyp, + int, msgflg, compat_long_t, timeoutms) +{ + timeoutms = (timeoutms + 9) / 10; + return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp, + msgflg, compat_do_msg_fill, (long)timeoutms); +} #endif void msg_init_ns(struct ipc_namespace *ns) diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 19aa8068..783a1de 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -212,6 +212,10 @@ COND_SYSCALL(msgrcv); COND_SYSCALL_COMPAT(msgrcv); COND_SYSCALL(msgsnd); COND_SYSCALL_COMPAT(msgsnd); +COND_SYSCALL(msgrcv_timed); +COND_SYSCALL_COMPAT(msgrcv_timed); +COND_SYSCALL(msgsnd_timed); +COND_SYSCALL_COMPAT(msgsnd_timed); /* ipc/sem.c */ COND_SYSCALL(semget); -- 2.7.4 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Eric Gao <eric.tech@foxmail.com> To: catalin.marinas@arm.com, will@kernel.org, geert@linux-m68k.org, monstr@monstr.eu, tsbogend@alpha.franken.de, James.Bottomley@HansenPartnership.com, deller@gmx.de, mpe@ellerman.id.au, hca@linux.ibm.com, gor@linux.ibm.com, borntraeger@de.ibm.com, ysato@users.sourceforge.jp, dalias@libc.org, davem@davemloft.net, luto@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, chris@zankel.net, jcmvbkbc@gmail.com, arnd@arndb.de, benh@kernel.crashing.org, paulus@samba.org, hpa@zytor.com, eric.tech@foxmail.com Cc: linux-arch@vger.kernel.org, linux-api@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-alpha@vger.kernel.org Subject: [PATCH] ipc/msg: add msgsnd_timed and msgrcv_timed syscall for system V message queue Date: Sat, 27 Feb 2021 14:52:02 +0800 [thread overview] Message-ID: <tencent_30362DDFFEE04E6CDACB6F803734A8DC7B06@qq.com> (raw) sometimes, we need the msgsnd or msgrcv syscall can return after a limited time, so that the business thread do not be blocked here all the time. In this case, I add the msgsnd_timed and msgrcv_timed syscall that with time parameter, which has a unit of ms. Signed-off-by: Eric Gao <eric.tech@foxmail.com> --- arch/alpha/kernel/syscalls/syscall.tbl | 2 + arch/arm/tools/syscall.tbl | 2 + arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/include/asm/unistd32.h | 4 ++ arch/ia64/kernel/syscalls/syscall.tbl | 2 + arch/m68k/kernel/syscalls/syscall.tbl | 2 + arch/microblaze/kernel/syscalls/syscall.tbl | 2 + arch/mips/kernel/syscalls/syscall_n32.tbl | 2 + arch/mips/kernel/syscalls/syscall_n64.tbl | 2 + arch/mips/kernel/syscalls/syscall_o32.tbl | 2 + arch/parisc/kernel/syscalls/syscall.tbl | 2 + arch/powerpc/kernel/syscalls/syscall.tbl | 2 + arch/s390/kernel/syscalls/syscall.tbl | 2 + arch/sh/kernel/syscalls/syscall.tbl | 2 + arch/sparc/kernel/syscalls/syscall.tbl | 2 + arch/x86/entry/syscalls/syscall_32.tbl | 2 + arch/x86/entry/syscalls/syscall_64.tbl | 2 + arch/xtensa/kernel/syscalls/syscall.tbl | 2 + include/linux/compat.h | 4 ++ include/linux/syscalls.h | 4 ++ include/uapi/asm-generic/unistd.h | 6 +- ipc/msg.c | 87 ++++++++++++++++++++++++++--- kernel/sys_ni.c | 4 ++ 23 files changed, 133 insertions(+), 10 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 02f0244..eed8cc6 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -482,3 +482,5 @@ 550 common process_madvise sys_process_madvise 551 common epoll_pwait2 sys_epoll_pwait2 552 common mount_setattr sys_mount_setattr +553 common msgrcv_timed sys_msgrcv_timed +554 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index dcc1191..c16baa6 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -456,3 +456,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 949788f..64ebdc1e 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -38,7 +38,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 443 +#define __NR_compat_syscalls 445 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 3d874f6..705676a 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -893,6 +893,10 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise) __SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2) #define __NR_mount_setattr 442 __SYSCALL(__NR_mount_setattr, sys_mount_setattr) +#define __NR_msgrcv_timed 443 +__SYSCALL(__NR_msgrcv_timed, sys_msgrcv_timed) +#define __NR_msgsnd_timed 444 +__SYSCALL(__NR_msgsnd_timed, sys_msgsnd_timed) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index d892311..ad57e6d 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -363,3 +363,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index 72bde67..1d33825 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -442,3 +442,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index d603a5e..38d7f7a 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -448,3 +448,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index 8fd8c17..42b7db5 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -381,3 +381,5 @@ 440 n32 process_madvise sys_process_madvise 441 n32 epoll_pwait2 compat_sys_epoll_pwait2 442 n32 mount_setattr sys_mount_setattr +443 n32 msgrcv_timed sys_msgrcv_timed +444 n32 msgsnd_timed sys_msgsnd_timed diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index 169f214..060208b 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -357,3 +357,5 @@ 440 n64 process_madvise sys_process_madvise 441 n64 epoll_pwait2 sys_epoll_pwait2 442 n64 mount_setattr sys_mount_setattr +443 n64 msgrcv_timed sys_msgrcv_timed +444 n64 msgsnd_timed sys_msgsnd_timed diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 090d29c..0f1f6ee 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -430,3 +430,5 @@ 440 o32 process_madvise sys_process_madvise 441 o32 epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 o32 mount_setattr sys_mount_setattr +443 o32 msgrcv_timed sys_msgrcv_timed +444 o32 msgsnd_timed sys_msgsnd_timed diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 271a925..fef5544 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -440,3 +440,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 0b2480c..115217c 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -522,3 +522,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index 3abef21..863b992 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -445,3 +445,5 @@ 440 common process_madvise sys_process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index d08eeba..24245c0 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -445,3 +445,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index 84403a9..d35e062 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -488,3 +488,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index a1c9f496f..6adc251 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -447,3 +447,5 @@ 440 i386 process_madvise sys_process_madvise 441 i386 epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 442 i386 mount_setattr sys_mount_setattr +443 i386 msgrcv_timed sys_msgrcv_timed compat_sys_msgrcv_timed +444 i386 msgsnd_timed sys_msgsnd_timed compat_sys_msgsnd_timed diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 7bf01cb..44e4c63 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -364,6 +364,8 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 365a9b8..12bdd62 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -413,3 +413,5 @@ 440 common process_madvise sys_process_madvise 441 common epoll_pwait2 sys_epoll_pwait2 442 common mount_setattr sys_mount_setattr +443 common msgrcv_timed sys_msgrcv_timed +444 common msgsnd_timed sys_msgsnd_timed diff --git a/include/linux/compat.h b/include/linux/compat.h index 6e65be7..e2fd2ac 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -743,6 +743,10 @@ asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg); asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, int msgflg); +asmlinkage long compat_sys_msgrcv_timed(int msqid, compat_uptr_t msgp, + compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg, compat_long_t timeoutms); +asmlinkage long compat_sys_msgsnd_timed(int msqid, compat_uptr_t msgp, + compat_ssize_t msgsz, int msgflg, compat_long_t timeoutms); /* ipc/sem.c */ asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 2839dc9..369cc19 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -808,6 +808,10 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg); asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg); +asmlinkage long sys_msgrcv_timed(int msqid, struct msgbuf __user *msgp, + size_t msgsz, long msgtyp, int msgflg, long timeoutms); +asmlinkage long sys_msgsnd_timed(int msqid, struct msgbuf __user *msgp, + size_t msgsz, int msgflg, long timeoutms); /* ipc/sem.c */ asmlinkage long sys_semget(key_t key, int nsems, int semflg); diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index ce58cff..ef3cfad 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -561,6 +561,10 @@ __SC_COMP(__NR_msgctl, sys_msgctl, compat_sys_msgctl) __SC_COMP(__NR_msgrcv, sys_msgrcv, compat_sys_msgrcv) #define __NR_msgsnd 189 __SC_COMP(__NR_msgsnd, sys_msgsnd, compat_sys_msgsnd) +#define __NR_msgrcv_timed 443 +__SC_COMP(__NR_msgrcv_timed, sys_msgrcv_timed, compat_sys_msgrcv_timed) +#define __NR_msgsnd_timed 444 +__SC_COMP(__NR_msgsnd_timed, sys_msgsnd_timed, compat_sys_msgsnd_timed) /* ipc/sem.c */ #define __NR_semget 190 @@ -865,7 +869,7 @@ __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) __SYSCALL(__NR_mount_setattr, sys_mount_setattr) #undef __NR_syscalls -#define __NR_syscalls 443 +#define __NR_syscalls 445 /* * 32 bit systems traditionally used different diff --git a/ipc/msg.c b/ipc/msg.c index acd1bc7..88167c0 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -838,13 +838,14 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg, } static long do_msgsnd(int msqid, long mtype, void __user *mtext, - size_t msgsz, int msgflg) + size_t msgsz, int msgflg, long timeoutms) { struct msg_queue *msq; struct msg_msg *msg; int err; struct ipc_namespace *ns; DEFINE_WAKE_Q(wake_q); + bool timeoutflag = false; ns = current->nsproxy->ipc_ns; @@ -905,7 +906,15 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, ipc_unlock_object(&msq->q_perm); rcu_read_unlock(); - schedule(); + + /* sometimes, we need msgsnd syscall return after a given time */ + if (timeoutms <= 0) { + schedule(); + } else { + timeoutms = schedule_timeout(timeoutms); + if (timeoutms == 0) + timeoutflag = true; + } rcu_read_lock(); ipc_lock_object(&msq->q_perm); @@ -918,6 +927,11 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, } ss_del(&s); + if (true == timeoutflag) { + err = -ETIME; + goto out_unlock0; + } + if (signal_pending(current)) { err = -ERESTARTNOHAND; goto out_unlock0; @@ -957,7 +971,7 @@ long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, if (get_user(mtype, &msgp->mtype)) return -EFAULT; - return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); + return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg, 0); } SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, @@ -966,6 +980,18 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, return ksys_msgsnd(msqid, msgp, msgsz, msgflg); } +SYSCALL_DEFINE5(msgsnd_timed, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, + int, msgflg, long, timeoutms) +{ + long mtype; + + timeoutms = (timeoutms + 9) / 10; + + if (get_user(mtype, &msgp->mtype)) + return -EFAULT; + return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg, timeoutms); +} + #ifdef CONFIG_COMPAT struct compat_msgbuf { @@ -981,7 +1007,7 @@ long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp, if (get_user(mtype, &up->mtype)) return -EFAULT; - return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg); + return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg, 0); } COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, @@ -989,6 +1015,20 @@ COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, { return compat_ksys_msgsnd(msqid, msgp, msgsz, msgflg); } + +COMPAT_SYSCALL_DEFINE5(msgsnd_timed, int, msqid, compat_uptr_t, msgp, + compat_ssize_t, msgsz, int, msgflg, compat_long_t, timeoutms) +{ + struct compat_msgbuf __user *up = compat_ptr(msgp); + compat_long_t mtype; + + timeoutms = (timeoutms + 9) / 10; + + if (get_user(mtype, &up->mtype)) + return -EFAULT; + + return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg, (long)timeoutms); +} #endif static inline int convert_mode(long *msgtyp, int msgflg) @@ -1088,13 +1128,14 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) } static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, - long (*msg_handler)(void __user *, struct msg_msg *, size_t)) + long (*msg_handler)(void __user *, struct msg_msg *, size_t), long timeoutms) { int mode; struct msg_queue *msq; struct ipc_namespace *ns; struct msg_msg *msg, *copy = NULL; DEFINE_WAKE_Q(wake_q); + bool timeoutflag = false; ns = current->nsproxy->ipc_ns; @@ -1187,7 +1228,15 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in ipc_unlock_object(&msq->q_perm); rcu_read_unlock(); - schedule(); + + /* sometimes, we need msgrcv syscall return after a given time */ + if (timeoutms <= 0) { + schedule(); + } else { + timeoutms = schedule_timeout(timeoutms); + if (timeoutms == 0) + timeoutflag = true; + } /* * Lockless receive, part 1: @@ -1229,6 +1278,12 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in goto out_unlock0; list_del(&msr_d.r_list); + + if (true == timeoutflag) { + msg = ERR_PTR(-ETIME); + goto out_unlock0; + } + if (signal_pending(current)) { msg = ERR_PTR(-ERESTARTNOHAND); goto out_unlock0; @@ -1256,7 +1311,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg) { - return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill, 0); } SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, @@ -1265,6 +1320,13 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, return ksys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); } +SYSCALL_DEFINE6(msgrcv_timed, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, + long, msgtyp, int, msgflg, long, timeoutms) +{ + timeoutms = (timeoutms + 9) / 10; + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill, timeoutms); +} + #ifdef CONFIG_COMPAT static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) { @@ -1284,7 +1346,7 @@ long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg) { return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp, - msgflg, compat_do_msg_fill); + msgflg, compat_do_msg_fill, 0); } COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, @@ -1293,6 +1355,15 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, { return compat_ksys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); } + +COMPAT_SYSCALL_DEFINE6(msgrcv_timed, int, msqid, compat_uptr_t, msgp, + compat_ssize_t, msgsz, compat_long_t, msgtyp, + int, msgflg, compat_long_t, timeoutms) +{ + timeoutms = (timeoutms + 9) / 10; + return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp, + msgflg, compat_do_msg_fill, (long)timeoutms); +} #endif void msg_init_ns(struct ipc_namespace *ns) diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 19aa8068..783a1de 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -212,6 +212,10 @@ COND_SYSCALL(msgrcv); COND_SYSCALL_COMPAT(msgrcv); COND_SYSCALL(msgsnd); COND_SYSCALL_COMPAT(msgsnd); +COND_SYSCALL(msgrcv_timed); +COND_SYSCALL_COMPAT(msgrcv_timed); +COND_SYSCALL(msgsnd_timed); +COND_SYSCALL_COMPAT(msgsnd_timed); /* ipc/sem.c */ COND_SYSCALL(semget); -- 2.7.4
next reply other threads:[~2021-02-27 6:55 UTC|newest] Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-02-27 6:52 Eric Gao [this message] 2021-02-27 6:52 ` [PATCH] ipc/msg: add msgsnd_timed and msgrcv_timed syscall for system V message queue Eric Gao 2021-02-27 12:29 ` Arnd Bergmann 2021-02-27 12:29 ` Arnd Bergmann 2021-02-27 12:29 ` Arnd Bergmann [not found] <tencent_2CB9BD7D4063DE3F6845F79176B2D29A7E09@qq.com> 2021-02-28 15:38 ` Arnd Bergmann 2021-02-28 15:38 ` Arnd Bergmann 2021-02-28 15:38 ` Arnd Bergmann [not found] ` <tencent_2B7E37BD494059DF7D6845F641769CD28209@qq.com> 2021-02-28 19:49 ` Arnd Bergmann 2021-02-28 19:49 ` Arnd Bergmann 2021-02-28 19:49 ` Arnd Bergmann [not found] <tencent_E0772A5A82FD941DB0B488DF366F3F509F07@qq.com> 2021-03-04 1:12 ` Andrew Morton 2021-03-04 19:57 ` Manfred Spraul
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=tencent_30362DDFFEE04E6CDACB6F803734A8DC7B06@qq.com \ --to=eric.tech@foxmail.com \ --cc=James.Bottomley@HansenPartnership.com \ --cc=arnd@arndb.de \ --cc=benh@kernel.crashing.org \ --cc=borntraeger@de.ibm.com \ --cc=bp@alien8.de \ --cc=catalin.marinas@arm.com \ --cc=chris@zankel.net \ --cc=dalias@libc.org \ --cc=davem@davemloft.net \ --cc=deller@gmx.de \ --cc=geert@linux-m68k.org \ --cc=gor@linux.ibm.com \ --cc=hca@linux.ibm.com \ --cc=hpa@zytor.com \ --cc=jcmvbkbc@gmail.com \ --cc=linux-alpha@vger.kernel.org \ --cc=linux-api@vger.kernel.org \ --cc=linux-arch@vger.kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=luto@kernel.org \ --cc=mingo@redhat.com \ --cc=monstr@monstr.eu \ --cc=mpe@ellerman.id.au \ --cc=paulus@samba.org \ --cc=tglx@linutronix.de \ --cc=tsbogend@alpha.franken.de \ --cc=will@kernel.org \ --cc=ysato@users.sourceforge.jp \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.