diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-05-28 21:42:18 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-05-28 21:42:18 +0000 |
commit | 94c7babe23d72a1e379da0cf0aab32fcf9fadcf3 (patch) | |
tree | eedc930a4ed4a1108c87cae26d3fcda7e411dd1f /nuttx/sched | |
parent | 405c2b328ff4cd571bb9e464541b4d297b18f93d (diff) | |
download | px4-nuttx-94c7babe23d72a1e379da0cf0aab32fcf9fadcf3.tar.gz px4-nuttx-94c7babe23d72a1e379da0cf0aab32fcf9fadcf3.tar.bz2 px4-nuttx-94c7babe23d72a1e379da0cf0aab32fcf9fadcf3.zip |
atexit() functions now called when task killed by task delete; For MCUs with <= 64Kb of SRAM, CONFIG_MM_SMALL can be defined to reduce the memory allocation overhead
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3648 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/sched')
-rw-r--r-- | nuttx/sched/Makefile | 10 | ||||
-rw-r--r-- | nuttx/sched/exit.c | 59 | ||||
-rw-r--r-- | nuttx/sched/os_internal.h | 1 | ||||
-rw-r--r-- | nuttx/sched/task_delete.c | 16 | ||||
-rw-r--r-- | nuttx/sched/task_exithook.c | 157 |
5 files changed, 179 insertions, 64 deletions
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile index 859bd57b4..9ea7ca1ba 100644 --- a/nuttx/sched/Makefile +++ b/nuttx/sched/Makefile @@ -44,11 +44,11 @@ MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c \ sched_setuppthreadfiles.c sched_releasefiles.c TSK_SRCS = task_create.c task_init.c task_setup.c task_activate.c \ - task_start.c task_delete.c task_deletecurrent.c task_restart.c \ - exit.c atexit.c getpid.c sched_addreadytorun.c sched_removereadytorun.c \ - sched_addprioritized.c sched_mergepending.c sched_addblocked.c \ - sched_removeblocked.c sched_free.c sched_gettcb.c sched_verifytcb.c \ - sched_releasetcb.c + task_start.c task_delete.c task_deletecurrent.c task_exithook.c \ + task_restart.c exit.c atexit.c getpid.c sched_addreadytorun.c \ + sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \ + sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \ + sched_verifytcb.c sched_releasetcb.c SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \ sched_setscheduler.c sched_getscheduler.c \ diff --git a/nuttx/sched/exit.c b/nuttx/sched/exit.c index 6793eae77..2964b5a01 100644 --- a/nuttx/sched/exit.c +++ b/nuttx/sched/exit.c @@ -67,7 +67,7 @@ ****************************************************************************/ /**************************************************************************** - * Private Functionss + * Private Functions ****************************************************************************/ /**************************************************************************** @@ -78,68 +78,29 @@ * Function: exit * * Description: - * The exit() function causes normal process termination - * and the value of status & 0377 is returned to the parent. + * The exit() function causes normal process termination and the value of + * status & 0377 to be returned to the parent. * - * All functions registered with atexit() and on_exit() are - * called, in the reverse order of their registration. + * All functions registered with atexit() and on_exit() are called, in the + * reverse order of their registration. * - * All open streams are flushed and closed. Files created - * by tmpfile() are removed. + * All open streams are flushed and closed. * ****************************************************************************/ void exit(int status) { -#if CONFIG_NFILE_STREAMS > 0 || defined(CONFIG_SCHED_WAITPID) || defined(CONFIG_SCHED_ATEXIT) _TCB *tcb = (_TCB*)g_readytorun.head; -#endif - /* Only the lower 8 bits of the exit status are used */ + /* Only the lower 8-bits of status are used */ status &= 0xff; - /* Flush all streams (File descriptors will be closed when - * the TCB is deallocated. - */ + /* Perform common task termination logic */ -#if CONFIG_NFILE_STREAMS > 0 - (void)lib_flushall(tcb->streams); -#endif + task_exithook(tcb, status); - /* Wakeup any tasks waiting for this task to exit */ - -#ifdef CONFIG_SCHED_WAITPID /* Experimental */ - while (tcb->exitsem.semcount < 0) - { - /* "If more than one thread is suspended in waitpid() awaiting - * termination of the same process, exactly one thread will return - * the process status at the time of the target process termination." - * Hmmm.. what do we return to the others? - */ - - if (tcb->stat_loc) - { - *tcb->stat_loc = status << 8; - tcb->stat_loc = NULL; - } - - /* Wake up the thread */ - - sem_post(&tcb->exitsem); - } -#endif - - /* If an exit function was registered, call it now. */ - -#ifdef CONFIG_SCHED_ATEXIT - if (tcb->exitfunc) - { - (*tcb->exitfunc)(); - } -#endif - - /* Then "really" exit */ + /* Then "really" exit. Only the lower 8 bits of the exit status are used. */ _exit(status); } diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h index b25ee1c5e..3287507a9 100644 --- a/nuttx/sched/os_internal.h +++ b/nuttx/sched/os_internal.h @@ -265,6 +265,7 @@ extern void task_start(void); extern int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main); extern int task_argsetup(FAR _TCB *tcb, const char *name, const char *argv[]); +extern void task_exithook(FAR _TCB *tcb, int status); extern int task_deletecurrent(void); #ifndef CONFIG_CUSTOM_STACK extern int kernel_thread(const char *name, int priority, diff --git a/nuttx/sched/task_delete.c b/nuttx/sched/task_delete.c index 4fd49a4ea..51b3e30da 100644 --- a/nuttx/sched/task_delete.c +++ b/nuttx/sched/task_delete.c @@ -140,14 +140,9 @@ int task_delete(pid_t pid) PANIC(OSERR_BADDELETESTATE); } - saved_state = irqsave(); - - /* Inform the instrumentation layer that the task has stopped */ - - sched_note_stop(dtcb); - /* Remove the task from the OS's tasks lists. */ + saved_state = irqsave(); dq_rem((FAR dq_entry_t*)dtcb, (dq_queue_t*)g_tasklisttable[dtcb->task_state].list); dtcb->task_state = TSTATE_TASK_INVALID; irqrestore(saved_state); @@ -156,11 +151,12 @@ int task_delete(pid_t pid) sched_unlock(); - /* Deallocate anything left in the TCB's queues */ + /* Perform common task termination logic (flushing streams, calling + * functions registered by at_exit/on_exit, etc.). I suppose EXIT_SUCCESS + * is an appropriate return value??? + */ -#ifndef CONFIG_DISABLE_SIGNALS - sig_cleanup(dtcb); /* Deallocate Signal lists */ -#endif + task_exithook(dtcb, EXIT_SUCCESS); /* Deallocate its TCB */ diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c new file mode 100644 index 000000000..9567f48a9 --- /dev/null +++ b/nuttx/sched/task_exithook.c @@ -0,0 +1,157 @@ +/**************************************************************************** + * sched/task_exithook.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdlib.h> +#include <unistd.h> +#include <debug.h> +#include <errno.h> + +#include <nuttx/fs.h> + +#include "os_internal.h" +#include "sig_internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: task_hook + * + * Description: + * This function implements some of the internal logic of exit() and + * task_delete(). This function performs some cleanup and other actions + * required when a task exists: + * + * - All open streams are flushed and closed. + * - All functions registered with atexit() and on_exit() are called, in + * the reverse order of their registration. + * + * When called from exit(), the tcb still resides at the head of the ready- + * to-run list. The following logic is safe because we will not be + * returning from the exit() call. + * + * When called from task_delete() we are operating on a different thread; + * on the thread that called task_delete(). In this case, task_delete + * will have already removed the tcb from the ready-to-run list to prevent + * any further action on this task. + * + ****************************************************************************/ + +void task_exithook(FAR _TCB *tcb, int status) +{ + /* Inform the instrumentation layer that the task has stopped */ + + sched_note_stop(tcb); + + /* Flush all streams (File descriptors will be closed when + * the TCB is deallocated). + */ + +#if CONFIG_NFILE_STREAMS > 0 + (void)lib_flushall(tcb->streams); +#endif + + /* Deallocate anything left in the TCB's queues */ + +#ifndef CONFIG_DISABLE_SIGNALS + sig_cleanup(tcb); /* Deallocate Signal lists */ +#endif + + /* Wakeup any tasks waiting for this task to exit */ + +#ifdef CONFIG_SCHED_WAITPID /* Experimental */ + while (tcb->exitsem.semcount < 0) + { + /* "If more than one thread is suspended in waitpid() awaiting + * termination of the same process, exactly one thread will return + * the process status at the time of the target process termination." + * Hmmm.. what do we return to the others? + */ + + if (tcb->stat_loc) + { + *tcb->stat_loc = status << 8; + tcb->stat_loc = NULL; + } + + /* Wake up the thread */ + + sem_post(&tcb->exitsem); + } +#endif + + /* If an exit function was registered, call it now. NOTE: In the case + * of task_delete(), the exit function will *not* be called on the thread + * execution of the task being deleted! + */ + +#ifdef CONFIG_SCHED_ATEXIT + if (tcb->exitfunc) + { + (*tcb->exitfunc)(); + } +#endif +} |