You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/05/04 13:20:12 UTC
[incubator-nuttx] 03/05: sched: add nx_wait,
nx_waitid and nx_waitpid
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit de2a9d8a771ac4434d94a654e2b60c4fd0de19a1
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Mon May 4 00:54:56 2020 +0800
sched: add nx_wait, nx_waitid and nx_waitpid
Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
include/nuttx/sched.h | 10 ++
sched/sched/sched_wait.c | 11 +-
sched/sched/sched_waitid.c | 198 ++++++++++++-----------
sched/sched/sched_waitpid.c | 374 ++++++++++++++++++++++----------------------
4 files changed, 313 insertions(+), 280 deletions(-)
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 8d07601..cc63e7c 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -1260,6 +1260,16 @@ int nxsched_setaffinity(pid_t pid, size_t cpusetsize,
int sched_get_stackinfo(pid_t pid, FAR struct stackinfo_s *stackinfo);
+/********************************************************************************
+ * Name: nx_wait/nx_waitid/nx_waitpid
+ ********************************************************************************/
+
+#ifdef CONFIG_SCHED_WAITPID
+pid_t nx_wait(FAR int *stat_loc);
+int nx_waitid(int idtype, id_t id, FAR siginfo_t *info, int options);
+pid_t nx_waitpid(pid_t pid, FAR int *stat_loc, int options);
+#endif
+
#undef EXTERN
#if defined(__cplusplus)
}
diff --git a/sched/sched/sched_wait.c b/sched/sched/sched_wait.c
index 7dd9070..42e84f3 100644
--- a/sched/sched/sched_wait.c
+++ b/sched/sched/sched_wait.c
@@ -54,6 +54,15 @@
****************************************************************************/
/****************************************************************************
+ * Name: nx_wait
+ ****************************************************************************/
+
+pid_t nx_wait(FAR int *stat_loc)
+{
+ return nx_waitpid((pid_t)-1, stat_loc, 0);
+}
+
+/****************************************************************************
* Name: wait
*
* Description:
@@ -85,7 +94,7 @@ pid_t wait(FAR int *stat_loc)
* trivial case.
*/
- return waitpid((pid_t) - 1, stat_loc, 0);
+ return waitpid((pid_t)-1, stat_loc, 0);
}
#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT */
diff --git a/sched/sched/sched_waitid.c b/sched/sched/sched_waitid.c
index a3431de..edabfee 100644
--- a/sched/sched/sched_waitid.c
+++ b/sched/sched/sched_waitid.c
@@ -93,69 +93,10 @@ static void exited_child(FAR struct tcb_s *rtcb,
****************************************************************************/
/****************************************************************************
- * Name: waitid
- *
- * Description:
- * The waitid() function suspends the calling thread until one child of
- * the process containing the calling thread changes state. It records the
- * current state of a child in the structure pointed to by 'info'. If a
- * child process changed state prior to the call to waitid(), waitid()
- * returns immediately. If more than one thread is suspended in wait() or
- * waitpid() waiting termination of the same process, exactly one thread
- * will return the process status at the time of the target process
- * termination
- *
- * The idtype and id arguments are used to specify which children waitid()
- * will wait for.
- *
- * If idtype is P_PID, waitid() will wait for the child with a process
- * ID equal to (pid_t)id.
- *
- * If idtype is P_PGID, waitid() will wait for any child with a process
- * group ID equal to (pid_t)id.
- *
- * If idtype is P_ALL, waitid() will wait for any children and id is
- * ignored.
- *
- * The options argument is used to specify which state changes waitid()
- * will will wait for. It is formed by OR-ing together one or more of the
- * following flags:
- *
- * WEXITED - Wait for processes that have exited.
- * WSTOPPED - Status will be returned for any child that has stopped
- * upon receipt of a signal.
- * WCONTINUED - Status will be returned for any child that was stopped
- * and has been continued.
- * WNOHANG - Return immediately if there are no children to wait for.
- * WNOWAIT - Keep the process whose status is returned in 'info' in a
- * waitable state. This will not affect the state of the process; the
- * process may be waited for again after this call completes.
- *
- * The 'info' argument must point to a siginfo_t structure. If waitid()
- * returns because a child process was found that satisfied the conditions
- * indicated by the arguments idtype and options, then the structure
- * pointed to by 'info' will be filled in by the system with the status of
- * the process. The si_signo member will always be equal to SIGCHLD.
- *
- * Input Parameters:
- * See description.
- *
- * Returned Value:
- * If waitid() returns due to the change of state of one of its children,
- * 0 is returned. Otherwise, -1 is returned and errno is set to indicate
- * the error.
- *
- * The waitid() function will fail if:
- *
- * ECHILD - The calling process has no existing unwaited-for child
- * processes.
- * EINTR - The waitid() function was interrupted by a signal.
- * EINVAL - An invalid value was specified for options, or idtype and id
- * specify an invalid set of processes.
- *
+ * Name: nx_waitid
****************************************************************************/
-int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
+int nx_waitid(int idtype, id_t id, FAR siginfo_t *info, int options)
{
FAR struct tcb_s *rtcb = this_task();
FAR struct tcb_s *ctcb;
@@ -164,8 +105,7 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
bool retains;
#endif
sigset_t set;
- int errcode;
- int ret;
+ int ret = OK;
/* MISSING LOGIC: If WNOHANG is provided in the options, then this
* function should returned immediately. However, there is no mechanism
@@ -179,8 +119,7 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
if (idtype != P_PID && idtype != P_ALL)
{
- set_errno(ENOSYS);
- return ERROR;
+ return -ENOSYS;
}
/* None of the options are supported except for WEXITED (which must be
@@ -190,15 +129,10 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
if (options != WEXITED)
{
- set_errno(ENOSYS);
- return ERROR;
+ return -ENOSYS;
}
#endif
- /* waitid() is a cancellation point */
-
- enter_cancellation_point();
-
/* Create a signal set that contains only SIGCHLD */
sigemptyset(&set);
@@ -221,8 +155,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
{
/* There are no children */
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
else if (idtype == P_PID)
{
@@ -238,8 +172,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
if (ctcb == NULL || ctcb->group->tg_ppid != rtcb->pid)
#endif
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
/* Does this task retain child status? */
@@ -252,8 +186,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
{
/* This specific pid is not a child */
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
}
@@ -264,8 +198,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
{
/* There are no children */
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
else if (idtype == P_PID)
{
@@ -281,8 +215,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
if (ctcb == NULL || ctcb->group->tg_ppid != rtcb->pid)
#endif
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
#endif
@@ -353,8 +287,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
* to reported ECHILD than bogus status.
*/
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
#else
@@ -372,8 +306,8 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
* Let's return ECHILD.. that is at least informative.
*/
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
#endif
@@ -382,8 +316,7 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
ret = nxsig_waitinfo(&set, info);
if (ret < 0)
{
- errcode = -ret;
- goto errout_with_errno;
+ goto errout;
}
/* Make there this was SIGCHLD */
@@ -417,22 +350,97 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
else /* if (idtype == P_PGID) */
{
- errcode = ENOSYS;
- goto errout_with_errno;
+ ret = -ENOSYS;
+ goto errout;
}
}
}
- leave_cancellation_point();
+errout:
sched_unlock();
- return OK;
+ return ret;
+}
+
+/****************************************************************************
+ * Name: waitid
+ *
+ * Description:
+ * The waitid() function suspends the calling thread until one child of
+ * the process containing the calling thread changes state. It records the
+ * current state of a child in the structure pointed to by 'info'. If a
+ * child process changed state prior to the call to waitid(), waitid()
+ * returns immediately. If more than one thread is suspended in wait() or
+ * waitpid() waiting termination of the same process, exactly one thread
+ * will return the process status at the time of the target process
+ * termination
+ *
+ * The idtype and id arguments are used to specify which children waitid()
+ * will wait for.
+ *
+ * If idtype is P_PID, waitid() will wait for the child with a process
+ * ID equal to (pid_t)id.
+ *
+ * If idtype is P_PGID, waitid() will wait for any child with a process
+ * group ID equal to (pid_t)id.
+ *
+ * If idtype is P_ALL, waitid() will wait for any children and id is
+ * ignored.
+ *
+ * The options argument is used to specify which state changes waitid()
+ * will will wait for. It is formed by OR-ing together one or more of the
+ * following flags:
+ *
+ * WEXITED - Wait for processes that have exited.
+ * WSTOPPED - Status will be returned for any child that has stopped
+ * upon receipt of a signal.
+ * WCONTINUED - Status will be returned for any child that was stopped
+ * and has been continued.
+ * WNOHANG - Return immediately if there are no children to wait for.
+ * WNOWAIT - Keep the process whose status is returned in 'info' in a
+ * waitable state. This will not affect the state of the process; the
+ * process may be waited for again after this call completes.
+ *
+ * The 'info' argument must point to a siginfo_t structure. If waitid()
+ * returns because a child process was found that satisfied the conditions
+ * indicated by the arguments idtype and options, then the structure
+ * pointed to by 'info' will be filled in by the system with the status of
+ * the process. The si_signo member will always be equal to SIGCHLD.
+ *
+ * Input Parameters:
+ * See description.
+ *
+ * Returned Value:
+ * If waitid() returns due to the change of state of one of its children,
+ * 0 is returned. Otherwise, -1 is returned and errno is set to indicate
+ * the error.
+ *
+ * The waitid() function will fail if:
+ *
+ * ECHILD - The calling process has no existing unwaited-for child
+ * processes.
+ * EINTR - The waitid() function was interrupted by a signal.
+ * EINVAL - An invalid value was specified for options, or idtype and id
+ * specify an invalid set of processes.
+ *
+ ****************************************************************************/
-errout_with_errno:
- set_errno(errcode);
+int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
+{
+ int ret;
+
+ /* waitid() is a cancellation point */
+
+ enter_cancellation_point();
+
+ ret = nx_waitid(idtype, id, info, options);
+ if (ret < 0)
+ {
+ set_errno(-ret);
+ ret = ERROR;
+ }
leave_cancellation_point();
- sched_unlock();
- return ERROR;
+ return ret;
}
#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT */
diff --git a/sched/sched/sched_waitpid.c b/sched/sched/sched_waitpid.c
index 8ff5244..45527be 100644
--- a/sched/sched/sched_waitpid.c
+++ b/sched/sched/sched_waitpid.c
@@ -59,144 +59,19 @@
****************************************************************************/
/****************************************************************************
- * Name: waitpid
- *
- * Description:
- * The waitpid() functions will obtain status information pertaining to one
- * of the caller's child processes. The waitpid() function will suspend
- * execution of the calling thread until status information for one of the
- * terminated child processes of the calling process is available, or until
- * delivery of a signal whose action is either to execute a signal-catching
- * function or to terminate the process. 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. If status information is available prior to the
- * call to waitpid(), return will be immediate.
- *
- * The pid argument specifies a set of child processes for which status is
- * requested. The waitpid() function will only return the status of a child
- * process from this set:
- *
- * - If pid is equal to (pid_t)-1, status is requested for any child
- * process. In this respect, waitpid() is then equivalent to wait().
- * - If pid is greater than 0, it specifies the process ID of a single
- * child process for which status is requested.
- * - If pid is 0, status is requested for any child process whose process
- * group ID is equal to that of the calling process.
- * - If pid is less than (pid_t)-1, status is requested for any child
- * process whose process group ID is equal to the absolute value of pid.
- *
- * The options argument is constructed from the bitwise-inclusive OR of
- * zero or more of the following flags, defined in the <sys/wait.h> header:
- *
- * WCONTINUED - The waitpid() function will report the status of any
- * continued child process specified by pid whose status has not been
- * reported since it continued from a job control stop.
- * WNOHANG - The waitpid() function will not suspend execution of the
- * calling thread if status is not immediately available for one of the
- * child processes specified by pid.
- * WUNTRACED - The status of any child processes specified by pid that are
- * stopped, and whose status has not yet been reported since they stopped,
- * will also be reported to the requesting process.
- *
- * If the calling process has SA_NOCLDWAIT set or has SIGCHLD set to
- * SIG_IGN, and the process has no unwaited-for children that were
- * transformed into zombie processes, the calling thread will block until
- * all of the children of the process containing the calling thread
- * terminate, and waitpid() will fail and set errno to ECHILD.
- *
- * If waitpid() returns because the status of a child process is available,
- * these functions will return a value equal to the process ID of the child
- * process. In this case, if the value of the argument stat_loc is not a
- * null pointer, information will be stored in the location pointed to by
- * stat_loc. The value stored at the location pointed to by stat_loc will
- * be 0 if and only if the status returned is from a terminated child
- * process that terminated by one of the following means:
- *
- * 1. The process returned 0 from main().
- * 2. The process called _exit() or exit() with a status argument of 0.
- * 3. The process was terminated because the last thread in the process
- * terminated.
- *
- * Regardless of its value, this information may be interpreted using the
- * following macros, which are defined in <sys/wait.h> and evaluate to
- * integral expressions; the stat_val argument is the integer value pointed
- * to by stat_loc.
- *
- * WIFEXITED(stat_val) - Evaluates to a non-zero value if status was
- * returned for a child process that terminated normally.
- * WEXITSTATUS(stat_val) - If the value of WIFEXITED(stat_val) is non-zero,
- * this macro evaluates to the low-order 8 bits of the status argument
- * that the child process passed to _exit() or exit(), or the value the
- * child process returned from main().
- * WIFSIGNALED(stat_val) - Evaluates to a non-zero value if status was
- * returned for a child process that terminated due to the receipt of a
- * signal that was not caught (see <signal.h>).
- * WTERMSIG(stat_val) - If the value of WIFSIGNALED(stat_val) is non-zero,
- * this macro evaluates to the number of the signal that caused the
- * termination of the child process.
- * WIFSTOPPED(stat_val) - Evaluates to a non-zero value if status was
- * returned for a child process that is currently stopped.
- * WSTOPSIG(stat_val) - If the value of WIFSTOPPED(stat_val) is non-zero,
- * this macro evaluates to the number of the signal that caused the child
- * process to stop.
- * WIFCONTINUED(stat_val) - Evaluates to a non-zero value if status was
- * returned for a child process that has continued from a job control
- * stop.
- *
- * Input Parameters:
- * pid - The task ID of the thread to waid for
- * stat_loc - The location to return the exit status
- * options - ignored
- *
- * Returned Value:
- * If waitpid() returns because the status of a child process is available,
- * it will return a value equal to the process ID of the child process for
- * which status is reported.
- *
- * If waitpid() returns due to the delivery of a signal to the calling
- * process, -1 will be returned and errno set to EINTR.
- *
- * If waitpid() was invoked with WNOHANG set in options, it has at least
- * one child process specified by pid for which status is not available,
- * and status is not available for any process specified by pid, 0 is
- * returned.
- *
- * Otherwise, (pid_t)-1 will be returned, and errno set to indicate the
- * error:
- *
- * ECHILD - The process specified by pid does not exist or is not a child
- * of the calling process, or the process group specified by pid
- * does not exist does not have any member process that is a child
- * of the calling process.
- * EINTR - The function was interrupted by a signal. The value of the
- * location pointed to by stat_loc is undefined.
- * EINVAL - The options argument is not valid.
- *
- * Assumptions:
- *
- * Compatibility
- * If there is no SIGCHLD signal supported (CONFIG_SCHED_HAVE_PARENT not
- * defined), then waitpid() is still available, but does not obey the
- * restriction that the pid be a child of the caller.
- *
+ * Name: nx_waitpid
****************************************************************************/
#ifndef CONFIG_SCHED_HAVE_PARENT
-pid_t waitpid(pid_t pid, int *stat_loc, int options)
+pid_t nx_waitpid(pid_t pid, int *stat_loc, int options)
{
FAR struct tcb_s *ctcb;
FAR struct task_group_s *group;
bool mystat = false;
- int errcode;
int ret;
DEBUGASSERT(stat_loc);
- /* waitpid() is a cancellation point */
-
- enter_cancellation_point();
-
/* Disable pre-emption so that nothing changes in the following tests */
sched_lock();
@@ -206,8 +81,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
ctcb = sched_gettcb(pid);
if (ctcb == NULL)
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
/* Then the task group corresponding to this PID */
@@ -249,50 +124,46 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
/* Don't wait if status is not available */
ret = nxsem_trywait(&group->tg_exitsem);
- group_delwaiter(group);
-
- if (ret < 0)
- {
- pid = 0;
- }
}
else
{
/* Wait if necessary for status to become available */
ret = nxsem_wait(&group->tg_exitsem);
- group_delwaiter(group);
+ }
- if (ret < 0)
- {
- /* Unlock pre-emption and return the ERROR (nxsem_wait has already
- * set the errno). Handle the awkward case of whether or not we
- * need to nullify the stat_loc value.
- */
+ group_delwaiter(group);
- if (mystat)
- {
- group->tg_statloc = NULL;
- group->tg_waitflags = 0;
- }
+ if (ret < 0)
+ {
+ /* Handle the awkward case of whether or not we
+ * need to nullify the stat_loc value.
+ */
+
+ if (mystat)
+ {
+ group->tg_statloc = NULL;
+ group->tg_waitflags = 0;
+ }
- errcode = -ret;
- goto errout_with_errno;
+ if ((options & WNOHANG) != 0)
+ {
+ pid = 0;
+ }
+ else
+ {
+ goto errout;
}
}
/* On success, return the PID */
- leave_cancellation_point();
sched_unlock();
return pid;
-errout_with_errno:
- set_errno(errcode);
-
- leave_cancellation_point();
+errout:
sched_unlock();
- return ERROR;
+ return ret;
}
/****************************************************************************
@@ -309,7 +180,7 @@ errout_with_errno:
****************************************************************************/
#else
-pid_t waitpid(pid_t pid, int *stat_loc, int options)
+pid_t nx_waitpid(pid_t pid, int *stat_loc, int options)
{
FAR struct tcb_s *rtcb = this_task();
FAR struct tcb_s *ctcb;
@@ -319,15 +190,10 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
#endif
FAR struct siginfo info;
sigset_t set;
- int errcode;
int ret;
DEBUGASSERT(stat_loc);
- /* waitpid() is a cancellation point */
-
- enter_cancellation_point();
-
/* Create a signal set that contains only SIGCHLD */
sigemptyset(&set);
@@ -348,8 +214,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
if (rtcb->group->tg_children == NULL && retains)
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
else if (pid != (pid_t)-1)
{
@@ -368,8 +234,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
if (ctcb->group->tg_ppid != rtcb->pid)
#endif
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
@@ -383,8 +249,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
if (group_findchild(rtcb->group, pid) == NULL)
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
}
@@ -395,8 +261,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
/* There are no children */
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
else if (pid != (pid_t)-1)
{
@@ -412,8 +278,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
if (ctcb == NULL || ctcb->group->tg_ppid != rtcb->pid)
#endif
{
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
@@ -497,8 +363,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
* to reported ECHILD than bogus status.
*/
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
}
@@ -518,8 +384,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
* Let's return ECHILD.. that is at least informative.
*/
- errcode = ECHILD;
- goto errout_with_errno;
+ ret = -ECHILD;
+ goto errout;
}
#endif /* CONFIG_SCHED_CHILD_STATUS */
@@ -529,8 +395,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
ret = nxsig_waitinfo(&set, &info);
if (ret < 0)
{
- errcode = -ret;
- goto errout_with_errno;
+ goto errout;
}
/* Was this the death of the thread we were waiting for? In the of
@@ -567,17 +432,158 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
}
}
- leave_cancellation_point();
sched_unlock();
- return (int)pid;
-
-errout_with_errno:
- set_errno(errcode);
+ return pid;
- leave_cancellation_point();
+errout:
sched_unlock();
- return ERROR;
+ return ret;
}
#endif /* CONFIG_SCHED_HAVE_PARENT */
+/****************************************************************************
+ * Name: waitpid
+ *
+ * Description:
+ * The waitpid() functions will obtain status information pertaining to one
+ * of the caller's child processes. The waitpid() function will suspend
+ * execution of the calling thread until status information for one of the
+ * terminated child processes of the calling process is available, or until
+ * delivery of a signal whose action is either to execute a signal-catching
+ * function or to terminate the process. 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. If status information is available prior to the
+ * call to waitpid(), return will be immediate.
+ *
+ * The pid argument specifies a set of child processes for which status is
+ * requested. The waitpid() function will only return the status of a child
+ * process from this set:
+ *
+ * - If pid is equal to (pid_t)-1, status is requested for any child
+ * process. In this respect, waitpid() is then equivalent to wait().
+ * - If pid is greater than 0, it specifies the process ID of a single
+ * child process for which status is requested.
+ * - If pid is 0, status is requested for any child process whose process
+ * group ID is equal to that of the calling process.
+ * - If pid is less than (pid_t)-1, status is requested for any child
+ * process whose process group ID is equal to the absolute value of pid.
+ *
+ * The options argument is constructed from the bitwise-inclusive OR of
+ * zero or more of the following flags, defined in the <sys/wait.h> header:
+ *
+ * WCONTINUED - The waitpid() function will report the status of any
+ * continued child process specified by pid whose status has not been
+ * reported since it continued from a job control stop.
+ * WNOHANG - The waitpid() function will not suspend execution of the
+ * calling thread if status is not immediately available for one of the
+ * child processes specified by pid.
+ * WUNTRACED - The status of any child processes specified by pid that are
+ * stopped, and whose status has not yet been reported since they stopped,
+ * will also be reported to the requesting process.
+ *
+ * If the calling process has SA_NOCLDWAIT set or has SIGCHLD set to
+ * SIG_IGN, and the process has no unwaited-for children that were
+ * transformed into zombie processes, the calling thread will block until
+ * all of the children of the process containing the calling thread
+ * terminate, and waitpid() will fail and set errno to ECHILD.
+ *
+ * If waitpid() returns because the status of a child process is available,
+ * these functions will return a value equal to the process ID of the child
+ * process. In this case, if the value of the argument stat_loc is not a
+ * null pointer, information will be stored in the location pointed to by
+ * stat_loc. The value stored at the location pointed to by stat_loc will
+ * be 0 if and only if the status returned is from a terminated child
+ * process that terminated by one of the following means:
+ *
+ * 1. The process returned 0 from main().
+ * 2. The process called _exit() or exit() with a status argument of 0.
+ * 3. The process was terminated because the last thread in the process
+ * terminated.
+ *
+ * Regardless of its value, this information may be interpreted using the
+ * following macros, which are defined in <sys/wait.h> and evaluate to
+ * integral expressions; the stat_val argument is the integer value pointed
+ * to by stat_loc.
+ *
+ * WIFEXITED(stat_val) - Evaluates to a non-zero value if status was
+ * returned for a child process that terminated normally.
+ * WEXITSTATUS(stat_val) - If the value of WIFEXITED(stat_val) is non-zero,
+ * this macro evaluates to the low-order 8 bits of the status argument
+ * that the child process passed to _exit() or exit(), or the value the
+ * child process returned from main().
+ * WIFSIGNALED(stat_val) - Evaluates to a non-zero value if status was
+ * returned for a child process that terminated due to the receipt of a
+ * signal that was not caught (see <signal.h>).
+ * WTERMSIG(stat_val) - If the value of WIFSIGNALED(stat_val) is non-zero,
+ * this macro evaluates to the number of the signal that caused the
+ * termination of the child process.
+ * WIFSTOPPED(stat_val) - Evaluates to a non-zero value if status was
+ * returned for a child process that is currently stopped.
+ * WSTOPSIG(stat_val) - If the value of WIFSTOPPED(stat_val) is non-zero,
+ * this macro evaluates to the number of the signal that caused the child
+ * process to stop.
+ * WIFCONTINUED(stat_val) - Evaluates to a non-zero value if status was
+ * returned for a child process that has continued from a job control
+ * stop.
+ *
+ * Input Parameters:
+ * pid - The task ID of the thread to waid for
+ * stat_loc - The location to return the exit status
+ * options - ignored
+ *
+ * Returned Value:
+ * If waitpid() returns because the status of a child process is available,
+ * it will return a value equal to the process ID of the child process for
+ * which status is reported.
+ *
+ * If waitpid() returns due to the delivery of a signal to the calling
+ * process, -1 will be returned and errno set to EINTR.
+ *
+ * If waitpid() was invoked with WNOHANG set in options, it has at least
+ * one child process specified by pid for which status is not available,
+ * and status is not available for any process specified by pid, 0 is
+ * returned.
+ *
+ * Otherwise, (pid_t)-1 will be returned, and errno set to indicate the
+ * error:
+ *
+ * ECHILD - The process specified by pid does not exist or is not a child
+ * of the calling process, or the process group specified by pid
+ * does not exist does not have any member process that is a child
+ * of the calling process.
+ * EINTR - The function was interrupted by a signal. The value of the
+ * location pointed to by stat_loc is undefined.
+ * EINVAL - The options argument is not valid.
+ *
+ * Assumptions:
+ *
+ * Compatibility
+ * If there is no SIGCHLD signal supported (CONFIG_SCHED_HAVE_PARENT not
+ * defined), then waitpid() is still available, but does not obey the
+ * restriction that the pid be a child of the caller.
+ *
+ ****************************************************************************/
+
+pid_t waitpid(pid_t pid, int *stat_loc, int options)
+{
+ pid_t ret;
+
+ /* waitpid() is a cancellation point */
+
+ enter_cancellation_point();
+
+ /* Let nx_waitpid() do the work. */
+
+ ret = nx_waitpid(pid, stat_loc, options);
+ if (ret < 0)
+ {
+ set_errno(-ret);
+ ret = ERROR;
+ }
+
+ leave_cancellation_point();
+ return ret;
+}
+
#endif /* CONFIG_SCHED_WAITPID */