From 889237d6fbdcc92f94cc6f8612b665b93f6bc51c Mon Sep 17 00:00:00 2001 From: shaojinchun Date: Thu, 24 Dec 2020 11:49:28 +0800 Subject: [PATCH] =?UTF-8?q?syscall=E5=AF=B9=E6=8E=A5signal=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/lwp/lwp_signal.c | 143 ++++++++++++++++++++++++++++++---- components/lwp/lwp_signal.h | 5 +- components/lwp/lwp_syscall.c | 145 +++++++++++++++++++++++++++++++++-- include/rtdef.h | 10 +++ 4 files changed, 281 insertions(+), 22 deletions(-) diff --git a/components/lwp/lwp_signal.c b/components/lwp/lwp_signal.c index 3c7f0d0195..6b62f48bfa 100644 --- a/components/lwp/lwp_signal.c +++ b/components/lwp/lwp_signal.c @@ -171,7 +171,7 @@ int lwp_signal_check(void) goto out; } - lwp = thread->lwp; + lwp = (struct rt_lwp*)thread->lwp; if (lwp->signal_in_process) { @@ -217,7 +217,7 @@ int lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag) } else { - lwp = thread->lwp; + lwp = (struct rt_lwp*)thread->lwp; lwp->user_ctx.sp = user_sp; lwp->user_ctx.pc = user_pc; lwp->user_ctx.flag = user_flag; @@ -251,7 +251,7 @@ struct rt_user_context *lwp_signal_restore(void) } else { - lwp = thread->lwp; + lwp = (struct rt_lwp*)thread->lwp; ctx = &lwp->user_ctx; RT_ASSERT(lwp->signal_in_process != 0); lwp->signal_in_process = 0; @@ -341,17 +341,93 @@ void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func) rt_hw_interrupt_enable(level); } -int lwp_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset) +int lwp_sigaction(int sig, const struct lwp_sigaction *act, + struct lwp_sigaction *oact, size_t sigsetsize) +{ + rt_base_t level; + struct rt_lwp *lwp; + int ret = -RT_EINVAL; + lwp_sigset_t newset; + + level = rt_hw_interrupt_disable(); + lwp = (struct rt_lwp*)rt_thread_self()->lwp; + if (!lwp) + { + goto out; + } + if (sigsetsize != sizeof(lwp_sigset_t)) + { + goto out; + } + if (!act && !oact) + { + goto out; + } + if (oact) + { + oact->sa_mask = lwp->signal_mask; + oact->sa_flags = 0; + oact->sa_restorer = RT_NULL; + oact->__sa_handler._sa_handler = lwp->signal_handler[sig - 1]; + } + if (act) + { + newset = act->sa_mask; + lwp_sigdelset(&newset, SIGKILL); + lwp_sigdelset(&newset, SIGSTOP); + lwp->signal_mask = newset; + lwp_sighandler_set(sig, act->__sa_handler._sa_handler); + } + ret = 0; +out: + rt_hw_interrupt_enable(level); + return ret; +} + +rt_inline void sigorsets(lwp_sigset_t *dset, const lwp_sigset_t *set0, const lwp_sigset_t *set1) +{ + switch (_LWP_NSIG_WORDS) + { + case 4: + dset->sig[3] = set0->sig[3] | set1->sig[3]; + dset->sig[2] = set0->sig[2] | set1->sig[2]; + case 2: + dset->sig[1] = set0->sig[1] | set1->sig[1]; + case 1: + dset->sig[0] = set0->sig[0] | set1->sig[0]; + default: + return; + } +} + +rt_inline void sigandsets(lwp_sigset_t *dset, const lwp_sigset_t *set0, const lwp_sigset_t *set1) +{ + switch (_LWP_NSIG_WORDS) + { + case 4: + dset->sig[3] = set0->sig[3] & set1->sig[3]; + dset->sig[2] = set0->sig[2] & set1->sig[2]; + case 2: + dset->sig[1] = set0->sig[1] & set1->sig[1]; + case 1: + dset->sig[0] = set0->sig[0] & set1->sig[0]; + default: + return; + } +} + +int lwp_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset) { int ret = -1; rt_base_t level; struct rt_lwp *lwp; struct rt_thread *thread; + lwp_sigset_t newset; level = rt_hw_interrupt_disable(); thread = rt_thread_self(); - lwp = thread->lwp; + lwp = (struct rt_lwp*)thread->lwp; if (!lwp) { goto out; @@ -360,20 +436,41 @@ int lwp_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset) { rt_memcpy(oset, &lwp->signal_mask, sizeof(lwp_sigset_t)); } - rt_memcpy(&lwp->signal_mask, sigset, sizeof(lwp_sigset_t)); - lwp_sigdelset(&lwp->signal_mask, SIGKILL); - lwp_sigdelset(&lwp->signal_mask, SIGSTOP); - ret = 0; + if (sigset) + { + switch (how) + { + case SIG_BLOCK: + sigorsets(&newset, &lwp->signal_mask, sigset); + break; + case SIG_UNBLOCK: + sigandsets(&newset, &lwp->signal_mask, sigset); + break; + case SIG_SETMASK: + newset = *sigset; + break; + default: + ret = RT_EINVAL; + goto out; + } + + lwp_sigdelset(&newset, SIGKILL); + lwp_sigdelset(&newset, SIGSTOP); + + lwp->signal_mask = newset; + } + ret = 0; out: rt_hw_interrupt_enable(level); return ret; } -int lwp_thread_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset) +int lwp_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset) { rt_base_t level; struct rt_thread *thread; + lwp_sigset_t newset; level = rt_hw_interrupt_disable(); thread = rt_thread_self(); @@ -382,10 +479,30 @@ int lwp_thread_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset) { rt_memcpy(oset, &thread->signal_mask, sizeof(lwp_sigset_t)); } - rt_memcpy(&thread->signal_mask, sigset, sizeof(lwp_sigset_t)); - lwp_sigdelset(&thread->signal_mask, SIGKILL); - lwp_sigdelset(&thread->signal_mask, SIGSTOP); + if (sigset) + { + switch (how) + { + case SIG_BLOCK: + sigorsets(&newset, &thread->signal_mask, sigset); + break; + case SIG_UNBLOCK: + sigandsets(&newset, &thread->signal_mask, sigset); + break; + case SIG_SETMASK: + newset = *sigset; + break; + default: + goto out; + } + + lwp_sigdelset(&newset, SIGKILL); + lwp_sigdelset(&newset, SIGSTOP); + + thread->signal_mask = newset; + } +out: rt_hw_interrupt_enable(level); return 0; } diff --git a/components/lwp/lwp_signal.h b/components/lwp/lwp_signal.h index 7e3118bb0e..27e24adbf3 100644 --- a/components/lwp/lwp_signal.h +++ b/components/lwp/lwp_signal.h @@ -22,9 +22,10 @@ int lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag); struct rt_user_context *lwp_signal_restore(void); lwp_sighandler_t lwp_sighandler_get(int sig); void lwp_sighandler_set(int sig, lwp_sighandler_t func); -int lwp_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset); +int lwp_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset); void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func); -int lwp_thread_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset); +int lwp_sigaction(int sig, const struct lwp_sigaction *act, struct lwp_sigaction * oact, size_t sigsetsize); +int lwp_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset); int lwp_kill(pid_t pid, int sig); int lwp_thread_kill(rt_thread_t thread, int sig); diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index a392698367..ed94062e60 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -1427,14 +1427,103 @@ rt_err_t sys_thread_mdelay(rt_int32_t ms) return rt_thread_mdelay(ms); } -void sys_sighandler_set(int sig, lwp_sighandler_t func) +int sys_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact, size_t sigsetsize) { - lwp_sighandler_set(sig, func); + int ret = -RT_EINVAL; + struct lwp_sigaction kact, *pkact = RT_NULL; + struct lwp_sigaction koact, *pkoact = RT_NULL; + + if (!sigsetsize) + { + goto out; + } + if (sigsetsize > sizeof(lwp_sigset_t)) + { + sigsetsize = sizeof(lwp_sigset_t); + goto out; + } + if (!act && !oact) + { + goto out; + } + if (oact) + { + if (!lwp_user_accessable((void*)oact, sigsetsize)) + { + goto out; + } + pkoact = &koact; + } + if (act) + { + if (!lwp_user_accessable((void*)act, sigsetsize)) + { + goto out; + } + kact.__sa_handler._sa_handler = act->sa_handler; + memcpy(&kact.sa_mask, &act->sa_mask, sigsetsize); + pkact = &kact; + } + + ret = lwp_sigaction(sig, pkact, pkoact, sigsetsize); + if (ret == 0) + { + lwp_put_to_user(&oact->sa_handler, &pkoact->__sa_handler._sa_handler, sizeof(void (*)(int))); + lwp_put_to_user(&oact->sa_mask, &pkoact->sa_mask, sigsetsize); + lwp_put_to_user(&oact->sa_flags, &pkoact->sa_flags, sizeof(int)); + lwp_put_to_user(&oact->sa_restorer, &pkoact->sa_restorer, sizeof(void (*)(void))); + } +out: + return ret; } -int sys_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset) +int sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t size) { - return lwp_sigprocmask(sigset, oset); + int ret = -1; + lwp_sigset_t newset, *pnewset = RT_NULL; + lwp_sigset_t oldset, *poldset = RT_NULL; + + if (!size) + { + return ret; + } + if (!oset && !sigset) + { + return ret; + } + if (size > sizeof(lwp_sigset_t)) + { + size = sizeof(lwp_sigset_t); + return ret; + } + if (oset) + { + if (!lwp_user_accessable((void*)oset, size)) + { + return ret; + } + poldset = &oldset; + } + if (sigset) + { + if (!lwp_user_accessable((void*)oset, size)) + { + return ret; + } + lwp_get_from_user(&newset, (void*)sigset, size); + pnewset = &newset; + } + ret = lwp_sigprocmask(how, pnewset, poldset); + if (ret < 0) + { + return ret; + } + if (oset) + { + lwp_put_to_user(oset, poldset, size); + } + return ret; } int sys_thread_kill(rt_thread_t thread, int sig) @@ -1447,9 +1536,51 @@ void sys_thread_sighandler_set(int sig, lwp_sighandler_t func) lwp_thread_sighandler_set(sig, func); } -int sys_thread_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset) +int sys_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset, size_t size) { - return lwp_thread_sigprocmask(sigset, oset); + int ret = -1; + lwp_sigset_t newset, *pnewset = RT_NULL; + lwp_sigset_t oldset, *poldset = RT_NULL; + + if (!size) + { + return ret; + } + if (!oset && !sigset) + { + return ret; + } + if (size != sizeof(lwp_sigset_t)) + { + return ret; + } + if (oset) + { + if (!lwp_user_accessable((void*)oset, size)) + { + return ret; + } + poldset = &oldset; + } + if (sigset) + { + if (!lwp_user_accessable((void*)oset, size)) + { + return ret; + } + lwp_get_from_user(&newset, (void*)sigset, sizeof(lwp_sigset_t)); + pnewset = &newset; + } + ret = lwp_thread_sigprocmask(how, pnewset, poldset); + if (ret < 0) + { + return ret; + } + if (oset) + { + lwp_put_to_user(oset, poldset, sizeof(lwp_sigset_t)); + } + return ret; } int32_t sys_waitpid(int32_t pid, int *status, int options) @@ -1866,7 +1997,7 @@ const static void* func_table[] = (void *)sys_notimpl, //(void *)rt_work_submit, (void *)sys_notimpl, //(void *)rt_wqueue_wakeup, (void *)sys_thread_mdelay, - (void*)sys_sighandler_set, + (void*)sys_sigaction, (void*)sys_sigprocmask, (void*)sys_thread_kill, (void*)sys_thread_sighandler_set, diff --git a/include/rtdef.h b/include/rtdef.h index efc8634e8c..542a586ee1 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -609,6 +609,16 @@ typedef struct { unsigned long sig[_LWP_NSIG_WORDS]; } lwp_sigset_t; +struct lwp_sigaction { + union { + void (*_sa_handler)(int); + void (*_sa_sigaction)(int, siginfo_t *, void *); + } __sa_handler; + lwp_sigset_t sa_mask; + int sa_flags; + void (*sa_restorer)(void); +}; + struct rt_user_context { void *sp; -- Gitee