From 69318b10241753f7135da1de219668709d2b8dce Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 28 Nov 2019 12:47:36 -0600 Subject: [PATCH] Re-implements reverted commit 344f7bc9f61d139b932bf6c6a5001e7a8e54409d in a way that should not have the undesired side-effect. include/nuttx/sched.h: Add a bit to the TCB flags to indicat the thread is a user thread in a syscall. sched/nuttx/nxsig_dispatch.c: Delay dispatching to signal handlers if within a system call. In all syscall implementations: Process delayed signal handling when exiting system call. --- arch/arm/src/armv6-m/up_svcall.c | 16 ++++++++++++++-- arch/arm/src/armv7-a/arm_syscall.c | 18 +++++++++++++++--- arch/arm/src/armv7-m/up_svcall.c | 16 ++++++++++++++-- arch/arm/src/armv7-r/arm_syscall.c | 18 +++++++++++++++--- arch/mips/src/mips32/up_swint0.c | 18 +++++++++++++++--- arch/misoc/src/lm32/lm32_swint.c | 18 +++++++++++++++--- arch/misoc/src/minerva/minerva_swint.c | 16 ++++++++++++++-- arch/risc-v/src/rv32im/up_swint.c | 18 +++++++++++++++--- include/nuttx/sched.h | 19 ++++++++++--------- net/netlink/netlink_conn.c | 4 ++-- net/netlink/netlink_sockif.c | 4 +++- sched/signal/sig_dispatch.c | 21 +++++++++++++++------ sched/signal/sig_unmaskpendingsignal.c | 1 - 13 files changed, 147 insertions(+), 40 deletions(-) diff --git a/arch/arm/src/armv6-m/up_svcall.c b/arch/arm/src/armv6-m/up_svcall.c index f964248cbc..79bda1990c 100644 --- a/arch/arm/src/armv6-m/up_svcall.c +++ b/arch/arm/src/armv6-m/up_svcall.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/armv6-m/up_svcall.c * - * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2014, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ # include #endif +#include "signal/signal.h" #include "svcall.h" #include "exc_return.h" #include "up_internal.h" @@ -269,6 +270,13 @@ int up_svcall(int irq, FAR void *context, FAR void *arg) */ regs[REG_R0] = regs[REG_R2]; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; #endif @@ -437,7 +445,11 @@ int up_svcall(int irq, FAR void *context, FAR void *arg) /* Offset R0 to account for the reserved values */ - regs[REG_R0] -= CONFIG_SYS_RESERVED; + regs[REG_R0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_R0]); #endif diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c index 00e4f43c6b..493f4a26c4 100644 --- a/arch/arm/src/armv7-a/arm_syscall.c +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/armv7-a/arm_syscall.c * - * Copyright (C) 2013-2014, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2014, 2016, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,7 @@ #include #include +#include "signal/signal.h" #include "arm.h" #include "svcall.h" #include "addrenv.h" @@ -218,7 +219,14 @@ uint32_t *arm_syscall(uint32_t *regs) #endif /* Save the new SYSCALL nesting level */ - rtcb->xcp.nsyscalls = index; + rtcb->xcp.nsyscalls = index; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; @@ -449,7 +457,11 @@ uint32_t *arm_syscall(uint32_t *regs) #endif /* Offset R0 to account for the reserved values */ - regs[REG_R0] -= CONFIG_SYS_RESERVED; + regs[REG_R0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_R0]); #endif diff --git a/arch/arm/src/armv7-m/up_svcall.c b/arch/arm/src/armv7-m/up_svcall.c index 50897568cb..a2e9947c02 100644 --- a/arch/arm/src/armv7-m/up_svcall.c +++ b/arch/arm/src/armv7-m/up_svcall.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/armv7-m/up_svcall.c * - * Copyright (C) 2009, 2011-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2011-2015, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,7 @@ # include #endif +#include "signal/signal.h" #include "svcall.h" #include "exc_return.h" #include "up_internal.h" @@ -269,6 +270,13 @@ int up_svcall(int irq, FAR void *context, FAR void *arg) */ regs[REG_R0] = regs[REG_R2]; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; #endif @@ -437,7 +445,11 @@ int up_svcall(int irq, FAR void *context, FAR void *arg) /* Offset R0 to account for the reserved values */ - regs[REG_R0] -= CONFIG_SYS_RESERVED; + regs[REG_R0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_R0]); #endif diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c index 3abc36df90..80c4e91012 100644 --- a/arch/arm/src/armv7-r/arm_syscall.c +++ b/arch/arm/src/armv7-r/arm_syscall.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/armv7-r/arm_syscall.c * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 20-19 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,7 @@ #include #include +#include "signal/signal.h" #include "arm.h" #include "svcall.h" #include "up_internal.h" @@ -216,7 +217,14 @@ uint32_t *arm_syscall(uint32_t *regs) #endif /* Save the new SYSCALL nesting level */ - rtcb->xcp.nsyscalls = index; + rtcb->xcp.nsyscalls = index; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; @@ -447,7 +455,11 @@ uint32_t *arm_syscall(uint32_t *regs) #endif /* Offset R0 to account for the reserved values */ - regs[REG_R0] -= CONFIG_SYS_RESERVED; + regs[REG_R0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_R0]); #endif diff --git a/arch/mips/src/mips32/up_swint0.c b/arch/mips/src/mips32/up_swint0.c index 67b2278b69..b093ed0447 100644 --- a/arch/mips/src/mips32/up_swint0.c +++ b/arch/mips/src/mips32/up_swint0.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/mips/src/mips32/up_swint0.c * - * Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2012, 2015, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -50,6 +50,7 @@ #include #include +#include "signal/signal.h" #include "up_internal.h" /**************************************************************************** @@ -224,7 +225,14 @@ int up_swint0(int irq, FAR void *context, FAR void *arg) g_current_regs[REG_EPC] = rtcb->xcp.syscall[index].sysreturn; #error "Missing logic -- need to restore the original mode" - rtcb->xcp.nsyscalls = index; + rtcb->xcp.nsyscalls = index; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; #endif @@ -256,12 +264,16 @@ int up_swint0(int irq, FAR void *context, FAR void *arg) #error "Missing logic -- Need to save mode" rtcb->xcp.nsyscalls = index + 1; - regs[REG_EPC] = (uint32_t)dispatch_syscall; + regs[REG_EPC] = (uint32_t)dispatch_syscall; #error "Missing logic -- Need to set privileged mode" /* Offset R0 to account for the reserved values */ g_current_regs[REG_R0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_A0]); #endif diff --git a/arch/misoc/src/lm32/lm32_swint.c b/arch/misoc/src/lm32/lm32_swint.c index 54e17dc150..a71225aad8 100644 --- a/arch/misoc/src/lm32/lm32_swint.c +++ b/arch/misoc/src/lm32/lm32_swint.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/misoc/src/lm32/lm32_swint.c * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2016, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * Ramtin Amin * @@ -49,6 +49,7 @@ #include #include +#include "signal/signal.h" #include "lm32.h" /**************************************************************************** @@ -225,7 +226,14 @@ int lm32_swint(int irq, FAR void *context, FAR void *arg) g_current_regs[REG_EPC] = rtcb->xcp.syscall[index].sysreturn; #error "Missing logic -- need to restore the original mode" - rtcb->xcp.nsyscalls = index; + rtcb->xcp.nsyscalls = index; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; #endif @@ -257,12 +265,16 @@ int lm32_swint(int irq, FAR void *context, FAR void *arg) #error "Missing logic -- Need to save mode" rtcb->xcp.nsyscalls = index + 1; - regs[REG_EPC] = (uint32_t)dispatch_syscall; + regs[REG_EPC] = (uint32_t)dispatch_syscall; #error "Missing logic -- Need to set privileged mode" /* Offset R0 to account for the reserved values */ g_current_regs[REG_A0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_A0]); #endif diff --git a/arch/misoc/src/minerva/minerva_swint.c b/arch/misoc/src/minerva/minerva_swint.c index 4404cbae60..23a9ec7869 100644 --- a/arch/misoc/src/minerva/minerva_swint.c +++ b/arch/misoc/src/minerva/minerva_swint.c @@ -49,6 +49,7 @@ #include #include +#include "signal/signal.h" #include "minerva.h" /**************************************************************************** @@ -212,7 +213,14 @@ int minerva_swint(int irq, FAR void *context, FAR void *arg) g_current_regs[REG_CSR_MEPC] = rtcb->xcp.syscall[index].sysreturn; #error "Missing logic -- need to restore the original mode" - rtcb->xcp.nsyscalls = index; + rtcb->xcp.nsyscalls = index; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; #endif @@ -245,12 +253,16 @@ int minerva_swint(int irq, FAR void *context, FAR void *arg) #error "Missing logic -- Need to save mode" rtcb->xcp.nsyscalls = index + 1; - regs[REG_CSR_MEPC] = (uint32_t) dispatch_syscall; + regs[REG_CSR_MEPC] = (uint32_t) dispatch_syscall; #error "Missing logic -- Need to set privileged mode" /* Offset R0 to account for the reserved values */ g_current_regs[REG_A0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_A0]); #endif diff --git a/arch/risc-v/src/rv32im/up_swint.c b/arch/risc-v/src/rv32im/up_swint.c index e1b8dca8ad..2527062517 100644 --- a/arch/risc-v/src/rv32im/up_swint.c +++ b/arch/risc-v/src/rv32im/up_swint.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/riscv/src/rv32im/up_swint.c * - * Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2011-2012, 2015, 2019 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,7 @@ #include +#include "signal/signal.h" #include "up_internal.h" /**************************************************************************** @@ -222,7 +223,14 @@ int up_swint(int irq, FAR void *context, FAR void *arg) g_current_regs[REG_EPC] = rtcb->xcp.syscall[index].sysreturn; #error "Missing logic -- need to restore the original mode" - rtcb->xcp.nsyscalls = index; + rtcb->xcp.nsyscalls = index; + + /* Handle any signal actions that were deferred while processing + * the system call. + */ + + rtcb->flags &= ~TCB_FLAG_SYSCALL; + (void)nxsig_unmask_pendingsignal(); } break; #endif @@ -254,12 +262,16 @@ int up_swint(int irq, FAR void *context, FAR void *arg) #error "Missing logic -- Need to save mode" rtcb->xcp.nsyscalls = index + 1; - regs[REG_EPC] = (uint32_t)dispatch_syscall; + regs[REG_EPC] = (uint32_t)dispatch_syscall; #error "Missing logic -- Need to set privileged mode" /* Offset R0 to account for the reserved values */ g_current_regs[REG_A0] -= CONFIG_SYS_RESERVED; + + /* Indicate that we are in a syscall handler. */ + + rtcb->flags |= TCB_FLAG_SYSCALL; #else svcerr("ERROR: Bad SYS call: %d\n", regs[REG_A0]); #endif diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 7ec687ac44..2e998028d1 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -103,24 +103,25 @@ /* Values for the struct tcb_s flags bits */ -#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */ +#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */ #define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT) # define TCB_FLAG_TTYPE_TASK (0 << TCB_FLAG_TTYPE_SHIFT) /* Normal user task */ # define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */ # define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */ -#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */ -#define TCB_FLAG_CANCEL_DEFERRED (1 << 3) /* Bit 3: Deferred (vs asynch) cancellation type */ -#define TCB_FLAG_CANCEL_PENDING (1 << 4) /* Bit 4: Pthread cancel is pending */ -#define TCB_FLAG_POLICY_SHIFT (5) /* Bit 5-6: Scheduling policy */ +#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */ +#define TCB_FLAG_CANCEL_DEFERRED (1 << 3) /* Bit 3: Deferred (vs asynch) cancellation type */ +#define TCB_FLAG_CANCEL_PENDING (1 << 4) /* Bit 4: Pthread cancel is pending */ +#define TCB_FLAG_POLICY_SHIFT (5) /* Bit 5-6: Scheduling policy */ #define TCB_FLAG_POLICY_MASK (3 << TCB_FLAG_POLICY_SHIFT) # define TCB_FLAG_SCHED_FIFO (0 << TCB_FLAG_POLICY_SHIFT) /* FIFO scheding policy */ # define TCB_FLAG_SCHED_RR (1 << TCB_FLAG_POLICY_SHIFT) /* Round robin scheding policy */ # define TCB_FLAG_SCHED_SPORADIC (2 << TCB_FLAG_POLICY_SHIFT) /* Sporadic scheding policy */ # define TCB_FLAG_SCHED_OTHER (3 << TCB_FLAG_POLICY_SHIFT) /* Other scheding policy */ -#define TCB_FLAG_CPU_LOCKED (1 << 7) /* Bit 7: Locked to this CPU */ -#define TCB_FLAG_SIGNAL_ACTION (1 << 8) /* Bit 8: In a signal handler */ -#define TCB_FLAG_EXIT_PROCESSING (1 << 9) /* Bit 9: Exitting */ - /* Bits 10-15: Available */ +#define TCB_FLAG_CPU_LOCKED (1 << 7) /* Bit 7: Locked to this CPU */ +#define TCB_FLAG_SIGNAL_ACTION (1 << 8) /* Bit 8: In a signal handler */ +#define TCB_FLAG_SYSCALL (1 << 9) /* Bit 9: In a system call */ +#define TCB_FLAG_EXIT_PROCESSING (1 << 10) /* Bit 10: Exitting */ + /* Bits 11-15: Available */ /* Values for struct task_group tg_flags */ diff --git a/net/netlink/netlink_conn.c b/net/netlink/netlink_conn.c index 61030ea3e2..f974f5d833 100644 --- a/net/netlink/netlink_conn.c +++ b/net/netlink/netlink_conn.c @@ -127,8 +127,8 @@ static void netlink_notify_waiters(FAR struct netlink_conn_s *conn) int i; /* Notify every pending thread. Lock the scheduler while we do this so - * there there is no thrashing: All waiters will be restarted, but only - * the highest priority waiter will get to run and will receive the + * that there is no thrashing: All waiters will be restarted, but only + * the highest priority waiter will get to run and it will receive the * response. */ diff --git a/net/netlink/netlink_sockif.c b/net/netlink/netlink_sockif.c index 557471196e..d3464793a6 100644 --- a/net/netlink/netlink_sockif.c +++ b/net/netlink/netlink_sockif.c @@ -640,8 +640,10 @@ static int netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds, { struct sigaction act; - /* Set up a signal handler to recive the notification when + /* Set up a signal handler to receive the notification when * a response has been queued. + * REVISIT: Make sure that the CONFIG_NETLINK_SIGNAL is not + * blocked. */ if (conn->pollsem != NULL || conn->pollevent != NULL) diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index 6ce98ea770..f78446eb29 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -1,8 +1,8 @@ /**************************************************************************** * sched/signal/sig_dispatch.c * - * Copyright (C) 2007, 2009, 2011, 2016, 2018 Gregory Nutt. All rights - * reserved. + * Copyright (C) 2007, 2009, 2011, 2016, 2018-2019 Gregory Nutt. All + * rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -311,11 +311,13 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) /************************* MASKED SIGNAL HANDLING ************************/ - /* Check if the signal is masked -- if it is, it will be added to the list - * of pending signals. + /* Check if the signal is masked OR if it is received while we are + * processing a system call -- in either case, it will be added to the + * list of pending signals. */ - if (sigismember(&stcb->sigprocmask, info->si_signo)) + if (sigismember(&stcb->sigprocmask, info->si_signo) || + (stcb->flags & TCB_FLAG_SYSCALL) != NULL) { /* Check if the task is waiting for this pending signal. If so, then * unblock it. This must be performed in a critical section because @@ -380,9 +382,16 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) * handler attached to the signal, then the default action is * simply to ignore the signal */ + } - /*********************** OTHER SIGNAL HANDLING ***********************/ + /************************* OTHER SIGNAL HANDLING *************************/ + /* Performed only if the signal is unmasked. These actions also must + * happen within a system call. + */ + + if (!sigismember(&stcb->sigprocmask, info->si_signo)) + { /* If the task is blocked waiting for a semaphore, then that task must * be unblocked when a signal is received. */ diff --git a/sched/signal/sig_unmaskpendingsignal.c b/sched/signal/sig_unmaskpendingsignal.c index ef439f635e..7ea803b4e0 100644 --- a/sched/signal/sig_unmaskpendingsignal.c +++ b/sched/signal/sig_unmaskpendingsignal.c @@ -127,4 +127,3 @@ bool nxsig_unmask_pendingsignal(void) sched_unlock(); return true; } -