summaryrefslogtreecommitdiff
path: root/nuttx/sched
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-11 16:53:44 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-11 16:53:44 +0000
commit7272d1e7473fc1ce1d0a29c7287260402ca2420e (patch)
tree46e6b528a6ace37a9ec35f2e4c1d7d3fe8b510f5 /nuttx/sched
parent8b26f2afdf93273f95e24840b68df485f971f89a (diff)
downloadpx4-nuttx-7272d1e7473fc1ce1d0a29c7287260402ca2420e.tar.gz
px4-nuttx-7272d1e7473fc1ce1d0a29c7287260402ca2420e.tar.bz2
px4-nuttx-7272d1e7473fc1ce1d0a29c7287260402ca2420e.zip
Various changes while debugging posix_spawn
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5510 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/sched')
-rw-r--r--nuttx/sched/task_vfork.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/nuttx/sched/task_vfork.c b/nuttx/sched/task_vfork.c
index 64f6f0636..0ea09b048 100644
--- a/nuttx/sched/task_vfork.c
+++ b/nuttx/sched/task_vfork.c
@@ -218,6 +218,9 @@ pid_t task_vforkstart(FAR _TCB *child)
#endif
FAR const char *name;
pid_t pid;
+#ifdef CONFIG_SCHED_WAITPID
+ int rc;
+#endif
int ret;
svdbg("Starting Child TCB=%p, parent=%p\n", child, g_readytorun.head);
@@ -246,6 +249,64 @@ pid_t task_vforkstart(FAR _TCB *child)
return ERROR;
}
+ /* Since the child task has the same priority as the parent task, it is
+ * now ready to run, but has not yet ran. It is a requirement that
+ * the parent enivornment be stable while vfork runs; the child thread
+ * is still dependent on things in the parent thread... like the pointers
+ * into parent thread's stack which will still appear in the child's
+ * registers and environment.
+ *
+ * We do not have SIG_CHILD, so we have to do some silly things here.
+ * The simplest way to make sure that the child thread runs to completion
+ * is simply to yield here. Since the child can only do exit() or
+ * execv/l(), that should be all that is needed.
+ *
+ * Hmmm.. this is probably not sufficient. What if we are running
+ * SCHED_RR? What if the child thread is suspeneded and rescheduled
+ * after the parent thread again?
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+
+ /* We can also exploit a bug in the execv() implementation: The PID
+ * of the task exec'ed by the child will not be the same as the PID of
+ * the child task. Therefore, waitpid() on the child task's PID will
+ * accomplish what we need to do.
+ */
+
+ rc = 0;
+
+#ifdef CONFIG_DEBUG
+ ret = waitpid(pid, &rc, 0);
+ if (ret < 0)
+ {
+ sdbg("ERROR: waitpid failed: %d\n", errno);
+ }
+#else
+ (void)waitpid(pid, &rc, 0);
+#endif
+
+#else
+ /* Again exploiting that execv() bug: Check if the child thread is
+ * still running.
+ */
+
+ while ((ret = kill(pid, 0)) == OK)
+ {
+ /* Yes.. then we can yield to it -- assuming that it has not lowered
+ * its priority. sleep(0) might be a safer thing to do since it does
+ * not depend on prioirities: It will halt the parent thread for one
+ * system clock tick. This will delay the return to the parent thread.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ sleep(0);
+#else
+ sched_yield();
+#endif
+ }
+#endif
+
return pid;
}