From 9d370fc3632fc2891c7a8e0af747491688ecb121 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Tue, 2 Mar 2021 08:38:58 +0900 Subject: [PATCH] sched: task: Call nxtask_flushstreams() without critical section Summary: - During investigating critical section with semaphores, I noticed that nxtask_flushstreams() is called with a critical section. - The function calls lib_flushall() which handles a semaphore in userspace. - So it should be done without a critical section Impact: - SMP only Testing: - Tested with ostest the following configs - esp32-devkitc:smp (QEMU), sabre-6quad:smp (QEMU) - maix-bit:smp (QEMU), sim:smp - spresense:smp - Tested with nxplayer and stress test with spresense:wifi_smp Signed-off-by: Masayuki Ishikawa --- sched/task/task_exithook.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/sched/task/task_exithook.c b/sched/task/task_exithook.c index 8378c0c8fc..0e34a99ab7 100644 --- a/sched/task/task_exithook.c +++ b/sched/task/task_exithook.c @@ -586,7 +586,6 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking) tcb->cpcount = 0; #endif -#if defined(CONFIG_SCHED_ATEXIT) || defined(CONFIG_SCHED_ONEXIT) /* If exit function(s) were registered, call them now before we do any un- * initialization. * @@ -604,14 +603,28 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking) if (!nonblocking) { +#if defined(CONFIG_SCHED_ATEXIT) || defined(CONFIG_SCHED_ONEXIT) nxtask_atexit(tcb); /* Call any registered on_exit function(s) */ nxtask_onexit(tcb, status); - } #endif + /* If this is the last thread in the group, then flush all streams + * (File descriptors will be closed when the TCB is deallocated). + * + * NOTES: + * 1. We cannot flush the buffered I/O if nonblocking is requested. + * that might cause this logic to block. + * 2. This function will only be called with non-blocking == true + * only when called through _exit(). _exit() behavior does not + * require that the streams be flushed + */ + + nxtask_flushstreams(tcb); + } + /* If the task was terminated by another task, it may be in an unknown * state. Make some feeble effort to recover the state. */ @@ -632,22 +645,6 @@ void nxtask_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking) nxtask_exitwakeup(tcb, status); - /* If this is the last thread in the group, then flush all streams (File - * descriptors will be closed when the TCB is deallocated). - * - * NOTES: - * 1. We cannot flush the buffered I/O if nonblocking is requested. - * that might cause this logic to block. - * 2. This function will only be called with non-blocking == true - * only when called through _exit(). _exit() behavior does not - * require that the streams be flushed - */ - - if (!nonblocking) - { - nxtask_flushstreams(tcb); - } - /* Leave the task group. Perhaps discarding any un-reaped child * status (no zombies here!) */