summaryrefslogtreecommitdiff
path: root/nuttx/sched/task_exithook.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-25 17:23:38 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-25 17:23:38 +0000
commitf2933cc4b65836a712f1ab996512999959a8c48a (patch)
treedd7f8afd13defdb90a4a8ffaba352f90efc3ec3a /nuttx/sched/task_exithook.c
parent1520663dd52c25496f285eb2e08077318c600759 (diff)
downloadpx4-nuttx-f2933cc4b65836a712f1ab996512999959a8c48a.tar.gz
px4-nuttx-f2933cc4b65836a712f1ab996512999959a8c48a.tar.bz2
px4-nuttx-f2933cc4b65836a712f1ab996512999959a8c48a.zip
Add framework to support task groups
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5562 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/sched/task_exithook.c')
-rw-r--r--nuttx/sched/task_exithook.c106
1 files changed, 68 insertions, 38 deletions
diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c
index 1813c12ed..30ce41f71 100644
--- a/nuttx/sched/task_exithook.c
+++ b/nuttx/sched/task_exithook.c
@@ -197,39 +197,28 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
****************************************************************************/
#ifdef CONFIG_SCHED_HAVE_PARENT
-static inline void task_sigchild(FAR _TCB *tcb, int status)
+static inline void task_sigchild(FAR _TCB *ptcb, FAR _TCB *ctcb, int status)
{
- FAR _TCB *ptcb;
siginfo_t info;
- /* Only exiting tasks should generate SIGCHLD. pthreads use other
- * mechansims.
+ /* Only the final exiting thread in a task group should generate SIGCHLD.
+ * If task groups are not supported then we will report SIGCHLD when the
+ * task exits.
*/
- if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ if (ctcb->group->tg_crefs == 1)
+#else
+ if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
+#endif
{
- /* Keep things stationary through the following */
-
- sched_lock();
-
- /* Get the TCB of the receiving task */
-
- ptcb = sched_gettcb(tcb->parent);
- if (!ptcb)
- {
- /* The parent no longer exists... bail */
-
- sched_unlock();
- return;
- }
-
#ifdef CONFIG_SCHED_CHILD_STATUS
- /* Check if the parent task has suppressed retention of child exit
+ /* Check if the parent task group has suppressed retention of child exit
* status information. Only 'tasks' report exit status, not pthreads.
* pthreads have a different mechanism.
*/
- if ((ptcb->flags & TCB_FLAG_NOCLDWAIT) == 0)
+ if ((ptcb->group->tg_flags & GROUP_FLAG_NOCLDWAIT) == 0)
{
FAR struct child_status_s *child;
@@ -255,15 +244,6 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
ptcb->nchildren--;
#endif
- /* Set the parent to an impossible PID. We do this because under
- * certain conditions, task_exithook() can be called multiple times.
- * If this function is called again, sched_gettcb() will fail on the
- * invalid parent PID above, nchildren will be decremented once and
- * all will be well.
- */
-
- tcb->parent = INVALID_PROCESS_ID;
-
/* Create the siginfo structure. We don't actually know the cause.
* That is a bug. Let's just say that the child task just exit-ted
* for now.
@@ -272,7 +252,7 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
info.si_signo = SIGCHLD;
info.si_code = CLD_EXITED;
info.si_value.sival_ptr = NULL;
- info.si_pid = tcb->pid;
+ info.si_pid = ctcb->pid;
info.si_status = status;
/* Send the signal. We need to use this internal interface so that we
@@ -280,11 +260,59 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
*/
(void)sig_received(ptcb, &info);
+ }
+}
+#else
+# define task_sigchild(ptct,ctcb,status)
+#endif
+
+/****************************************************************************
+ * Name: task_leavegroup
+ *
+ * Description:
+ * Send the SIGCHILD signal to the parent thread
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static inline void task_leavegroup(FAR _TCB *ctcb, int status)
+{
+ FAR _TCB *ptcb;
+
+ /* Keep things stationary throughout the following */
+
+ sched_lock();
+
+ /* Get the TCB of the receiving, parent task. We do this early to
+ * handle multiple calls to task_leavegroup. ctcb->parent is set to an
+ * invalid value below and the following call will fail if we are
+ * called again.
+ */
+
+ ptcb = sched_gettcb(ctcb->parent);
+ if (!ptcb)
+ {
+ /* The parent no longer exists... bail */
+
sched_unlock();
+ return;
}
+
+ /* Send SIGCHLD to all members of the parent's task group */
+
+ task_sigchild(ptcb, ctcb, status);
+
+ /* Set the parent to an impossible PID. We do this because under certain
+ * conditions, task_exithook() can be called multiple times. If this
+ * function is called again, sched_gettcb() will fail on the invalid
+ * parent PID above and all will be well.
+ */
+
+ ctcb->parent = INVALID_PROCESS_ID;
+ sched_unlock();
}
#else
-# define task_sigchild(tcb,status)
+# define task_leavegroup(ctcb,status)
#endif
/****************************************************************************
@@ -363,9 +391,9 @@ void task_exithook(FAR _TCB *tcb, int status)
task_onexit(tcb, status);
- /* Send SIGCHLD to the parent of the exit-ing task */
+ /* Leave the task group */
- task_sigchild(tcb, status);
+ task_leavegroup(tcb, status);
/* Wakeup any tasks waiting for this task to exit */
@@ -379,10 +407,12 @@ void task_exithook(FAR _TCB *tcb, int status)
(void)lib_flushall(tcb->streams);
#endif
- /* Discard any un-reaped child status (no zombies here!) */
+ /* Leave the task group. Perhaps discarding any un-reaped child
+ * status (no zombies here!)
+ */
-#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
- task_removechildren(tcb);
+#ifdef HAVE_TASK_GROUP
+ group_leave(tcb);
#endif
/* Free all file-related resources now. This gets called again