Loading arch/arm/kernel/entry-common.S +6 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,11 @@ work_pending: mov r0, sp @ 'regs' mov r2, why @ 'syscall' bl do_work_pending b no_work_pending tst r0, #1 beq no_work_pending ldmia sp, {r0 - r6} @ have to reload r0 - r6 b local_restart @ ... and off we go /* * "slow" syscall return path. "why" tells us if this was a real syscall. */ Loading Loading @@ -396,6 +400,7 @@ ENTRY(vector_swi) eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif local_restart: ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing stmdb sp!, {r4, r5} @ push fifth and sixth args Loading arch/arm/kernel/signal.c +29 −21 Original line number Diff line number Diff line Loading @@ -569,12 +569,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) static int do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; int restart = 0; /* * If we were from a system call, check for system call restarting... Loading @@ -589,10 +590,12 @@ static void do_signal(struct pt_regs *regs, int syscall) * debugger will see the already changed PSW. */ switch (retval) { case -ERESTART_RESTARTBLOCK: restart++; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTART_RESTARTBLOCK: restart++; regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; Loading @@ -604,13 +607,15 @@ static void do_signal(struct pt_regs *regs, int syscall) * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { if (regs->ARM_pc != restart_addr) restart = 0; if (signr > 0) { if (unlikely(restart)) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS Loading @@ -618,28 +623,23 @@ static void do_signal(struct pt_regs *regs, int syscall) regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } handle_signal(signr, &ka, &info, regs); return; return 0; } if (syscall) { /* * Handle restarting a different system call. As above, * if a debugger has chosen to restart at a different PC, * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK && regs->ARM_pc == restart_addr) if (unlikely(restart)) { if (restart > 1) set_thread_flag(TIF_SYSCALL_RESTARTSYS); regs->ARM_pc = continue_addr; } restore_saved_sigmask(); return restart; } asmlinkage void asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) { do { Loading @@ -647,10 +647,17 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) schedule(); } else { if (unlikely(!user_mode(regs))) return; return 0; local_irq_enable(); if (thread_flags & _TIF_SIGPENDING) { do_signal(regs, syscall); if (unlikely(do_signal(regs, syscall))) { /* * Restart without handlers. * Deal with it without leaving * the kernel space. */ return 1; } syscall = 0; } else { clear_thread_flag(TIF_NOTIFY_RESUME); Loading @@ -660,4 +667,5 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) local_irq_disable(); thread_flags = current_thread_info()->flags; } while (thread_flags & _TIF_WORK_MASK); return 0; } Loading
arch/arm/kernel/entry-common.S +6 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,11 @@ work_pending: mov r0, sp @ 'regs' mov r2, why @ 'syscall' bl do_work_pending b no_work_pending tst r0, #1 beq no_work_pending ldmia sp, {r0 - r6} @ have to reload r0 - r6 b local_restart @ ... and off we go /* * "slow" syscall return path. "why" tells us if this was a real syscall. */ Loading Loading @@ -396,6 +400,7 @@ ENTRY(vector_swi) eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif local_restart: ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing stmdb sp!, {r4, r5} @ push fifth and sixth args Loading
arch/arm/kernel/signal.c +29 −21 Original line number Diff line number Diff line Loading @@ -569,12 +569,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) static int do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; int restart = 0; /* * If we were from a system call, check for system call restarting... Loading @@ -589,10 +590,12 @@ static void do_signal(struct pt_regs *regs, int syscall) * debugger will see the already changed PSW. */ switch (retval) { case -ERESTART_RESTARTBLOCK: restart++; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTART_RESTARTBLOCK: restart++; regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; Loading @@ -604,13 +607,15 @@ static void do_signal(struct pt_regs *regs, int syscall) * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { if (regs->ARM_pc != restart_addr) restart = 0; if (signr > 0) { if (unlikely(restart)) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS Loading @@ -618,28 +623,23 @@ static void do_signal(struct pt_regs *regs, int syscall) regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } handle_signal(signr, &ka, &info, regs); return; return 0; } if (syscall) { /* * Handle restarting a different system call. As above, * if a debugger has chosen to restart at a different PC, * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK && regs->ARM_pc == restart_addr) if (unlikely(restart)) { if (restart > 1) set_thread_flag(TIF_SYSCALL_RESTARTSYS); regs->ARM_pc = continue_addr; } restore_saved_sigmask(); return restart; } asmlinkage void asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) { do { Loading @@ -647,10 +647,17 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) schedule(); } else { if (unlikely(!user_mode(regs))) return; return 0; local_irq_enable(); if (thread_flags & _TIF_SIGPENDING) { do_signal(regs, syscall); if (unlikely(do_signal(regs, syscall))) { /* * Restart without handlers. * Deal with it without leaving * the kernel space. */ return 1; } syscall = 0; } else { clear_thread_flag(TIF_NOTIFY_RESUME); Loading @@ -660,4 +667,5 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) local_irq_disable(); thread_flags = current_thread_info()->flags; } while (thread_flags & _TIF_WORK_MASK); return 0; }