From 4ce5f56ad6f4691563944243dcebe7149f6211c6 Mon Sep 17 00:00:00 2001 From: shell Date: Sun, 30 Jul 2023 18:40:28 +0800 Subject: [PATCH 1/2] [smart] Using exp frame to pass context Remove the previous implementation of context passing by variable Signed-off-by: Shell --- .../lwp/arch/aarch64/cortex-a/lwp_arch.c | 6 ---- .../lwp/arch/aarch64/cortex-a/lwp_arch.h | 1 - .../lwp/arch/aarch64/cortex-a/lwp_gcc.S | 32 +++++++++++++------ 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_arch.c b/components/lwp/arch/aarch64/cortex-a/lwp_arch.c index f2302514212..d4a4f7e64da 100644 --- a/components/lwp/arch/aarch64/cortex-a/lwp_arch.c +++ b/components/lwp/arch/aarch64/cortex-a/lwp_arch.c @@ -130,7 +130,6 @@ void *arch_signal_ucontext_restore(rt_base_t user_sp) void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo, struct rt_hw_exp_stack *exp_frame, - rt_base_t elr, rt_base_t spsr, lwp_sigset_t *save_sig_mask) { struct signal_ucontext *new_sp; @@ -147,11 +146,6 @@ void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo, /* exp frame is already aligned as AAPCS64 required */ memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame)); - /* fix the 3 fields in exception frame, so that memcpy will be fine */ - new_sp->frame.pc = elr; - new_sp->frame.cpsr = spsr; - new_sp->frame.sp_el0 = user_sp; - /* copy the save_sig_mask */ memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_arch.h b/components/lwp/arch/aarch64/cortex-a/lwp_arch.h index 46bbac5770f..f9faebfc916 100644 --- a/components/lwp/arch/aarch64/cortex-a/lwp_arch.h +++ b/components/lwp/arch/aarch64/cortex-a/lwp_arch.h @@ -48,7 +48,6 @@ rt_inline void icache_invalid_all(void) */ void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo, struct rt_hw_exp_stack *exp_frame, - rt_base_t elr, rt_base_t spsr, lwp_sigset_t *save_sig_mask); /** diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S b/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S index cf75bd24b33..541c360a555 100644 --- a/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S +++ b/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S @@ -193,7 +193,7 @@ arch_syscall_exit: add sp, sp, #0x40 RESTORE_FPU sp -/* the sp is reset to the outer most level */ +/* the sp is reset to the outer most level, irq and fiq are disabled */ START_POINT(arch_ret_to_user) /* save exception frame */ SAVE_FPU sp @@ -245,11 +245,18 @@ START_POINT(arch_ret_to_user) /** * push 2 dummy words to simulate a exception frame of interrupt + * @note in kernel state, the context switch dont saved the context */ - add sp, sp, #-0x10 + mrs x0, spsr_el1 + mrs x1, elr_el1 + stp x1, x0, [sp, #-0x10]! mov x0, sp + msr daifclr, #3 bl lwp_thread_signal_catch - add sp, sp, #0x10 + msr daifset, #3 + ldp x1, x0, [sp], #0x10 + msr spsr_el1, x0 + msr elr_el1, x1 /* check debug */ /* restore exception frame */ @@ -405,7 +412,6 @@ arch_signal_quit: msr spsr_el1, x3 ldp x29, x30, [sp], #0x10 - // msr sp_el0, x29 ldp x28, x29, [sp], #0x10 msr fpcr, x28 @@ -452,12 +458,9 @@ arch_thread_signal_enter: * move exception frame to user stack */ mrs x0, sp_el0 - mrs x3, elr_el1 - mov x5, x4 - /** FIXME: spsr must restore from exception frame */ - mrs x4, spsr_el1 + mov x3, x4 - /* arch_signal_ucontext_save(user_sp, psiginfo, exp_frame, elr, spsr, save_sig_mask); */ + /* arch_signal_ucontext_save(user_sp, psiginfo, exp_frame, save_sig_mask); */ bl arch_signal_ucontext_save dc cvau, x0 @@ -469,7 +472,16 @@ arch_thread_signal_enter: * @brief Prepare the environment for signal handler */ - /** drop exp frame on kernel stack, reset kernel sp */ + /** + * reset the cpsr + * and drop exp frame on kernel stack, reset kernel sp + * + * @note Since we will reset spsr, but the reschedule will + * corrupt the spsr, we diable irq for a short period here + */ + msr daifset, #3 + ldr x1, [x20, #CONTEXT_OFFSET_SPSR_EL1] + msr spsr_el1, x1 add sp, x20, #CONTEXT_SIZE /** reset user sp */ From ee2c1cc4846c495f99f2763c58d1e28c62b21d35 Mon Sep 17 00:00:00 2001 From: Shell Date: Mon, 31 Jul 2023 11:38:46 +0800 Subject: [PATCH 2/2] [smart] fix process kill not working Add more debug log info. Not deliver masked signal to thread. Reset mask on timedwait. Do terminate by compete of every thread in a process. Signed-off-by: Shell --- components/lwp/lwp_pid.c | 34 ++++++++++++--------- components/lwp/lwp_signal.c | 57 +++++++++++++++++++++++------------- components/lwp/lwp_syscall.c | 6 ++-- 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index 461ada6c368..82185adf344 100644 --- a/components/lwp/lwp_pid.c +++ b/components/lwp/lwp_pid.c @@ -983,26 +983,31 @@ void lwp_terminate(struct rt_lwp *lwp) return; } + LOG_D("%s(lwp=%p \"%s\")", __func__, lwp, lwp->cmd); + level = rt_hw_interrupt_disable(); /* stop the receiving of signals */ - lwp->terminated = RT_TRUE; - - /* broadcast exit request for sibling threads */ - for (list = lwp->t_grp.next; list != &lwp->t_grp; list = list->next) + if (!lwp->terminated) { - rt_thread_t thread; + lwp->terminated = RT_TRUE; - thread = rt_list_entry(list, struct rt_thread, sibling); - if (thread->exit_request == LWP_EXIT_REQUEST_NONE) - { - thread->exit_request = LWP_EXIT_REQUEST_TRIGGERED; - } - if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) + /* broadcast exit request for sibling threads */ + for (list = lwp->t_grp.next; list != &lwp->t_grp; list = list->next) { - thread->error = RT_EINTR; - rt_hw_dsb(); - rt_thread_wakeup(thread); + rt_thread_t thread; + + thread = rt_list_entry(list, struct rt_thread, sibling); + if (thread->exit_request == LWP_EXIT_REQUEST_NONE) + { + thread->exit_request = LWP_EXIT_REQUEST_TRIGGERED; + } + if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) + { + thread->error = RT_EINTR; + rt_hw_dsb(); + rt_thread_wakeup(thread); + } } } rt_hw_interrupt_enable(level); @@ -1031,6 +1036,7 @@ void lwp_wait_subthread_exit(void) while (1) { int subthread_is_terminated; + LOG_D("%s: wait for subthread exiting", __func__); level = rt_hw_interrupt_disable(); subthread_is_terminated = (int)(thread->sibling.prev == &lwp->t_grp); diff --git a/components/lwp/lwp_signal.c b/components/lwp/lwp_signal.c index 704c9f0a83f..41a8495429b 100644 --- a/components/lwp/lwp_signal.c +++ b/components/lwp/lwp_signal.c @@ -546,32 +546,36 @@ void lwp_thread_signal_catch(void *exp_frame) * @note that the p_usi is release before entering signal action by * reseting the kernel sp. */ + LOG_D("%s: enter signal handler(signo=%d) at %p", __func__, signo, handler); arch_thread_signal_enter(signo, p_usi, exp_frame, handler, &save_sig_mask); /* the arch_thread_signal_enter() never return */ RT_ASSERT(0); } } - static int _do_signal_wakeup(rt_thread_t thread, int sig) { int need_schedule; - if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) + if (!_sigismember(&thread->signal.sigset_mask, sig)) { - - if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK) + if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) { - rt_thread_wakeup(thread); - need_schedule = 1; - } - else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK)) - { - rt_thread_wakeup(thread); - need_schedule = 1; + if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK) + { + rt_thread_wakeup(thread); + need_schedule = 1; + } + else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK)) + { + rt_thread_wakeup(thread); + need_schedule = 1; + } + else + { + need_schedule = 0; + } } else - { need_schedule = 0; - } } else need_schedule = 0; @@ -633,7 +637,7 @@ static int _siginfo_deliver_to_lwp(struct rt_lwp *lwp, lwp_siginfo_t siginfo) return _do_signal_wakeup(catcher, siginfo->ksiginfo.signo); } -static int _siginfo_deliver_to_thread(struct rt_lwp *lwp, rt_thread_t thread, lwp_siginfo_t siginfo) +static int _siginfo_deliver_to_thread(rt_thread_t thread, lwp_siginfo_t siginfo) { sigqueue_enqueue(_SIGQ(thread), siginfo); return _do_signal_wakeup(thread, siginfo->ksiginfo.signo); @@ -679,6 +683,9 @@ rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code, long value) } else { + LOG_D("%s(lwp=%p \"%s\",signo=%ld,code=%ld,value=%ld)", + __func__, lwp, lwp->cmd, signo, code, value); + need_schedule = RT_FALSE; /* FIXME: acquire READ lock to lwp */ @@ -848,7 +855,7 @@ rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code, long if (siginfo) { - need_schedule = _siginfo_deliver_to_thread(lwp, thread, siginfo); + need_schedule = _siginfo_deliver_to_thread(thread, siginfo); ret = 0; } else @@ -943,10 +950,10 @@ static int _dequeue_signal(rt_thread_t thread, lwp_sigset_t *mask, siginfo_t *us rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset, siginfo_t *usi, struct timespec *timeout) { - LOG_D("%s", __func__); - rt_base_t level; rt_err_t ret; + lwp_sigset_t saved_sigset; + lwp_sigset_t blocked_sigset; int sig; /** @@ -960,6 +967,7 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset, _sigdelset(sigset, SIGSTOP); _signotsets(sigset, sigset); + /* FIXME: acquire READ lock to lwp */ level = rt_hw_interrupt_disable(); sig = _dequeue_signal(thread, sigset, usi); @@ -967,17 +975,19 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset, if (sig) return sig; - /* WARNING atomic problem, what if pending signal arrives before we sleep */ - /** * @brief POSIX * if none of the signals specified by set are pending, sigtimedwait() shall * wait for the time interval specified in the timespec structure referenced * by timeout. + * + * @note If the pending signal arrives before thread suspend, the suspend + * operation will return a failure */ + _sigandsets(&blocked_sigset, &thread->signal.sigset_mask, sigset); + _thread_signal_mask(thread, LWP_SIG_MASK_CMD_SET_MASK, &blocked_sigset, &saved_sigset); if (timeout) { - /* TODO: verify timeout valid ? not overflow 32bits, nanosec valid, ... */ rt_uint32_t time; time = rt_timespec_to_tick(timeout); @@ -1006,9 +1016,14 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset, if (ret == RT_EOK) { rt_schedule(); - ret = -EAGAIN; + /* If thread->error reliable? */ + if (thread->error == -RT_EINTR) + ret = -EINTR; + else + ret = -EAGAIN; } /* else ret == -EINTR */ + _thread_signal_mask(thread, LWP_SIG_MASK_CMD_SET_MASK, &saved_sigset, RT_NULL); /* FIXME: acquire READ lock to lwp */ level = rt_hw_interrupt_disable(); diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 3dc743b1827..ddb09464655 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -346,10 +346,11 @@ void sys_exit(int value) lwp_put_to_user(clear_child_tid, &t, sizeof t); sys_futex(clear_child_tid, FUTEX_WAKE, 1, RT_NULL, RT_NULL, 0); } + lwp_terminate(lwp); + main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling); if (main_thread == tid) { - lwp_terminate(lwp); lwp_wait_subthread_exit(); lwp->lwp_ret = value; } @@ -3494,6 +3495,7 @@ sysret_t sys_sigtimedwait(const sigset_t *sigset, siginfo_t *info, const struct } else { + /* if sigset of user is smaller, clear extra space */ memset(&lwpset, 0, sizeof(lwpset)); } @@ -3526,7 +3528,7 @@ sysret_t sys_sigtimedwait(const sigset_t *sigset, siginfo_t *info, const struct sig = lwp_thread_signal_timedwait(rt_thread_self(), &lwpset, &kinfo, ptimeout); - if (info) + if (sig > 0 && info) { if (!lwp_user_accessable((void *)info, sizeof(*info))) return -EFAULT;