summaryrefslogtreecommitdiffstats
path: root/nuttx/sched
diff options
context:
space:
mode:
authorpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2012-01-31 23:39:12 +0000
committerpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2012-01-31 23:39:12 +0000
commit835f66079e76710bb2fe74866f9eb646a9a03014 (patch)
tree4ec59e18f087faba4945cf1bb1d7855d44e82080 /nuttx/sched
parent63f70dffcd78744d106da124e68beaa303a5fd5b (diff)
Add on_exit(); Re-order some logic in the task shutdown sequence. Sometimes some complex logic needs to execute when closing file descriptors and this needs to happen early while the task is still healthy
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4354 7fd9a85b-ad96-42d3-883c-3090e2eb8679
Diffstat (limited to 'nuttx/sched')
-rw-r--r--nuttx/sched/Makefile14
-rw-r--r--nuttx/sched/atexit.c12
-rw-r--r--nuttx/sched/on_exit.c127
-rw-r--r--nuttx/sched/sched_releasefiles.c37
-rw-r--r--nuttx/sched/task_delete.c17
-rw-r--r--nuttx/sched/task_exithook.c50
6 files changed, 210 insertions, 47 deletions
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile
index 39a526edaf..b8a1bb519a 100644
--- a/nuttx/sched/Makefile
+++ b/nuttx/sched/Makefile
@@ -1,8 +1,8 @@
############################################################################
# sched/Makefile
#
-# Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
-# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -45,7 +45,7 @@ MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.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_exithook.c \
- task_restart.c exit.c atexit.c getpid.c sched_addreadytorun.c \
+ task_restart.c exit.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
@@ -55,6 +55,14 @@ SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \
sched_yield.c sched_rrgetinterval.c sched_foreach.c \
sched_lock.c sched_unlock.c sched_lockcount.c sched_self.c
+ifeq ($(CONFIG_SCHED_ATEXIT),y)
+SCHED_SRCS += atexit.c
+endif
+
+ifeq ($(CONFIG_SCHED_ONEXIT),y)
+SCHED_SRCS += on_exit.c
+endif
+
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
SCHED_SRCS += sched_reprioritize.c
endif
diff --git a/nuttx/sched/atexit.c b/nuttx/sched/atexit.c
index 3a116f4c14..da1be1c2ab 100644
--- a/nuttx/sched/atexit.c
+++ b/nuttx/sched/atexit.c
@@ -1,8 +1,8 @@
/************************************************************************
* sched/atexit.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -52,7 +52,7 @@
#ifdef CONFIG_SCHED_ATEXIT
/************************************************************************
- * Definitions
+ * Pre-processor Definitions
************************************************************************/
/************************************************************************
@@ -72,7 +72,7 @@
************************************************************************/
/************************************************************************
- * Private Functionss
+ * Private Functions
************************************************************************/
/************************************************************************
@@ -101,9 +101,9 @@ int atexit(void (*func)(void))
/* The following must be atomic */
sched_lock();
- if (func && !tcb->exitfunc)
+ if (func && !tcb->atexitfunc)
{
- tcb->exitfunc = func;
+ tcb->atexitfunc = func;
ret = OK;
}
diff --git a/nuttx/sched/on_exit.c b/nuttx/sched/on_exit.c
new file mode 100644
index 0000000000..9824ec7353
--- /dev/null
+++ b/nuttx/sched/on_exit.c
@@ -0,0 +1,127 @@
+/************************************************************************
+ * sched/on_exit.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <assert.h>
+#include <unistd.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/fs.h>
+
+#include "os_internal.h"
+
+#ifdef CONFIG_SCHED_ONEXIT
+
+/************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************/
+
+/************************************************************************
+ * Private Type Declarations
+ ************************************************************************/
+
+/************************************************************************
+ * Global Variables
+ ************************************************************************/
+
+/************************************************************************
+ * Private Variables
+ ************************************************************************/
+
+/************************************************************************
+ * Private Function Prototypes
+ ************************************************************************/
+
+/************************************************************************
+ * Private Functions
+ ************************************************************************/
+
+/************************************************************************
+ * Public Functions
+ ************************************************************************/
+
+/************************************************************************
+ * Function: atexit
+ *
+ * Description:
+ * Registers a function to be called at program exit.
+ * The on_exit() function registers the given function to be called
+ * at normal process termination, whether via exit or via return from
+ * the program's main(). The function is passed the status argument
+ * given to the last call to exit and the arg argument from on_exit().
+ *
+ * Limitiations in the current implementation:
+ *
+ * 1. Only a single on_exit function can be registered.
+ * 2. on_exit functions are not inherited when a new task is
+ * created.
+ *
+ * Parameters:
+ * func
+ *
+ * Return Value:
+ * Zero on success. Non-zero on failure.
+ *
+ ************************************************************************/
+
+int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg)
+{
+ _TCB *tcb = (_TCB*)g_readytorun.head;
+ int ret = ERROR;
+
+ /* The following must be atomic */
+
+ sched_lock();
+ if (func && !tcb->onexitfunc)
+ {
+ tcb->onexitfunc = func;
+ tdb->onexitarg = arg;
+ ret = OK;
+ }
+
+ sched_unlock();
+ return ret;
+}
+
+#endif /* CONFIG_SCHED_ATEXIT */
+
+
diff --git a/nuttx/sched/sched_releasefiles.c b/nuttx/sched/sched_releasefiles.c
index 160b0fb423..3990cd3c6b 100644
--- a/nuttx/sched/sched_releasefiles.c
+++ b/nuttx/sched/sched_releasefiles.c
@@ -1,8 +1,8 @@
/****************************************************************************
* sched/sched_releasefiles.c
*
- * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -58,7 +58,10 @@
* Function: sched_releasefiles
*
* Description:
- * Release file resources attached to a TCB.
+ * Release file resources attached to a TCB. This file may be called
+ * multiple times as a task exists. It will be called as early as possible
+ * to support proper closing of complex drivers that may need to wait
+ * on external events.
*
* Parameters:
* tcb - tcb of the new task.
@@ -75,25 +78,33 @@ int sched_releasefiles(_TCB *tcb)
if (tcb)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
- /* Free the file descriptor list */
+ /* Free the file descriptor list */
- files_releaselist(tcb->filelist);
- tcb->filelist = NULL;
+ if (tcb->filelist)
+ {
+ files_releaselist(tcb->filelist);
+ tcb->filelist = NULL;
+ }
#if CONFIG_NFILE_STREAMS > 0
- /* Free the stream list */
+ /* Free the stream list */
- lib_releaselist(tcb->streams);
- tcb->streams = NULL;
+ if (tcb->streams)
+ {
+ lib_releaselist(tcb->streams);
+ tcb->streams = NULL;
+ }
#endif /* CONFIG_NFILE_STREAMS */
#endif /* CONFIG_NFILE_DESCRIPTORS */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
- /* Free the file descriptor list */
-
- net_releaselist(tcb->sockets);
- tcb->sockets = NULL;
+ /* Free the file descriptor list */
+ if (tcb->sockets)
+ {
+ net_releaselist(tcb->sockets);
+ tcb->sockets = NULL;
+ }
#endif /* CONFIG_NSOCKET_DESCRIPTORS */
}
return OK;
diff --git a/nuttx/sched/task_delete.c b/nuttx/sched/task_delete.c
index 31715051a1..4cd2b3ba7a 100644
--- a/nuttx/sched/task_delete.c
+++ b/nuttx/sched/task_delete.c
@@ -140,6 +140,16 @@ int task_delete(pid_t pid)
PANIC(OSERR_BADDELETESTATE);
}
+ /* Perform common task termination logic (flushing streams, calling
+ * functions registered by at_exit/on_exit, etc.). We need to do
+ * this as early as possible so that higher level clean-up logic
+ * can run in a healthy tasking environment.
+ *
+ * I suppose EXIT_SUCCESS is an appropriate return value???
+ */
+
+ task_exithook(dtcb, EXIT_SUCCESS);
+
/* Remove the task from the OS's tasks lists. */
saved_state = irqsave();
@@ -151,13 +161,6 @@ int task_delete(pid_t pid)
sched_unlock();
- /* 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???
- */
-
- task_exithook(dtcb, EXIT_SUCCESS);
-
/* Deallocate its TCB */
sched_releasetcb(dtcb);
diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c
index 9567f48a9f..7dc07e79f1 100644
--- a/nuttx/sched/task_exithook.c
+++ b/nuttx/sched/task_exithook.c
@@ -1,8 +1,8 @@
/****************************************************************************
* sched/task_exithook.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -106,18 +106,23 @@ void task_exithook(FAR _TCB *tcb, int status)
sched_note_stop(tcb);
- /* Flush all streams (File descriptors will be closed when
- * the TCB is deallocated).
+ /* If an exit function was registered, call it now before we do any un-
+ * initialized. NOTE: In the case of task_delete(), the exit function
+ * will *not* be called on the thread execution of the task being deleted!
*/
-#if CONFIG_NFILE_STREAMS > 0
- (void)lib_flushall(tcb->streams);
+#ifdef CONFIG_SCHED_ATEXIT
+ if (tcb->atexitfunc)
+ {
+ (*tcb->atexitfunc)();
+ }
#endif
- /* Deallocate anything left in the TCB's queues */
-
-#ifndef CONFIG_DISABLE_SIGNALS
- sig_cleanup(tcb); /* Deallocate Signal lists */
+#ifdef CONFIG_SCHED_ONEXIT
+ if (tcb->onexitfunc)
+ {
+ (*tcb->onexitfunc)(status, tcb->onexitarg);
+ }
#endif
/* Wakeup any tasks waiting for this task to exit */
@@ -142,16 +147,25 @@ void task_exithook(FAR _TCB *tcb, int status)
sem_post(&tcb->exitsem);
}
#endif
+ /* Flush all streams (File descriptors will be closed when
+ * the TCB is deallocated).
+ */
- /* 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!
+#if CONFIG_NFILE_STREAMS > 0
+ (void)lib_flushall(tcb->streams);
+#endif
+
+ /* Free all file-related resources now. This gets called again
+ * just be be certain when the TCB is delallocated. However, we
+ * really need to close files as soon as possible while we still
+ * have a functioning task.
*/
-#ifdef CONFIG_SCHED_ATEXIT
- if (tcb->exitfunc)
- {
- (*tcb->exitfunc)();
- }
+ (void)sched_releasefiles(tcb);
+
+ /* Deallocate anything left in the TCB's queues */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ sig_cleanup(tcb); /* Deallocate Signal lists */
#endif
}