9
0
Fork 0

New interface task_spawn(); exec_builtin() now uses task_spawn(); All argv types should be char * const * not const char **

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5598 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-02-02 19:31:30 +00:00
parent f1851b468b
commit 60185fe969
41 changed files with 1453 additions and 371 deletions

View File

@ -4100,3 +4100,10 @@
* drivers/serial/serial.c: Correct some race conditions when checking
for disconnection of a removable serial device.
* sched/task_posixspawn.c, task_spawn.c, task_spawnparms.c and
spawn_internal.h: Create new interface task_spawn() that is
like posix_spawn(), but uses entry point addresses like
task_create().
* Corrected all argv[] arguments. Should be char * const *, not
const char **.

View File

@ -13,7 +13,7 @@
<h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1>
<p><small>by</small></p>
<p>Gregory Nutt<p>
<p>Last Updated: January 23, 2013</p>
<p>Last Updated: February 2, 2013</p>
</td>
</tr>
</table>
@ -221,7 +221,6 @@ paragraphs.
<p>
Standard <code>posix_spawn</code> interfaces:
</p>
<ul>
<li><a href="#posix_spawn">2.1.11 posix_spawn and posix_spawnp</a></li>
<li><a href="#posix_spawn_file_actions_init">2.1.12 posix_spawn_file_actions_init</a></li>
@ -239,6 +238,14 @@ paragraphs.
<li><a href="#posix_spawnattr_setschedpolicy">2.1.24 posix_spawnattr_setschedpolicy</a></li>
<li><a href="#posix_spawnattr_setsigmask">2.1.25 posix_spawnattr_setsigmask</a></li>
</ul>
<p>
Non-standard task control interfaces inspired by <code>posix_spawn</code>:
</p>
<ul>
<li><a href="#task_spawn">2.1.26 task_spawn</a></li>
<li><a href="#task_spawnattr_getstacksize">2.1.27 task_spawnattr_getstacksize</a></li>
<li><a href="#task_spawnattr_setstacksize">2.1.28 task_spawnattr_setstacksize</a></li>
</ul>
<H3><a name="taskcreate">2.1.1 task_create</a></H3>
@ -246,7 +253,7 @@ paragraphs.
<b>Function Prototype:</b>
<ul><pre>
#include &lt;sched.h&gt;
int task_create(char *name, int priority, int stack_size, main_t entry, const char *argv[]);
int task_create(char *name, int priority, int stack_size, main_t entry, char * const argv[]);
</pre></ul>
<p>
@ -336,7 +343,7 @@ VxWorks provides the following similar interface:
<pre>
#include &lt;sched.h&gt;
int task_init(_TCB *tcb, char *name, int priority, uint32_t *stack, uint32_t stack_size,
maint_t entry, const char *argv[]);
maint_t entry, char * const argv[]);
</pre>
<p>
@ -831,7 +838,7 @@ int posix_spawnp(FAR pid_t *pid, FAR const char *file,
</pre></ul>
<p>
<b>Description:</b>
The <code>posix_spawn()</code> and <code>posix_spawnp()</code> functions will create a new, child task, constructed from a regular executable file.<p>
The <code>posix_spawn()</code> and <code>posix_spawnp()</code> functions will create a new, child task, constructed from a regular executable file.
</p>
<p>
<b>Input Parameters:</b>
@ -1403,6 +1410,206 @@ int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr, FAR const sigset_t *
On success, this function returns 0; on failure it will return an error number from <code>&lt;errno.h&gt;</code>
</p>
<h3><a name="task_spawn">2.1.26 task_spawn</a></h3>
<p>
<b>Function Prototype:</b>
</p>
<ul><pre>
#include &lt;spawn.h&gt;
int task_spawn(FAR pid_t *pid, FAR const char *name, main_t entry,
FAR const posix_spawn_file_actions_t *file_actions,
FAR const posix_spawnattr_t *attr,
FAR char *const argv[], FAR char *const envp[]);
</pre></ul>
<p>
<b>Description:</b>
The <code>task_spawn()</code> function will create a new, child task, where the entry point to the task is an address in memory.
</p>
</p>
<ul>
<li>
<p>
<code>pid</code>:
Upon successful completion, <code>task_spawn()</code> will return the task ID of the child task to the parent task, in the variable pointed to by a non-NULL <code>pid</code> argument.
If the <code>pid</code> argument is a null pointer, the process ID of the child is not returned to the caller.
</p>
</li>
<li>
<p>
<code>name</code>:
The name to assign to the child task.
</p>
</li>
<li>
<p>
<code>entry</code>:
The child task's entry point (an address in memory).
</p>
</li>
<li>
<p>
<code>file_actions</code>:
If <code>file_actions</code> is a null pointer, then file descriptors open in the calling process will remain open in the child process (unless <code>CONFIG_FDCLONE_STDIO</code> is defined).
If <code>file_actions</code> is not NULL, then the file descriptors open in the child process will be those open in the calling process as modified by the spawn file actions object pointed to by <code>file_actions</code>.
</p>
</li>
<li>
<p>
<code>attr</code>:
If the value of the <code>attr</code> parameter is <code>NULL</code>, the all default values for the POSIX spawn attributes will be used.
Otherwise, the attributes will be set according to the spawn flags.
The <code>posix_spawnattr_t</code> spawn attributes object type is defined in <code>spawn.h</code>.
It will contains these attributes, not all of which are supported by NuttX:
</p>
<ul>
<li>
<code>POSIX_SPAWN_SETPGROUP</code>:
Setting of the new task's process group is not supported.
NuttX does not support process groups.
</li>
<li>
<code>POSIX_SPAWN_SETSCHEDPARAM</code>:
Set new tasks priority to the <code>sched_param</code> value.
</li>
<li>
<code>POSIX_SPAWN_SETSCHEDULER</code>:
Set the new task's scheduler policy to the <code>sched_policy</code> value.
</li>
<li>
<code>POSIX_SPAWN_RESETIDS</code>
Resetting of the effective user ID of the child process is not supported.
NuttX does not support effective user IDs.
</li>
<li>
<code>POSIX_SPAWN_SETSIGMASK</code>:
Set the new task's signal mask.
</li>
<li>
<code>POSIX_SPAWN_SETSIGDEF</code>:
Resetting signal default actions is not supported.
NuttX does not support default signal actions.
</li>
</ul>
<p>
And the non-standard:
</p>
<ul>
<li>
<code>TASK_SPAWN_SETSTACKSIZE</code>:
Set the stack size for the new task.
</li>
</ul>
</li>
<li>
<p>
<code>argv</code>:
<code>argv[]</code> is the argument list for the new task. <code>argv[]</code> is an array of pointers to null-terminated strings.
The list is terminated with a null pointer.
</p>
</li>
<li>
<p>
<code>envp</code>:
The <code>envp[]</code> argument is not used by NuttX and may be <code>NULL</code>.
</p>
</li>
</ul>
<p>
<b>Returned Value:</b>
<code>task_spawn()</code> will return zero on success.
Otherwise, an error number will be returned as the function return value to indicate the error:
</p>
<p>
<b>POSIX Compatibility:</b>
This is a non-standard interface inspired by <code>posix_spawn()</code>.
</p>
<h3><a name="task_spawnattr_getstacksize">2.1.26 task_spawnattr_getstacksize</a></h3>
<p>
<b>Function Prototype:</b>
</p>
<ul><pre>
#include &lt;spawn.h&gt;
int task_spawnattr_getstacksize(FAR const posix_spawnattr_t *attr, FAR size_t *stacksize);
</pre></ul>
<p>
<b>Description:</b>
The <code>task_spawnattr_getstacksize()</code> function will obtain the value of the <i>spawn-stacksize</i> attribute from the attributes object referenced by <code>attr</code>.
</p>
<p>
<b>Input Parameters:</b>
</p>
<ul>
<li>
<code>attr</code>:
The address spawn attributes to be queried.
</li>
<li>
<code>policy</code>:
The location to return the <i>spawn-stacksize</i> value.
</li>
</ul>
<p>
<b>Returned Value:</b>
On success, this function returns 0; on failure it will return an error number from <code>&lt;errno.h&gt;</code>
</p>
<h3><a name="task_spawnattr_setstacksize">2.1.26 task_spawnattr_setstacksize</a></h3>
<p>
<b>Function Prototype:</b>
</p>
<ul><pre>
#include &lt;spawn.h&gt;
int task_spawnattr_setstacksize(FAR posix_spawnattr_t *attr, size_t stacksize);
</pre></ul>
<p>
<b>Description:</b>
The <code>task_spawnattr_setstacksize()</code> function will set the <i>spawn-stacksize</i> attribute in an initialized attributes object referenced by <code>attr</code>.
</p>
<p>
<b>Input Parameters:</b>
</p>
<ul>
<li>
<code>attr</code>:
The address spawn attributes to be used.
</li>
<li>
<code>policy</code>:
The new value of the <i>spawn-stacksize</i> attribute.
</li>
</ul>
<p>
<b>Returned Value:</b>
On success, this function returns 0; on failure it will return an error number from <code>&lt;errno.h&gt;</code>
</p>
<h3><a name="posix_spawn_file_actions_init">2.1.12 posix_spawn_file_actions_init</a></h3>
<p>
<b>Function Prototype:</b>
</p>
<ul><pre>
#include &lt;spawn.h&gt;
int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions);
</pre></ul>
<p>
<b>Description:</b>
The <code>posix_spawn_file_actions_init()</code> function initializes the object referenced by <code>file_actions</code> to an empty set of file actions for subsequent use in a call to <code>posix_spawn()</code> or <code>posix_spawnp()</code>.
</p>
<p>
<b>Input Parameters:</b>
</p>
<ul>
<li>
<code>file_actions</code>:
The address of the <code>posix_spawn_file_actions_t</code> to be initialized.
</li>
</ul>
<p>
<b>Returned Value:</b>
On success, this function returns 0; on failure it will return an error number from <code>&lt;errno.h&gt;</code>.
<p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>
@ -9277,9 +9484,9 @@ notify a task when a message is available on a queue.
<li><a href="#poll">poll</a></li>
<li><a href="#drvrpollops">poll.h</a></li>
<li><a href="#posix_spawn">posix_spawn</a></li>
<li><a href="#posix_spawn_file_actions_addclose">posix_spawn_file_actions_addclose</a></li>
</td>
<td valign="top" width="33%">
<li><a href="#posix_spawn_file_actions_addclose">posix_spawn_file_actions_addclose</a></li>
<li><a href="#posix_spawn_file_actions_adddup2">posix_spawn_file_actions_adddup2</a></li>
<li><a href="#posix_spawn_file_actions_addopen">posix_spawn_file_actions_addopen</a></li>
<li><a href="#posix_spawn_file_actions_destroy">posix_spawn_file_actions_destroy</a></li>
@ -9362,10 +9569,10 @@ notify a task when a message is available on a queue.
<li><a href="#standardio">rename</a></li>
<li><a href="#standardio">rmdir</a></li>
<li><a href="#dirdirentops">rewinddir</a></li>
</td>
<td valign="top">
<li><a href="#mmapxip">ROM disk driver</a></li>
<li><a href="#mmapxip">ROMFS</a></li>
</td>
<td valign="top">
<li><a href="#schedgetparam">sched_getparam</a></li>
<li><a href="#schedgetprioritymax">sched_get_priority_max</a></li>
<li><a href="#schedgetprioritymin">sched_get_priority_min</a></li>
@ -9419,8 +9626,11 @@ notify a task when a message is available on a queue.
<li><a href="#taskdelete">task_delete</a></li>
<li><a href="#taskinit">task_init</a></li>
<li><a href="#taskrestart">task_restart</a></li>
<li><a href="#Task_Switch">Task Control Interfaces</a>
<li><a href="#Task_Schedule">Task Scheduling Interfaces</a>
<li><a href="#task_spawn">task_spawn</a></li>
<li><a href="#task_spawnattr_getstacksize">task_spawnattr_getstacksize</a></li>
<li><a href="#task_spawnattr_setstacksize">task_spawnattr_setstacksize</a></li>
<li><a href="#Task_Switch">Task Switching Interfaces</a>
<li><a href="#dirdirentops">telldir</a></li>
<li><a href="#timercreate">timer_create</a></li>
<li><a href="#timerdelete">timer_delete</a></li>

View File

@ -1,4 +1,4 @@
NuttX TODO List (Last updated January 30, 2013)
NuttX TODO List (Last updated February 2, 2013)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -45,7 +45,7 @@ nuttx/
apps/
(5) Network Utilities (apps/netutils/)
(5) NuttShell (NSH) (apps/nshlib)
(4) NuttShell (NSH) (apps/nshlib)
(1) System libraries apps/system (apps/system)
(5) Other Applications & Tests (apps/examples/)
@ -2028,32 +2028,6 @@ o NuttShell (NSH) (apps/nshlib)
Status: Open
Priority: Low (enhancement)
Title: RE-DIRECTION OF BUILTIN APPLICATONS
Description: There is a problem with the re-direction of output form built-in
applications in NSH. When output is re-directed, exec_builtin()
spawns a tiny trampoline task that re-directs the output as
requested, starts the built-in task and then exit.
The problem is that when exec_builtin() starts the trampoline task,
it receives and returns the pid of the trampoline task, and *not*
the pid of the desired builtin application. This bad pid is returned
to NSH and when NSH tries to use that pid in the waitpid() call, it
fails because the trampoline task no longer exists.
The same tasking arrangement is used by the standard function
posix_spawn(). However, posix_spawn uses the non-standard, internal
NuttX interface task_reparent() to replace the childs parent task
with the caller of posix_spawn().
exec_builtin() should not use this internal interface, however,
since it resides in the application space. The suggested solution
is (1) move the exec_builtin() logic into nuttx/sched, (2) make it
a semi-standard interface renamed to task_spawn() and prototyped
in nuttx/include/sched.h, and then (2) use task_reparent to solve
the parental problem in the same way that posix_spawn does.
Status: Open
Priority: Medium
o System libraries apps/system (apps/system)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -92,7 +92,7 @@
*
****************************************************************************/
int exec(FAR const char *filename, FAR const char **argv,
int exec(FAR const char *filename, FAR char * const *argv,
FAR const struct symtab_s *exports, int nexports)
{
#ifdef CONFIG_SCHED_ONEXIT

View File

@ -195,7 +195,7 @@ int stm32_usbhost_initialize(void)
pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)usbhost_waiter, (const char **)NULL);
(main_t)usbhost_waiter, (FAR char * const *)NULL);
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -287,10 +287,10 @@ static int nsh_usbhostinitialize(void)
#ifndef CONFIG_CUSTOM_STACK
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#else
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#endif
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -310,10 +310,10 @@ static int nsh_usbhostinitialize(void)
#ifndef CONFIG_CUSTOM_STACK
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#else
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#endif
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -318,10 +318,10 @@ static int nsh_usbhostinitialize(void)
#ifndef CONFIG_CUSTOM_STACK
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#else
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#endif
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -194,7 +194,7 @@ int stm32_usbhost_initialize(void)
pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)usbhost_waiter, (const char **)NULL);
(main_t)usbhost_waiter, (FAR char * const *)NULL);
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -295,7 +295,7 @@ CONFIG_EOL_IS_EITHER_CRLF=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_EXECFUNCS_SYMTAB="g_symtab"
CONFIG_EXECFUNCS_NSYMBOLS=0
CONFIG_POSIX_SPAWN_STACKSIZE=1024
CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=1024
# CONFIG_LIBC_STRERROR is not set
# CONFIG_LIBC_PERROR_STDOUT is not set
CONFIG_ARCH_LOWPUTC=y

View File

@ -194,7 +194,7 @@ int stm32_usbhost_initialize(void)
pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)usbhost_waiter, (const char **)NULL);
(main_t)usbhost_waiter, (FAR char * const *)NULL);
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -194,7 +194,7 @@ int stm32_usbhost_initialize(void)
pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)usbhost_waiter, (const char **)NULL);
(main_t)usbhost_waiter, (FAR char * const *)NULL);
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -442,7 +442,7 @@ CONFIG_EOL_IS_EITHER_CRLF=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_EXECFUNCS_SYMTAB="exports"
CONFIG_EXECFUNCS_NSYMBOLS=10
CONFIG_POSIX_SPAWN_STACKSIZE=1024
CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=1024
# CONFIG_LIBC_STRERROR is not set
# CONFIG_LIBC_PERROR_STDOUT is not set
CONFIG_ARCH_LOWPUTC=y

View File

@ -194,7 +194,7 @@ int stm32_usbhost_initialize(void)
pid = TASK_CREATE("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)usbhost_waiter, (const char **)NULL);
(main_t)usbhost_waiter, (FAR char * const *)NULL);
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -289,10 +289,10 @@ static int nsh_usbhostinitialize(void)
#ifndef CONFIG_CUSTOM_STACK
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
CONFIG_USBHOST_STACKSIZE,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#else
pid = task_create("usbhost", CONFIG_USBHOST_DEFPRIO,
(main_t)nsh_waiter, (const char **)NULL);
(main_t)nsh_waiter, (FAR char * const *)NULL);
#endif
return pid < 0 ? -ENOEXEC : OK;
}

View File

@ -1570,10 +1570,10 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
#ifndef CONFIG_CUSTOM_STACK
priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO,
CONFIG_HIDKBD_STACKSIZE,
(main_t)usbhost_kbdpoll, (const char **)NULL);
(main_t)usbhost_kbdpoll, (FAR char * const *)NULL);
#else
priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO,
(main_t)usbhost_kbdpoll, (const char **)NULL);
(main_t)usbhost_kbdpoll, (FAR char * const *)NULL);
#endif
if (priv->pollpid == ERROR)
{

View File

@ -450,7 +450,7 @@ mkfatfs_tryfat12(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
* maxnclusters = nfatsects * sectorsize / 1.5 - 2
*/
maxnclusters = (config->fc_nfatsects >> (var->fv_sectshift + 1)) / 3;
maxnclusters = (config->fc_nfatsects << (var->fv_sectshift + 1)) / 3;
if (maxnclusters > FAT_MAXCLUST12)
{
maxnclusters = FAT_MAXCLUST12;

View File

@ -97,7 +97,7 @@ struct binary_s
/* Information provided to the loader to load and bind a module */
FAR const char *filename; /* Full path to the binary to be loaded (See NOTE 1 above) */
FAR const char **argv; /* Argument list */
FAR char * const *argv; /* Argument list */
FAR const struct symtab_s *exports; /* Table of exported symbols */
int nexports; /* The number of symbols in exports[] */
@ -290,7 +290,7 @@ int schedule_unload(pid_t pid, FAR struct binary_s *bin);
*
****************************************************************************/
int exec(FAR const char *filename, FAR const char **argv,
int exec(FAR const char *filename, FAR char * const *argv,
FAR const struct symtab_s *exports, int nexports);
/****************************************************************************

View File

@ -112,18 +112,18 @@ extern "C"
#ifndef CONFIG_CUSTOM_STACK
int task_init(FAR _TCB *tcb, const char *name, int priority,
FAR uint32_t *stack, uint32_t stack_size, main_t entry,
FAR const char *argv[]);
FAR char * const argv[]);
#else
int task_init(FAR _TCB *tcb, const char *name, int priority, main_t entry,
FAR const char *argv[]);
FAR char * const argv[]);
#endif
int task_activate(FAR _TCB *tcb);
#ifndef CONFIG_CUSTOM_STACK
int task_create(FAR const char *name, int priority, int stack_size, main_t entry,
FAR const char *argv[]);
FAR char * const argv[]);
#else
int task_create(FAR const char *name, int priority, main_t entry,
FAR const char *argv[]);
FAR char * const argv[]);
#endif
int task_delete(pid_t pid);
int task_restart(pid_t pid);

View File

@ -75,12 +75,18 @@
struct posix_spawnattr_s
{
uint8_t flags;
uint8_t priority;
uint8_t policy;
/* Used by posix_spawn, posix_spawnp, and task_spawn */
uint8_t flags; /* See POSIX_SPAWN_ definitions */
uint8_t priority; /* Task scheduling priority */
uint8_t policy; /* Task scheduling policy */
#ifndef CONFIG_DISABLE_SIGNALS
sigset_t sigmask;
sigset_t sigmask; /* Signals to be masked */
#endif
/* Used only by task_spawn (non-standard) */
size_t stacksize; /* Task stack size */
};
typedef struct posix_spawnattr_s posix_spawnattr_t;
@ -107,7 +113,10 @@ extern "C"
{
#endif
/* posix_spawn[p] interfaces ************************************************/
/* Spawn interfaces *********************************************************/
/* Standard posix_spawn[p] interfaces. These functions execute files in the
* file system at 'path'
*/
#ifdef CONFIG_BINFMT_EXEPATH
int posix_spawnp(FAR pid_t *pid, FAR const char *path,
@ -121,8 +130,20 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
FAR const posix_spawn_file_actions_t *file_actions,
FAR const posix_spawnattr_t *attr,
FAR char *const argv[], FAR char *const envp[]);
#define posix_spawnp(pid,path,file_actions,attr,argv,envp) \
posix_spawn(pid,path,file_actions,attr,argv,envp)
#endif
/* Non-standard task_spawn interface. This function uses the same
* semantics to execute a file in memory at 'entry', giving it the name
* 'name'.
*/
int task_spawn(FAR pid_t *pid, FAR const char *name, main_t entry,
FAR const posix_spawn_file_actions_t *file_actions,
FAR const posix_spawnattr_t *attr,
FAR char *const argv[], FAR char *const envp[]);
/* File action interfaces ***************************************************/
/* File action initialization and destruction */
@ -181,6 +202,15 @@ int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr,
# define posix_spawnattr_setsigmask(attr,sigmask) (ENOSYS)
#endif
/* Non-standard get/set spawn attributes interfaces for use only with
* task_spawn()
*/
int task_spawnattr_getstacksize(FAR const posix_spawnattr_t *attr,
size_t *stacksize);
int task_spawnattr_setstacksize(FAR posix_spawnattr_t *attr,
size_t stacksize);
/* Non standard debug functions */
#ifdef CONFIG_DEBUG

View File

@ -121,16 +121,25 @@ config EXECFUNCS_NSYMBOLS
symbols in that table. This selection provides the number of
symbols in the symbol table.
config POSIX_SPAWN_STACKSIZE
int "posix_spawn Stack Size"
endif
config POSIX_SPAWN_PROXY_STACKSIZE
int "Spawn Stack Size"
default 1024
---help---
If posix_spawn[p] uses I/O redirection options, then it will require
an intermediary/proxy task to muck with the file descriptors. This
configuration item specifies the stack size used for the proxy. Default:
1024 bytes.
If posix_spawn[p]() and task_spawn() use I/O redirection options,
they will require an intermediary/proxy task to muck with the file
descriptors. This configuration item specifies the stack size
used for the proxy. Default: 1024 bytes.
endif
config TASK_SPAWN_DEFAULT_STACKSIZE
int "Default task_spawn Stack Size"
default 2048
---help---
The actual size to use for the child task's stack can be set with
task_spawnattr_setstacksize(). This value specifies the default
stack size to use if task_spawnattr_setstacksize() is not used.
Default: 2048.
config LIBC_STRERROR
bool "Enable strerror"

View File

@ -45,8 +45,9 @@ 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
CSRCS += lib_psa_getstacksize.c lib_psa_init.c lib_psa_setflags.c
CSRCS += lib_psa_setschedparam.c lib_psa_setschedpolicy.c
CSRCS += lib_psa_setstacksize.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
CSRCS += lib_psa_getsigmask.c lib_psa_setsigmask.c

View File

@ -57,7 +57,7 @@
*
* Input Parameters:
* attr - The address spawn attributes to be queried.
* flags - The location to return the spawn-schedparam value.
* param - The location to return the spawn-schedparam value.
*
* Returned Value:
* On success, these functions return 0; on failure they return an error

View File

@ -0,0 +1,74 @@
/****************************************************************************
* libc/string/lib_psa_getstacksize.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sched.h>
#include <spawn.h>
#include <assert.h>
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: task_spawnattr_getstacksize
*
* Description:
* The task_spawnattr_getstacksize() function will obtain the value of
* the spawn-stacksize attribute from the attributes object referenced
* by attr.
*
* Input Parameters:
* attr - The address spawn attributes to be queried.
* stacksize - The location to return the spawn-stacksize value.
*
* Returned Value:
* On success, these functions return 0; on failure they return an error
* number from <errno.h>.
*
****************************************************************************/
int task_spawnattr_getstacksize(FAR const posix_spawnattr_t *attr,
size_t *stacksize)
{
DEBUGASSERT(attr && stacksize);
*stacksize = attr->stacksize;
return OK;
}

View File

@ -45,7 +45,15 @@
#include <errno.h>
/****************************************************************************
* Global Functions
* Pre-processor Definitions
****************************************************************************/
#ifndef TASK_SPAWN_DEFAULT_STACKSIZE
# define TASK_SPAWN_DEFAULT_STACKSIZE 2048
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
@ -76,10 +84,6 @@ int posix_spawnattr_init(posix_spawnattr_t *attr)
attr->flags = 0;
/* Set the default scheduler policy to the policy of this task */
attr->policy = sched_getscheduler(0);
/* Set the default priority to the same priority as this task */
ret = sched_getparam(0, &param);
@ -89,5 +93,17 @@ int posix_spawnattr_init(posix_spawnattr_t *attr)
}
attr->priority = param.sched_priority;
/* Set the default scheduler policy to the policy of this task */
attr->policy = sched_getscheduler(0);
/* Empty signal masek */
attr->sigmask = 0;
/* Default stack size */
attr->stacksize = TASK_SPAWN_DEFAULT_STACKSIZE;
return OK;
}

View File

@ -0,0 +1,73 @@
/****************************************************************************
* libc/string/lib_psa_setstacksize.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sched.h>
#include <spawn.h>
#include <assert.h>
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: task_spawnattr_setstacksize
*
* Description:
* The task_spawnattr_setstacksize() function shall set the spawn-
* stacksize attribute in an initialized attributes object referenced
* by attr.
*
* Input Parameters:
* attr - The address spawn attributes to be used.
* stacksize - The new stacksize to set.
*
* Returned Value:
* On success, these functions return 0; on failure they return an error
* number from <errno.h>.
*
****************************************************************************/
int task_spawnattr_setstacksize(FAR posix_spawnattr_t *attr, size_t stacksize)
{
DEBUGASSERT(attr);
attr->stacksize = stacksize;
return OK;
}

View File

@ -56,7 +56,7 @@
****************************************************************************/
/****************************************************************************
* Name: lib_psfa_dump
* Name: posix_spawn_file_actions_dump
*
* Description:
* Show the entryent file actions.
@ -126,4 +126,5 @@ void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions)
}
}
#endif /* CONFIG_DEBUG */
#endif /* CONFIG_DEBUG */

View File

@ -117,7 +117,7 @@
*
****************************************************************************/
int execv(FAR const char *path, FAR char *const argv[])
int execv(FAR const char *path, FAR char * const argv[])
{
FAR const struct symtab_s *symtab;
int nsymbols;
@ -129,7 +129,7 @@ int execv(FAR const char *path, FAR char *const argv[])
/* Start the task */
ret = exec(path, (FAR const char **)argv, symtab, nsymbols);
ret = exec(path, (FAR char * const *)argv, symtab, nsymbols);
if (ret < 0)
{
sdbg("exec failed: %d\n", errno);

View File

@ -48,6 +48,8 @@ TSK_SRCS += sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c
TSK_SRCS += sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c
TSK_SRCS += sched_verifytcb.c sched_releasetcb.c
TSK_SRCS += task_spawn.c task_spawnparms.c
ifneq ($(CONFIG_BINFMT_DISABLE),y)
ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
TSK_SRCS += task_posixspawn.c

View File

@ -141,7 +141,7 @@ int os_bringup(void)
g_pgworker = KERNEL_THREAD("pgfill", CONFIG_PAGING_DEFPRIO,
CONFIG_PAGING_STACKSIZE,
(main_t)pg_worker, (const char **)NULL);
(main_t)pg_worker, (FAR char * const *)NULL);
ASSERT(g_pgworker != ERROR);
#endif
@ -154,7 +154,7 @@ int os_bringup(void)
g_work[HPWORK].pid = KERNEL_THREAD("work0", CONFIG_SCHED_WORKPRIORITY,
CONFIG_SCHED_WORKSTACKSIZE,
(main_t)work_hpthread, (const char **)NULL);
(main_t)work_hpthread, (FAR char * const *)NULL);
ASSERT(g_work[HPWORK].pid != ERROR);
/* Start a lower priority worker thread for other, non-critical continuation
@ -166,7 +166,7 @@ int os_bringup(void)
g_work[LPWORK].pid = KERNEL_THREAD("work1", CONFIG_SCHED_LPWORKPRIORITY,
CONFIG_SCHED_LPWORKSTACKSIZE,
(main_t)work_lpthread, (const char **)NULL);
(main_t)work_lpthread, (FAR char * const *)NULL);
ASSERT(g_work[LPWORK].pid != ERROR);
#endif
#endif
@ -182,7 +182,7 @@ int os_bringup(void)
init_taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT,
CONFIG_USERMAIN_STACKSIZE,
(main_t)CONFIG_USER_ENTRYPOINT, (const char **)NULL);
(main_t)CONFIG_USER_ENTRYPOINT, (FAR char * const *)NULL);
ASSERT(init_taskid != ERROR);
/* We an save a few bytes by discarding the IDLE thread's environment. */

View File

@ -259,16 +259,16 @@ void weak_function task_initialize(void);
void task_start(void);
int task_schedsetup(FAR _TCB *tcb, int priority, start_t start,
main_t main, uint8_t ttype);
int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]);
int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR char * const argv[]);
void task_exithook(FAR _TCB *tcb, int status);
int task_deletecurrent(void);
#ifndef CONFIG_CUSTOM_STACK
int kernel_thread(FAR const char *name, int priority, int stack_size,
main_t entry, FAR const char *argv[]);
main_t entry, FAR char * const argv[]);
#else
int kernel_thread(FAR const char *name, int priority, main_t entry,
FAR const char *argv[]);
FAR char * const argv[]);
#endif
bool sched_addreadytorun(FAR _TCB *rtrtcb);
bool sched_removereadytorun(FAR _TCB *rtrtcb);

View File

@ -342,10 +342,10 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
{
/* We know that the child task was running okay we stared,
* so we must have lost the signal. What can we do?
* Let's claim we were interrupted by a signal.
* Let's return ECHILD.. that is at least informative.
*/
err = EINTR;
err = ECHILD;
goto errout_with_errno;
}
#endif

View File

@ -461,10 +461,10 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
/* We know that the child task was running okay we stared,
* so we must have lost the signal. What can we do?
* Let's claim we were interrupted by a signal.
* Let's return ECHILD.. that is at least informative.
*/
err = EINTR;
err = ECHILD;
goto errout_with_errno;
}
#endif

View File

@ -0,0 +1,158 @@
/****************************************************************************
* sched/spawn_internal.h
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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.
*
****************************************************************************/
#ifndef __SCHED_SPAWN_INERNAL_H
#define __SCHED_SPAWN_INERNAL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <spawn.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Type Definitions
****************************************************************************/
struct spawn_parms_s
{
/* Common parameters */
int result;
FAR pid_t *pid;
FAR const posix_spawn_file_actions_t *file_actions;
FAR const posix_spawnattr_t *attr;
FAR char * const *argv;
/* Parameters that differ for posix_spawn[p] and task_spawn */
union
{
struct
{
FAR const char *path;
} posix;
struct
{
FAR const char *name;
main_t entry;
} task;
} u;
};
/****************************************************************************
* Public Data
****************************************************************************/
extern sem_t g_spawn_parmsem;
#ifndef CONFIG_SCHED_WAITPID
extern sem_t g_spawn_execsem;
#endif
extern struct spawn_parms_s g_spawn_parms;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: spawn_semtake and spawn_semgive
*
* Description:
* Give and take semaphores
*
* Input Parameters:
*
* sem - The semaphore to act on.
*
* Returned Value:
* None
*
****************************************************************************/
void spawn_semtake(FAR sem_t *sem);
#define spawn_semgive(sem) sem_post(sem)
/****************************************************************************
* Name: spawn_execattrs
*
* Description:
* Set attributes of the new child task after it has been spawned.
*
* Input Parameters:
*
* pid - The pid of the new task.
* attr - The attributes to use
*
* Returned Value:
* Errors are not reported by this function. This is because errors
* cannot occur, but ratther that the new task has already been started
* so there is no graceful way to handle errors detected in this context
* (unless we delete the new task and recover).
*
* Assumptions:
* That task has been started but has not yet executed because pre-
* emption is disabled.
*
****************************************************************************/
int spawn_execattrs(pid_t pid, FAR const posix_spawnattr_t *attr);
/****************************************************************************
* Name: spawn_proxyattrs
*
* Description:
* Set attributes of the proxy task before it has started the new child
* task.
*
* Input Parameters:
*
* pid - The pid of the new task.
* attr - The attributes to use
* file_actions - The attributes to use
*
* Returned Value:
* 0 (OK) on successed; A negated errno value is returned on failure.
*
****************************************************************************/
int spawn_proxyattrs(FAR const posix_spawnattr_t *attr,
FAR const posix_spawn_file_actions_t *file_actions);
#endif /* __SCHED_SPAWN_INERNAL_H */

View File

@ -100,10 +100,10 @@
#ifndef CONFIG_CUSTOM_STACK
static int thread_create(const char *name, uint8_t ttype, int priority,
int stack_size, main_t entry, const char **argv)
int stack_size, main_t entry, FAR char * const argv[])
#else
static int thread_create(const char *name, uint8_t ttype, int priority,
main_t entry, const char **argv)
main_t entry, FAR char * const argv[])
#endif
{
FAR _TCB *tcb;
@ -244,10 +244,10 @@ errout:
#ifndef CONFIG_CUSTOM_STACK
int task_create(const char *name, int priority,
int stack_size, main_t entry, const char *argv[])
int stack_size, main_t entry, FAR char * const argv[])
#else
int task_create(const char *name, int priority,
main_t entry, const char *argv[])
main_t entry, FAR char * const argv[])
#endif
{
#ifndef CONFIG_CUSTOM_STACK
@ -275,10 +275,10 @@ int task_create(const char *name, int priority,
#ifndef CONFIG_CUSTOM_STACK
int kernel_thread(const char *name, int priority,
int stack_size, main_t entry, const char *argv[])
int stack_size, main_t entry, FAR char * const argv[])
#else
int kernel_thread(const char *name, int priority,
main_t entry, const char *argv[])
main_t entry, FAR char * const argv[])
#endif
{
#ifndef CONFIG_CUSTOM_STACK

View File

@ -114,10 +114,10 @@
#ifndef CONFIG_CUSTOM_STACK
int task_init(FAR _TCB *tcb, const char *name, int priority,
FAR uint32_t *stack, uint32_t stack_size,
main_t entry, const char *argv[])
main_t entry, FAR char * const argv[])
#else
int task_init(FAR _TCB *tcb, const char *name, int priority,
main_t entry, const char *argv[])
main_t entry, FAR char * const argv[])
#endif
{
int errcode;

View File

@ -40,36 +40,19 @@
#include <nuttx/config.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>
#include <sched.h>
#include <fcntl.h>
#include <spawn.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/binfmt/binfmt.h>
#include <nuttx/spawn.h>
#include "os_internal.h"
#include "group_internal.h"
#include "spawn_internal.h"
/****************************************************************************
* Private Types
****************************************************************************/
struct spawn_parms_s
{
int result;
FAR pid_t *pid;
FAR const char *path;
FAR const posix_spawn_file_actions_t *file_actions;
FAR const posix_spawnattr_t *attr;
FAR char *const *argv;
};
/****************************************************************************
* Public Data
****************************************************************************/
@ -78,47 +61,12 @@ struct spawn_parms_s
* Private Data
****************************************************************************/
static sem_t g_ps_parmsem = SEM_INITIALIZER(1);
#ifndef CONFIG_SCHED_WAITPID
static sem_t g_ps_execsem = SEM_INITIALIZER(0);
#endif
static struct spawn_parms_s g_ps_parms;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: spawn_semtake and spawn_semgive
*
* Description:
* Give and take semaphores
*
* Input Parameters:
*
* sem - The semaphore to act on.
*
* Returned Value:
* None
*
****************************************************************************/
static void spawn_semtake(FAR sem_t *sem)
{
int ret;
do
{
ret = sem_wait(sem);
ASSERT(ret == 0 || errno == EINTR);
}
while (ret != 0);
}
#define spawn_semgive(sem) sem_post(sem)
/****************************************************************************
* Name: spawn_exec
* Name: posix_spawn_exec
*
* Description:
* Execute the task from the file system.
@ -156,11 +104,10 @@ static void spawn_semtake(FAR sem_t *sem)
*
****************************************************************************/
static int spawn_exec(FAR pid_t *pidp, FAR const char *path,
FAR const posix_spawnattr_t *attr,
FAR char *const argv[])
static int posix_spawn_exec(FAR pid_t *pidp, FAR const char *path,
FAR const posix_spawnattr_t *attr,
FAR char * const argv[])
{
struct sched_param param;
FAR const struct symtab_s *symtab;
int nsymbols;
int pid;
@ -181,7 +128,7 @@ static int spawn_exec(FAR pid_t *pidp, FAR const char *path,
/* Start the task */
pid = exec(path, (FAR const char **)argv, symtab, nsymbols);
pid = exec(path, (FAR char * const *)argv, symtab, nsymbols);
if (pid < 0)
{
ret = errno;
@ -203,50 +150,7 @@ static int spawn_exec(FAR pid_t *pidp, FAR const char *path,
if (attr)
{
/* If we are only setting the priority, then call sched_setparm()
* to set the priority of the of the new task.
*/
if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0)
{
/* Get the priority from the attrributes */
param.sched_priority = attr->priority;
/* If we are setting *both* the priority and the scheduler,
* then we will call sched_setscheduler() below.
*/
if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) == 0)
{
svdbg("Setting priority=%d for pid=%d\n",
param.sched_priority, pid);
(void)sched_setparam(pid, &param);
}
}
/* If we are only changing the scheduling policy, then reset
* the priority to the default value (the same as this thread) in
* preparation for the sched_setscheduler() call below.
*/
else if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
{
(void)sched_getparam(0, &param);
}
/* Are we setting the scheduling policy? If so, use the priority
* setting determined above.
*/
if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
{
svdbg("Setting policy=%d priority=%d for pid=%d\n",
attr->policy, param.sched_priority, pid);
(void)sched_setscheduler(pid, attr->policy, &param);
}
(void)spawn_execattrs(pid, attr);
}
/* Re-enable pre-emption and return */
@ -257,94 +161,7 @@ errout:
}
/****************************************************************************
* Name: spawn_close, spawn_dup2, and spawn_open
*
* Description:
* Implement individual file actions
*
* Input Parameters:
* action - describes the action to be performed
*
* Returned Value:
* posix_spawn() and posix_spawnp() will return zero on success.
* Otherwise, an error number will be returned as the function return
* value to indicate the error.
*
****************************************************************************/
static inline int spawn_close(FAR struct spawn_close_file_action_s *action)
{
/* The return value from close() is ignored */
svdbg("Closing fd=%d\n", action->fd);
(void)close(action->fd);
return OK;
}
static inline int spawn_dup2(FAR struct spawn_dup2_file_action_s *action)
{
int ret;
/* Perform the dup */
svdbg("Dup'ing %d->%d\n", action->fd1, action->fd2);
ret = dup2(action->fd1, action->fd2);
if (ret < 0)
{
int errcode = errno;
sdbg("ERROR: dup2 failed: %d\n", errcode);
return errcode;
}
return OK;
}
static inline int spawn_open(FAR struct spawn_open_file_action_s *action)
{
int fd;
int ret = OK;
/* Open the file */
svdbg("Open'ing path=%s oflags=%04x mode=%04x\n",
action->path, action->oflags, action->mode);
fd = open(action->path, action->oflags, action->mode);
if (fd < 0)
{
ret = errno;
sdbg("ERROR: open failed: %d\n", ret);
}
/* Does the return file descriptor happen to match the required file
* desciptor number?
*/
else if (fd != action->fd)
{
/* No.. dup2 to get the correct file number */
svdbg("Dup'ing %d->%d\n", fd, action->fd);
ret = dup2(fd, action->fd);
if (ret < 0)
{
ret = errno;
sdbg("ERROR: dup2 failed: %d\n", ret);
}
svdbg("Closing fd=%d\n", fd);
close(fd);
}
return ret;
}
/****************************************************************************
* Name: spawn_proxy
* Name: posix_spawn_proxy
*
* Description:
* Perform file_actions, then execute the task from the file system.
@ -357,11 +174,9 @@ static inline int spawn_open(FAR struct spawn_open_file_action_s *action)
*
****************************************************************************/
static int spawn_proxy(int argc, char *argv[])
static int posix_spawn_proxy(int argc, FAR char *argv[])
{
FAR struct spawn_general_file_action_s *entry;
FAR const posix_spawnattr_t *attr = g_ps_parms.attr;
int ret = OK;
int ret;
/* 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
@ -369,62 +184,22 @@ static int spawn_proxy(int argc, char *argv[])
*/
#ifndef CONFIG_DISABLE_SIGNALS
DEBUGASSERT((g_ps_parms.file_actions && *g_ps_parms.file_actions) ||
(attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0));
DEBUGASSERT(g_spawn_parms.file_actions ||
(g_spawn_parms.attr &&
(g_spawn_parms.attr->flags & POSIX_SPAWN_SETSIGMASK) != 0));
#else
DEBUGASSERT(g_ps_parms.file_actions && *g_ps_parms.file_actions);
DEBUGASSERT(g_spawn_parms.file_actions);
#endif
/* Check if we need to change the signal mask */
#ifndef CONFIG_DISABLE_SIGNALS
if (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)
{
(void)sigprocmask(SIG_SETMASK, &attr->sigmask, NULL);
}
/* Were we also requested to perform file actions? */
if (g_ps_parms.file_actions)
#endif
{
/* Execute each file action */
for (entry = (FAR struct spawn_general_file_action_s *)*g_ps_parms.file_actions;
entry && ret == OK;
entry = entry->flink)
{
switch (entry->action)
{
case SPAWN_FILE_ACTION_CLOSE:
ret = spawn_close((FAR struct spawn_close_file_action_s *)entry);
break;
case SPAWN_FILE_ACTION_DUP2:
ret = spawn_dup2((FAR struct spawn_dup2_file_action_s *)entry);
break;
case SPAWN_FILE_ACTION_OPEN:
ret = spawn_open((FAR struct spawn_open_file_action_s *)entry);
break;
case SPAWN_FILE_ACTION_NONE:
default:
sdbg("ERROR: Unknown action: %d\n", entry->action);
ret = EINVAL;
break;
}
}
}
/* Check for failures */
/* Set the attributes and perform the file actions as appropriate */
ret = spawn_proxyattrs(g_spawn_parms.attr, g_spawn_parms.file_actions);
if (ret == OK)
{
/* Start the task */
ret = spawn_exec(g_ps_parms.pid, g_ps_parms.path, attr,
g_ps_parms.argv);
ret = posix_spawn_exec(g_spawn_parms.pid, g_spawn_parms.u.posix.path,
g_spawn_parms.attr, g_spawn_parms.argv);
#ifdef CONFIG_SCHED_HAVE_PARENT
if (ret == OK)
@ -433,7 +208,7 @@ static int spawn_proxy(int argc, char *argv[])
* What should we do in the event of a failure?
*/
int tmp = task_reparent(0, *g_ps_parms.pid);
int tmp = task_reparent(0, *g_spawn_parms.pid);
if (tmp < 0)
{
sdbg("ERROR: task_reparent() failed: %d\n", tmp);
@ -446,9 +221,9 @@ static int spawn_proxy(int argc, char *argv[])
* what we need to do.
*/
g_ps_parms.result = ret;
g_spawn_parms.result = ret;
#ifndef CONFIG_SCHED_WAITPID
spawn_semgive(&g_ps_execsem);
spawn_semgive(&g_posix_spawn_execsem);
#endif
return OK;
}
@ -585,7 +360,7 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
if (file_actions == NULL || *file_actions == NULL)
#endif
{
return spawn_exec(pid, path, attr, argv);
return posix_spawn_exec(pid, path, attr, argv);
}
/* Otherwise, we will have to go through an intermediary/proxy task in order
@ -601,16 +376,16 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
/* Get exclusive access to the global parameter structure */
spawn_semtake(&g_ps_parmsem);
spawn_semtake(&g_spawn_parmsem);
/* Populate the parameter structure */
g_ps_parms.result = ENOSYS;
g_ps_parms.pid = pid;
g_ps_parms.path = path;
g_ps_parms.file_actions = file_actions;
g_ps_parms.attr = attr;
g_ps_parms.argv = argv;
g_spawn_parms.result = ENOSYS;
g_spawn_parms.pid = pid;
g_spawn_parms.file_actions = file_actions ? *file_actions : NULL;
g_spawn_parms.attr = attr;
g_spawn_parms.argv = argv;
g_spawn_parms.u.posix.path = path;
/* Get the priority of this (parent) task */
@ -620,12 +395,12 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
int errcode = errno;
sdbg("ERROR: sched_getparam failed: %d\n", errcode);
spawn_semgive(&g_ps_parmsem);
spawn_semgive(&g_spawn_parmsem);
return errcode;
}
/* Disable pre-emption so that the proxy does not run until we waitpid
* is called. This is probably unnecessary since the spawn_proxy has
* is called. This is probably unnecessary since the posix_spawn_proxy has
* the same priority as this thread; it should be schedule behind this
* task in the ready-to-run list.
*/
@ -638,13 +413,14 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
* task.
*/
proxy = TASK_CREATE("spawn_proxy", param.sched_priority,
CONFIG_POSIX_SPAWN_STACKSIZE, (main_t)spawn_proxy,
(FAR const char **)NULL);
proxy = TASK_CREATE("posix_spawn_proxy", param.sched_priority,
CONFIG_POSIX_SPAWN_PROXY_STACKSIZE,
(main_t)posix_spawn_proxy,
(FAR char * const *)NULL);
if (proxy < 0)
{
ret = get_errno();
sdbg("ERROR: Failed to start spawn_proxy: %d\n", ret);
sdbg("ERROR: Failed to start posix_spawn_proxy: %d\n", ret);
goto errout_with_lock;
}
@ -659,17 +435,17 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
goto errout_with_lock;
}
#else
spawn_semtake(&g_ps_execsem);
spawn_semtake(&g_posix_spawn_execsem);
#endif
/* Get the result and relinquish our access to the parameter structure */
ret = g_ps_parms.result;
ret = g_spawn_parms.result;
errout_with_lock:
#ifdef CONFIG_SCHED_WAITPID
sched_unlock();
#endif
spawn_semgive(&g_ps_parmsem);
spawn_semgive(&g_spawn_parmsem);
return ret;
}

View File

@ -414,7 +414,7 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main,
*
****************************************************************************/
int task_argsetup(FAR _TCB *tcb, const char *name, const char *argv[])
int task_argsetup(FAR _TCB *tcb, const char *name, FAR char * const argv[])
{
int i;

411
nuttx/sched/task_spawn.c Normal file
View File

@ -0,0 +1,411 @@
/****************************************************************************
* sched/task_spawn.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/wait.h>
#include <sched.h>
#include <spawn.h>
#include <debug.h>
#include "os_internal.h"
#include "group_internal.h"
#include "spawn_internal.h"
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: task_spawn_exec
*
* Description:
* Execute the task from the file system.
*
* Input Parameters:
*
* pidp - Upon successful completion, this will return the task ID of the
* child task in the variable pointed to by a non-NULL 'pid' argument.|
*
* path - The 'path' argument identifies the file to execute. If
* CONFIG_BINFMT_EXEPATH is defined, this may be either a relative or
* or an absolute path. Otherwise, it must be an absolute path.
*
* attr - If the value of the 'attr' parameter is NULL, the all default
* values for the POSIX spawn attributes will be used. Otherwise, the
* attributes will be set according to the spawn flags. The
* following spawn flags are supported:
*
* - POSIX_SPAWN_SETSCHEDPARAM: Set new tasks priority to the sched_param
* value.
* - POSIX_SPAWN_SETSCHEDULER: Set the new tasks scheduler priority to
* the sched_policy value.
*
* NOTE: POSIX_SPAWN_SETSIGMASK is handled in ps_proxy().
*
* argv - argv[] is the argument list for the new task. argv[] is an
* array of pointers to null-terminated strings. The list is terminated
* with a null pointer.
*
* Returned Value:
* This function will return zero on success. Otherwise, an error number
* will be returned as the function return value to indicate the error.
* This errno value may be that set by execv(), sched_setpolicy(), or
* sched_setparam().
*
****************************************************************************/
static int task_spawn_exec(FAR pid_t *pidp, FAR const char *name,
main_t entry, FAR const posix_spawnattr_t *attr,
FAR char * const *argv)
{
int pid;
int ret = OK;
DEBUGASSERT(path);
/* Disable pre-emption so that we can modify the task parameters after
* we start the new task; the new task will not actually begin execution
* until we re-enable pre-emption.
*/
sched_lock();
/* Start the task */
pid = TASK_CREATE(name, attr->priority, attr->stacksize, entry, argv);
if (pid < 0)
{
ret = errno;
sdbg("ERROR: TASK_CREATE failed: %d\n", ret);
goto errout;
}
/* Return the task ID to the caller */
if (pid)
{
*pidp = pid;
}
/* Now set the attributes. Note that we ignore all of the return values
* here because we have already successfully started the task. If we
* return an error value, then we would also have to stop the task.
*/
if (attr)
{
(void)spawn_execattrs(pid, attr);
}
/* Re-enable pre-emption and return */
errout:
sched_unlock();
return ret;
}
/****************************************************************************
* Name: task_spawn_proxy
*
* Description:
* Perform file_actions, then execute the task from the file system.
*
* Input Parameters:
* Standard task start-up parameters
*
* Returned Value:
* Standard task return value.
*
****************************************************************************/
static int task_spawn_proxy(int argc, FAR char *argv[])
{
int ret;
/* Perform file actions and/or set a custom signal mask. We get here only
* if the file_actions parameter to task_spawn[p] was non-NULL and/or the
* option to change the signal mask was selected.
*/
#ifndef CONFIG_DISABLE_SIGNALS
DEBUGASSERT(g_spawn_parms.file_actions ||
(g_spawn_parms.attr &&
(g_spawn_parms.attr->flags & POSIX_SPAWN_SETSIGMASK) != 0));
#else
DEBUGASSERT(g_spawn_parms.file_actions);
#endif
/* Set the attributes and perform the file actions as appropriate */
ret = spawn_proxyattrs(g_spawn_parms.attr, g_spawn_parms.file_actions);
if (ret == OK)
{
/* Start the task */
ret = task_spawn_exec(g_spawn_parms.pid, g_spawn_parms.u.task.name,
g_spawn_parms.u.task.entry, g_spawn_parms.attr,
g_spawn_parms.argv);
#ifdef CONFIG_SCHED_HAVE_PARENT
if (ret == OK)
{
/* Change of the parent of the task we just spawned to our parent.
* What should we do in the event of a failure?
*/
int tmp = task_reparent(0, *g_spawn_parms.pid);
if (tmp < 0)
{
sdbg("ERROR: task_reparent() failed: %d\n", tmp);
}
}
#endif
}
/* Post the semaphore to inform the parent task that we have completed
* what we need to do.
*/
g_spawn_parms.result = ret;
#ifndef CONFIG_SCHED_WAITPID
spawn_semgive(&g_task_spawn_execsem);
#endif
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: task_spawn
*
* Description:
* The task_spawn() function will create a new, child task, where the
* entry point to the task is an address in memory.
*
* Input Parameters:
*
* pid - Upon successful completion, task_spawn() will return the task ID
* of the child task to the parent task, in the variable pointed to by
* a non-NULL 'pid' argument. If the 'pid' argument is a null pointer,
* the process ID of the child is not returned to the caller.
*
* name - The name to assign to the child task.
*
* entry - The child task's entry point (an address in memory)
*
* file_actions - If 'file_actions' is a null pointer, then file
* descriptors open in the calling process will remain open in the
* child process (unless CONFIG_FDCLONE_STDIO is defined). If
* 'file_actions' is not NULL, then the file descriptors open in the
* child process will be those open in the calling process as modified
* by the spawn file actions object pointed to by file_actions.
*
* attr - If the value of the 'attr' parameter is NULL, the all default
* values for the POSIX spawn attributes will be used. Otherwise, the
* attributes will be set according to the spawn flags. The
* task_spawnattr_t spawn attributes object type is defined in spawn.h.
* It will contains these attributes, not all of which are supported by
* NuttX:
*
* - POSIX_SPAWN_SETPGROUP: Setting of the new task's process group is
* not supported. NuttX does not support process groups.
* - POSIX_SPAWN_SETSCHEDPARAM: Set new tasks priority to the sched_param
* value.
* - POSIX_SPAWN_SETSCHEDULER: Set the new task's scheduler policy to
* the sched_policy value.
* - POSIX_SPAWN_RESETIDS: Resetting of the effective user ID of the child
* process is not supported. NuttX does not support effective user
* IDs.
* - POSIX_SPAWN_SETSIGMASK: Set the new task's signal mask.
* - POSIX_SPAWN_SETSIGDEF: Resetting signal default actions is not
* supported. NuttX does not support default signal actions.
*
* And the non-standard:
*
* - TASK_SPAWN_SETSTACKSIZE: Set the stack size for the new task.
*
* argv - argv[] is the argument list for the new task. argv[] is an
* array of pointers to null-terminated strings. The list is terminated
* with a null pointer.
*
* envp - The envp[] argument is not used by NuttX and may be NULL.
*
* Returned Value:
* task_spawn() will return zero on success. Otherwise, an error number
* will be returned as the function return value to indicate the error:
*
* - EINVAL: The value specified by 'file_actions' or 'attr' is invalid.
* - Any errors that might have been return if vfork() and excec[l|v]()
* had been called.
*
****************************************************************************/
int task_spawn(FAR pid_t *pid, FAR const char *name, main_t entry,
FAR const posix_spawn_file_actions_t *file_actions,
FAR const posix_spawnattr_t *attr,
FAR char *const argv[], FAR char *const envp[])
{
struct sched_param param;
pid_t proxy;
#ifdef CONFIG_SCHED_WAITPID
int status;
#endif
int ret;
DEBUGASSERT(path);
svdbg("pid=%p path=%s file_actions=%p attr=%p argv=%p\n",
pid, path, file_actions, attr, argv);
/* If there are no file actions to be performed and there is no change to
* the signal mask, then start the new child task directly from the parent task.
*/
#ifndef CONFIG_DISABLE_SIGNALS
if ((file_actions == NULL || *file_actions == NULL) &&
(attr == NULL || (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0))
#else
if (file_actions == NULL || *file_actions == NULL)
#endif
{
return task_spawn_exec(pid, name, entry, attr, argv);
}
/* Otherwise, we will have to go through an intermediary/proxy task in order
* to perform the I/O redirection. This would be a natural place to fork().
* However, true fork() behavior requires an MMU and most implementations
* of vfork() are not capable of these operations.
*
* Even without fork(), we can still do the job, but parameter passing is
* messier. Unfortunately, there is no (clean) way to pass binary values
* as a task parameter, so we will use a semaphore-protected global
* structure.
*/
/* Get exclusive access to the global parameter structure */
spawn_semtake(&g_spawn_parmsem);
/* Populate the parameter structure */
g_spawn_parms.result = ENOSYS;
g_spawn_parms.pid = pid;
g_spawn_parms.file_actions = file_actions ? *file_actions : NULL;
g_spawn_parms.attr = attr;
g_spawn_parms.argv = argv;
g_spawn_parms.u.task.name = name;
g_spawn_parms.u.task.entry = entry;
/* Get the priority of this (parent) task */
ret = sched_getparam(0, &param);
if (ret < 0)
{
int errcode = errno;
sdbg("ERROR: sched_getparam failed: %d\n", errcode);
spawn_semgive(&g_spawn_parmsem);
return errcode;
}
/* Disable pre-emption so that the proxy does not run until we waitpid
* is called. This is probably unnecessary since the task_spawn_proxy has
* the same priority as this thread; it should be schedule behind this
* task in the ready-to-run list.
*/
#ifdef CONFIG_SCHED_WAITPID
sched_lock();
#endif
/* Start the intermediary/proxy task at the same priority as the parent
* task.
*/
proxy = TASK_CREATE("task_spawn_proxy", param.sched_priority,
CONFIG_POSIX_SPAWN_PROXY_STACKSIZE,
(main_t)task_spawn_proxy,
(FAR char * const*)NULL);
if (proxy < 0)
{
ret = get_errno();
sdbg("ERROR: Failed to start task_spawn_proxy: %d\n", ret);
goto errout_with_lock;
}
/* Wait for the proxy to complete its job */
#ifdef CONFIG_SCHED_WAITPID
ret = waitpid(proxy, &status, 0);
if (ret < 0)
{
sdbg("ERROR: waitpid() failed: %d\n", errno);
goto errout_with_lock;
}
#else
spawn_semtake(&g_task_spawn_execsem);
#endif
/* Get the result and relinquish our access to the parameter structure */
ret = g_spawn_parms.result;
errout_with_lock:
#ifdef CONFIG_SCHED_WAITPID
sched_unlock();
#endif
spawn_semgive(&g_spawn_parmsem);
return ret;
}

View File

@ -0,0 +1,340 @@
/****************************************************************************
* sched/task_spawnparms.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <semaphore.h>
#include <fcntl.h>
#include <spawn.h>
#include <debug.h>
#include <nuttx/spawn.h>
#include "spawn_internal.h"
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
sem_t g_spawn_parmsem = SEM_INITIALIZER(1);
#ifndef CONFIG_SCHED_WAITPID
sem_t g_spawn_execsem = SEM_INITIALIZER(0);
#endif
struct spawn_parms_s g_spawn_parms;
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: spawn_close, spawn_dup2, and spawn_open
*
* Description:
* Implement individual file actions
*
* Input Parameters:
* action - describes the action to be performed
*
* Returned Value:
* posix_spawn() and posix_spawnp() will return zero on success.
* Otherwise, an error number will be returned as the function return
* value to indicate the error.
*
****************************************************************************/
static inline int spawn_close(FAR struct spawn_close_file_action_s *action)
{
/* The return value from close() is ignored */
svdbg("Closing fd=%d\n", action->fd);
(void)close(action->fd);
return OK;
}
static inline int spawn_dup2(FAR struct spawn_dup2_file_action_s *action)
{
int ret;
/* Perform the dup */
svdbg("Dup'ing %d->%d\n", action->fd1, action->fd2);
ret = dup2(action->fd1, action->fd2);
if (ret < 0)
{
int errcode = errno;
sdbg("ERROR: dup2 failed: %d\n", errcode);
return errcode;
}
return OK;
}
static inline int spawn_open(FAR struct spawn_open_file_action_s *action)
{
int fd;
int ret = OK;
/* Open the file */
svdbg("Open'ing path=%s oflags=%04x mode=%04x\n",
action->path, action->oflags, action->mode);
fd = open(action->path, action->oflags, action->mode);
if (fd < 0)
{
ret = errno;
sdbg("ERROR: open failed: %d\n", ret);
}
/* Does the return file descriptor happen to match the required file
* desciptor number?
*/
else if (fd != action->fd)
{
/* No.. dup2 to get the correct file number */
svdbg("Dup'ing %d->%d\n", fd, action->fd);
ret = dup2(fd, action->fd);
if (ret < 0)
{
ret = errno;
sdbg("ERROR: dup2 failed: %d\n", ret);
}
svdbg("Closing fd=%d\n", fd);
close(fd);
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: spawn_semtake and spawn_semgive
*
* Description:
* Give and take semaphores
*
* Input Parameters:
*
* sem - The semaphore to act on.
*
* Returned Value:
* None
*
****************************************************************************/
void spawn_semtake(FAR sem_t *sem)
{
int ret;
do
{
ret = sem_wait(sem);
ASSERT(ret == 0 || errno == EINTR);
}
while (ret != 0);
}
/****************************************************************************
* Name: spawn_execattrs
*
* Description:
* Set attributes of the new child task after it has been spawned.
*
* Input Parameters:
*
* pid - The pid of the new task.
* attr - The attributes to use
*
* Returned Value:
* Errors are not reported by this function. This is because errors
* cannot occur, but ratther that the new task has already been started
* so there is no graceful way to handle errors detected in this context
* (unless we delete the new task and recover).
*
* Assumptions:
* That task has been started but has not yet executed because pre-
* emption is disabled.
*
****************************************************************************/
int spawn_execattrs(pid_t pid, FAR const posix_spawnattr_t *attr)
{
struct sched_param param;
DEBUGASSERT(attr);
/* Now set the attributes. Note that we ignore all of the return values
* here because we have already successfully started the task. If we
* return an error value, then we would also have to stop the task.
*/
/* If we are only setting the priority, then call sched_setparm()
* to set the priority of the of the new task.
*/
if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0)
{
/* Get the priority from the attrributes */
param.sched_priority = attr->priority;
/* If we are setting *both* the priority and the scheduler,
* then we will call sched_setscheduler() below.
*/
if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) == 0)
{
svdbg("Setting priority=%d for pid=%d\n",
param.sched_priority, pid);
(void)sched_setparam(pid, &param);
}
}
/* If we are only changing the scheduling policy, then reset
* the priority to the default value (the same as this thread) in
* preparation for the sched_setscheduler() call below.
*/
else if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
{
(void)sched_getparam(0, &param);
}
/* Are we setting the scheduling policy? If so, use the priority
* setting determined above.
*/
if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
{
svdbg("Setting policy=%d priority=%d for pid=%d\n",
attr->policy, param.sched_priority, pid);
(void)sched_setscheduler(pid, attr->policy, &param);
}
return OK;
}
/****************************************************************************
* Name: spawn_proxyattrs
*
* Description:
* Set attributes of the proxy task before it has started the new child
* task.
*
* Input Parameters:
*
* pid - The pid of the new task.
* attr - The attributes to use
* file_actions - The attributes to use
*
* Returned Value:
* 0 (OK) on successed; A negated errno value is returned on failure.
*
****************************************************************************/
int spawn_proxyattrs(FAR const posix_spawnattr_t *attr,
FAR const posix_spawn_file_actions_t *file_actions)
{
FAR struct spawn_general_file_action_s *entry;
int ret = OK;
/* Check if we need to change the signal mask */
#ifndef CONFIG_DISABLE_SIGNALS
if (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)
{
(void)sigprocmask(SIG_SETMASK, &attr->sigmask, NULL);
}
/* Were we also requested to perform file actions? */
if (file_actions)
#endif
{
/* Yes.. Execute each file action */
for (entry = (FAR struct spawn_general_file_action_s *)file_actions;
entry && ret == OK;
entry = entry->flink)
{
switch (entry->action)
{
case SPAWN_FILE_ACTION_CLOSE:
ret = spawn_close((FAR struct spawn_close_file_action_s *)entry);
break;
case SPAWN_FILE_ACTION_DUP2:
ret = spawn_dup2((FAR struct spawn_dup2_file_action_s *)entry);
break;
case SPAWN_FILE_ACTION_OPEN:
ret = spawn_open((FAR struct spawn_open_file_action_s *)entry);
break;
case SPAWN_FILE_ACTION_NONE:
default:
sdbg("ERROR: Unknown action: %d\n", entry->action);
ret = EINVAL;
break;
}
}
}
return ret;
}

View File

@ -120,8 +120,8 @@
"stat","sys/stat.h","CONFIG_NFILE_DESCRIPTORS > 0","int","const char*","FAR struct stat*"
#"statfs","stdio.h","","int","FAR const char*","FAR struct statfs*"
"statfs","sys/statfs.h","CONFIG_NFILE_DESCRIPTORS > 0","int","const char*","struct statfs*"
"task_create","sched.h","","int","const char*","int","int","main_t","const char* []|const char**"
#"task_create","sched.h","","int","const char*","int","main_t","const char* []|const char**"
"task_create","sched.h","","int","const char*","int","int","main_t","FAR char * const []|FAR char * const *"
#"task_create","sched.h","","int","const char*","int","main_t","FAR char * const []|FAR char * const *"
"task_delete","sched.h","","int","pid_t"
"task_restart","sched.h","","int","pid_t"
"telldir","dirent.h","CONFIG_NFILE_DESCRIPTORS > 0","off_t","FAR DIR*"

Can't render this file because it has a wrong number of fields in line 2.