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:
parent
f1851b468b
commit
60185fe969
|
@ -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 **.
|
||||
|
||||
|
|
|
@ -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 <sched.h>
|
||||
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 <sched.h>
|
||||
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><errno.h></code>
|
||||
</p>
|
||||
|
||||
<h3><a name="task_spawn">2.1.26 task_spawn</a></h3>
|
||||
<p>
|
||||
<b>Function Prototype:</b>
|
||||
</p>
|
||||
<ul><pre>
|
||||
#include <spawn.h>
|
||||
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 <spawn.h>
|
||||
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><errno.h></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 <spawn.h>
|
||||
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><errno.h></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 <spawn.h>
|
||||
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><errno.h></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>
|
||||
|
|
30
nuttx/TODO
30
nuttx/TODO
|
@ -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)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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, ¶m);
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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, ¶m);
|
||||
}
|
||||
|
||||
/* 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, ¶m);
|
||||
}
|
||||
(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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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, ¶m);
|
||||
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;
|
||||
}
|
|
@ -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, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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, ¶m);
|
||||
}
|
||||
|
||||
/* 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, ¶m);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -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.
|
Loading…
Reference in New Issue