diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-02-04 16:02:20 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2013-02-04 16:02:20 +0000 |
commit | c94d7c870c456005b3e87d71acba8f7f9ea2b5ec (patch) | |
tree | 982d75559dbb2fc6f53a4e8d090d40ef5c9e0f80 /nuttx | |
parent | c13bd69be3d117b359275bcf3b2d631bb19bd597 (diff) | |
download | px4-nuttx-c94d7c870c456005b3e87d71acba8f7f9ea2b5ec.tar.gz px4-nuttx-c94d7c870c456005b3e87d71acba8f7f9ea2b5ec.tar.bz2 px4-nuttx-c94d7c870c456005b3e87d71acba8f7f9ea2b5ec.zip |
Move waitpid() data structures to task group; The caller of waitpid() is now only awakened when the final thread of the task group exits
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5608 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 6 | ||||
-rw-r--r-- | nuttx/include/nuttx/sched.h | 15 | ||||
-rw-r--r-- | nuttx/sched/sched_waitpid.c | 18 | ||||
-rw-r--r-- | nuttx/sched/task_exithook.c | 51 |
4 files changed, 66 insertions, 24 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index cc7b911ee..577e6473f 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -4109,7 +4109,11 @@ * sched/pthread* and include/nuttx/sched: Move pthread join data and pthread key calculation data into the "task group" structure. * sched/atexit.c, on_exit.c, task_exithook.c and include/nuttx/sched.h: - Move atexit and on_exit data structure to task group. These + Move atexit and on_exit data structures to task group. These callbacks are only issued now when the final member of the task group exits. + * sched/waitpid.c, task_exithook.c and include/nuttx/sched.h: + Move waitpid data data structures to task group. Callers of + of waitpid() are now only awakened whent he final thread of the + task group exits. diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h index 456135962..41715cb0a 100644 --- a/nuttx/include/nuttx/sched.h +++ b/nuttx/include/nuttx/sched.h @@ -83,6 +83,8 @@ # define HAVE_TASK_GROUP 1 # elif defined(CONFIG_SCHED_ONEXIT) /* Group on_exit() function */ # define HAVE_TASK_GROUP 1 +# elif defined(CONFIG_SCHED_WAITPID) /* Group waitpid() function */ +# define HAVE_TASK_GROUP 1 # elif CONFIG_NFILE_DESCRIPTORS > 0 /* File descriptors */ # define HAVE_TASK_GROUP 1 # elif CONFIG_NFILE_STREAMS > 0 /* Standard C buffered I/O */ @@ -326,6 +328,14 @@ struct task_group_s FAR struct child_status_s *tg_children; /* Head of a list of child status */ #endif + /* waitpid support ************************************************************/ + /* Simple mechanism used only when there is no support for SIGCHLD */ + +#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) + sem_t tg_exitsem; /* Support for waitpid */ + int *tg_statloc; /* Location to return exit status */ +#endif + /* Pthreads *******************************************************************/ #ifndef CONFIG_DISABLE_PTHREAD @@ -408,11 +418,6 @@ struct _TCB FAR void *starthookarg; /* The argument passed to the function */ #endif -#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) - sem_t exitsem; /* Support for waitpid */ - int *stat_loc; /* Location to return exit status */ -#endif - uint8_t sched_priority; /* Current priority of the thread */ #ifdef CONFIG_PRIORITY_INHERITANCE diff --git a/nuttx/sched/sched_waitpid.c b/nuttx/sched/sched_waitpid.c index e44ef6e21..e79dded4c 100644 --- a/nuttx/sched/sched_waitpid.c +++ b/nuttx/sched/sched_waitpid.c @@ -182,7 +182,8 @@ #ifndef CONFIG_SCHED_HAVE_PARENT pid_t waitpid(pid_t pid, int *stat_loc, int options) { - _TCB *ctcb; + FAR _TCB *ctcb; + FAR struct task_group_s *group; bool mystat; int err; int ret; @@ -212,21 +213,26 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options) goto errout_with_errno; } + /* The the task group corresponding to this PID */ + + group = ctcb->group; + DEBUGASSERT(group); + /* "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 (stat_loc != NULL && ctcb->stat_loc == NULL) + if (stat_loc != NULL && group->tg_statloc == NULL) { - ctcb->stat_loc = stat_loc; - mystat = true; + group->tg_statloc = stat_loc; + mystat = true; } /* Then wait for the task to exit */ - ret = sem_wait(&ctcb->exitsem); + ret = sem_wait(&group->tg_exitsem); if (ret < 0) { /* Unlock pre-emption and return the ERROR (sem_wait has already set @@ -236,7 +242,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options) if (mystat) { - ctcb->stat_loc = NULL; + group->tg_statloc = NULL; } goto errout; diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c index 20162c0d6..22a46613e 100644 --- a/nuttx/sched/task_exithook.c +++ b/nuttx/sched/task_exithook.c @@ -474,25 +474,52 @@ static inline void task_leavegroup(FAR _TCB *ctcb, int status) #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) static inline void task_exitwakeup(FAR _TCB *tcb, int status) { - /* Wakeup any tasks waiting for this task to exit */ + FAR struct task_group_s *group = tcb->group; + + /* Have we already left the group? */ - while (tcb->exitsem.semcount < 0) + if (group) { - /* "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? + /* Only tasks return valid status. Record the exit status when the + * task exists. The group, however, may still be executing. */ - if (tcb->stat_loc) + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK) { - *tcb->stat_loc = status << 8; - tcb->stat_loc = NULL; + /* Report the exit status. We do not nullify tg_statloc here + * because we want to prent other tasks from registering for + * the return status. There is only one task per task group, + * there for, this logic should execute exactly once in the + * lifetime of the task group. + * + * "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 (group->tg_statloc) + { + *group->tg_statloc = status << 8; + } } - /* Wake up the thread */ + /* Is this the last thread in the group? */ + + if (group->tg_nmembers == 1) + { + /* Yes.. Wakeup any tasks waiting for this task to exit */ + + group->tg_statloc = NULL; + while (group->tg_exitsem.semcount < 0) + { + /* Wake up the thread */ - sem_post(&tcb->exitsem); + sem_post(&group->tg_exitsem); + } + } } } #else @@ -530,7 +557,7 @@ void task_exithook(FAR _TCB *tcb, int status) { /* Under certain conditions, task_exithook() can be called multiple times. * A bit in the TCB was set the first time this function was called. If - * that bit is set, then just ext doing nothing more.. + * that bit is set, then just exit doing nothing more.. */ if ((tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0) |