diff --git a/ChangeLog b/ChangeLog index 7ddc4901e8..63aac89f54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3905,4 +3905,6 @@ (from Max Holtzberg). * configs/stm32f4discovery/posix_spawn: Added a configuration that can be used for testing posix_spawn(). + * arch/arm/src/stm32: Bring F1 support for general DMA and serial + DMA in paricular up to parity with F2/F4 (from Mike Smith). diff --git a/include/spawn.h b/include/spawn.h index 3978424fbf..39ed9be15c 100644 --- a/include/spawn.h +++ b/include/spawn.h @@ -61,7 +61,7 @@ #define POSIX_SPAWN_SETSCHEDPARAM (1 << 2) /* 1: Set task's priority */ #define POSIX_SPAWN_SETSCHEDULER (1 << 3) /* 1: Set task's scheduler policy */ #define POSIX_SPAWN_SETSIGDEF (1 << 4) /* 1: Set default signal actions */ -#define POSIX_SPAWN_SETSIGMASK (1 << 5) /* 1: Set sigmask *./ +#define POSIX_SPAWN_SETSIGMASK (1 << 5) /* 1: Set sigmask */ /**************************************************************************** * Type Definitions @@ -181,6 +181,16 @@ int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr, # define posix_spawnattr_setsigmask(attr,sigmask) (ENOSYS) #endif +/* Non standard debug functions */ + +#ifdef CONFIG_DEBUG +void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions); +void posix_spawnattr_dump(FAR posix_spawnattr_t *attr); +#else +# define posix_spawn_file_actions_dump(fa) +# define posix_spawnattr_dump(a) +#endif + #ifdef __cplusplus } #endif diff --git a/libc/spawn/Make.defs b/libc/spawn/Make.defs index 2cf75c410d..99ee781ce2 100644 --- a/libc/spawn/Make.defs +++ b/libc/spawn/Make.defs @@ -42,6 +42,10 @@ CSRCS += lib_ps.c CSRCS += lib_psfa_addaction.c lib_psfa_addclose.c lib_psfa_adddup2.c CSRCS += lib_psfa_addopen.c lib_psfa_destroy.c lib_psfa_init.c +ifeq ($(CONFIG_DEBUG),y) +CSRCS += lib_psfa_dump.c +endif + CSRCS += lib_psa_getflags.c lib_psa_getschedparam.c lib_psa_getschedpolicy.c CSRCS += lib_psa_init.c lib_psa_setflags.c lib_psa_setschedparam.c CSRCS += lib_psa_setschedpolicy.c @@ -50,6 +54,10 @@ ifneq ($(CONFIG_DISABLE_SIGNALS),y) CSRCS += lib_psa_getsigmask.c lib_psa_setsigmask.c endif +ifeq ($(CONFIG_DEBUG),y) +CSRCS += lib_psa_dump.c +endif + # Add the spawn directory to the build DEPPATH += --dep-path spawn diff --git a/libc/spawn/lib_ps.c b/libc/spawn/lib_ps.c index 7509d67377..a6a0590d4a 100644 --- a/libc/spawn/lib_ps.c +++ b/libc/spawn/lib_ps.c @@ -357,7 +357,7 @@ static int spawn_proxy(int argc, char *argv[]) { FAR struct spawn_general_file_action_s *entry; FAR const posix_spawnattr_t *attr = g_ps_parms.attr; - int ret; + int ret = OK; /* Perform file actions and/or set a custom signal mask. We get here only * if the file_actions parameter to posix_spawn[p] was non-NULL and/or the @@ -365,10 +365,10 @@ static int spawn_proxy(int argc, char *argv[]) */ #ifndef CONFIG_DISABLE_SIGNALS - DEBUGASSERT(g_ps_parms.file_actions || + DEBUGASSERT((g_ps_parms.file_actions && *g_ps_parms.file_actions) || (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)); #else - DEBUGASSERT(g_ps_parms.file_actions); + DEBUGASSERT(g_ps_parms.file_actions && *g_ps_parms.file_actions); #endif /* Check if we need to change the signal mask */ @@ -553,9 +553,10 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path, */ #ifndef CONFIG_DISABLE_SIGNALS - if (!file_actions && (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0) + if ((file_actions == NULL || *file_actions == NULL) && + (attr == NULL || (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0)) #else - if (!file_actions) + if (file_actions == NULL || *file_actions == NULL) #endif { return ps_exec(pid, path, attr, argv); @@ -601,7 +602,7 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path, proxy = TASK_CREATE("spawn_proxy", param.sched_priority, CONFIG_POSIX_SPAWN_STACKSIZE, (main_t)spawn_proxy, - (const char **)NULL); + (FAR const char **)NULL); if (proxy < 0) { int errcode = errno; diff --git a/libc/spawn/lib_psa_dump.c b/libc/spawn/lib_psa_dump.c new file mode 100644 index 0000000000..03770c6ff8 --- /dev/null +++ b/libc/spawn/lib_psa_dump.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * libc/string/lib_psa_dump.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include + +#ifdef CONFIG_DEBUG + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: posix_spawnattr_dump + * + * Description: + * Show the current attributes. + * + * Input Parameters: + * attr - The address of the spawn attributes to be dumped. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void posix_spawnattr_dump(posix_spawnattr_t *attr) +{ + dbg("attr[%p]:\n", attr); + dbg(" flags: %04x\n", attr->flags); + if (attr->flags == 0) + { + dbg(" None\n"); + } + else + { + if ((attr->flags & POSIX_SPAWN_RESETIDS) != 0) + { + dbg(" POSIX_SPAWN_RESETIDS\n"); + } + + if ((attr->flags & POSIX_SPAWN_SETPGROUP) != 0) + { + dbg(" POSIX_SPAWN_SETPGROUP\n"); + } + + if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0) + { + dbg(" POSIX_SPAWN_SETSCHEDPARAM\n"); + } + + if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0) + { + dbg(" POSIX_SPAWN_SETSCHEDULER\n"); + } + + if ((attr->flags & POSIX_SPAWN_SETSIGDEF) != 0) + { + dbg(" POSIX_SPAWN_SETSIGDEF\n"); + } + + if ((attr->flags & POSIX_SPAWN_SETSIGMASK) != 0) + { + dbg(" POSIX_SPAWN_SETSIGMASK\n"); + } + } + + dbg(" priority: %d\n", attr->priority); + + dbg(" policy: %d\n", attr->policy); + if (attr->policy == SCHED_FIFO) + { + dbg(" SCHED_FIFO\n"); + } + else if (attr->policy == SCHED_RR) + { + dbg(" SCHED_RR\n"); + } + else + { + dbg(" Unrecognized\n"); + } + +#ifndef CONFIG_DISABLE_SIGNALS + dbg(" sigmask: %08x\n", attr->sigmask); +#endif +}; + +#endif /* CONFIG_DEBUG */ \ No newline at end of file diff --git a/libc/spawn/lib_psa_init.c b/libc/spawn/lib_psa_init.c index 8aabfd090d..f76188c52b 100644 --- a/libc/spawn/lib_psa_init.c +++ b/libc/spawn/lib_psa_init.c @@ -43,7 +43,6 @@ #include #include #include -#include /**************************************************************************** * Global Functions @@ -58,7 +57,7 @@ * call to posix_spawn() or posix_spawnp(). * * Input Parameters: - * attr - The address spawn attributes to be initialized. + * attr - The address of the spawn attributes to be initialized. * * Returned Value: * On success, these functions return 0; on failure they return an error diff --git a/libc/spawn/lib_psfa_dump.c b/libc/spawn/lib_psfa_dump.c new file mode 100644 index 0000000000..d7bf1576de --- /dev/null +++ b/libc/spawn/lib_psfa_dump.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * libc/string/lib_psfa_dump.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include "spawn/spawn.h" + +#ifdef CONFIG_DEBUG + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_psfa_dump + * + * Description: + * Show the entryent file actions. + * + * Input Parameters: + * file_actions - The address of the file_actions to be dumped. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions) +{ + FAR struct spawn_general_file_action_s *entry; + + DEBUGASSERT(file_actions); + + dbg("File Actions[%p->%p]:\n", file_actions, *file_actions); + if (!*file_actions) + { + dbg(" NONE\n"); + return; + } + + /* Destroy each file action, one at a time */ + + for (entry = (FAR struct spawn_general_file_action_s *)*file_actions; + entry; + entry = entry->flink) + { + switch (entry->action) + { + case SPAWN_FILE_ACTION_CLOSE: + { + FAR struct spawn_close_file_action_s *action = + (FAR struct spawn_close_file_action_s *)entry; + + dbg(" CLOSE: fd=%d\n", action->fd); + } + break; + + case SPAWN_FILE_ACTION_DUP2: + { + FAR struct spawn_dup2_file_action_s *action = + (FAR struct spawn_dup2_file_action_s *)entry; + + dbg(" DUP2: %d->%d\n", action->fd1, action->fd2); + } + break; + + case SPAWN_FILE_ACTION_OPEN: + { + FAR struct spawn_open_file_action_s *action = + (FAR struct spawn_open_file_action_s *)entry; + + svdbg(" OPEN: path=%s oflags=%04x mode=%04x fd=%d\n", + action->path, action->oflags, action->mode, action->fd); + } + break; + + case SPAWN_FILE_ACTION_NONE: + default: + dbg(" ERROR: Unknown action: %d\n", entry->action); + break; + } + } +} + +#endif /* CONFIG_DEBUG */ \ No newline at end of file diff --git a/sched/task_vfork.c b/sched/task_vfork.c index 64f6f06366..0ea09b0487 100644 --- a/sched/task_vfork.c +++ b/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; }