Add internal API task_reparent(), used in posix_spawn(). Move libc/spawn/lib_ps.c to sched/task_posixspawn.c; Move libc/spawn/spawn.h to include/nuttx/spawn.h
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5531 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
e222dcd354
commit
3888a00d2d
@ -3971,4 +3971,9 @@
|
||||
automatically unload and clean-up after running a task that
|
||||
was loaded into memory.
|
||||
* binfmt/libbuiltin: Extensions from Mike Smith
|
||||
|
||||
* sched/task_reparent.c: Add internal interface to change the
|
||||
parent task.
|
||||
* sched/task_posixspawn(): Move libc/spawn/lib_ps.c to
|
||||
sched/task_posixspawn() now it requires internal, reparenting
|
||||
interfaces
|
||||
* include/nuttx/spawn(): Move libc/spawn.h to include/nuttx/spawn.h
|
||||
|
@ -97,7 +97,6 @@ int exec(FAR const char *filename, FAR const char **argv,
|
||||
{
|
||||
#ifdef CONFIG_SCHED_ONEXIT
|
||||
FAR struct binary_s *bin;
|
||||
int errorcode;
|
||||
int pid;
|
||||
int ret;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* libc/spawn/spawn.h
|
||||
* include/nuttx/spawn.h
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
@ -33,8 +33,8 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __LIBC_SPAWN_SPAWN_H
|
||||
#define __LIBC_SPAWN_SPAWN_H
|
||||
#ifndef __INCLUDE_NUTTX_SPAWN_H
|
||||
#define __INCLUDE_NUTTX_SPAWN_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
@ -118,4 +118,4 @@ void add_file_action(FAR posix_spawn_file_actions_t *file_action,
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LIBC_SPAWN_SPAWN_H */
|
||||
#endif /* __INCLUDE_NUTTX_SPAWN_H */
|
@ -61,14 +61,17 @@
|
||||
|
||||
/* All signals are "real time" signals */
|
||||
|
||||
#define SIGRTMIN 0 /* First real time signal */
|
||||
#define SIGRTMAX 31 /* Last real time signal */
|
||||
#define SIGRTMIN MIN_SIGNO /* First real time signal */
|
||||
#define SIGRTMAX MAX_SIGNO /* Last real time signal */
|
||||
|
||||
/* A few of the real time signals are used within the OS. They have
|
||||
* default values that can be overridden from the configuration file. The
|
||||
* rest are all user signals.
|
||||
*
|
||||
* These are semi-standard signal definitions:
|
||||
* The signal number zero is wasted for the most part. It is a valid
|
||||
* signal number, but has special meaning at many interfaces (e.g., Kill()).
|
||||
*
|
||||
* These are the semi-standard signal definitions:
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SIG_SIGUSR1
|
||||
|
@ -37,8 +37,6 @@
|
||||
|
||||
ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
|
||||
|
||||
CSRCS += lib_ps.c
|
||||
|
||||
CSRCS += lib_psfa_addaction.c lib_psfa_addclose.c lib_psfa_adddup2.c
|
||||
CSRCS += lib_psfa_addopen.c lib_psfa_destroy.c lib_psfa_init.c
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include <spawn.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <spawn.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
|
||||
|
@ -48,7 +48,7 @@ TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c \
|
||||
task_restart.c task_vfork.c exit.c getpid.c sched_addreadytorun.c \
|
||||
sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \
|
||||
sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \
|
||||
sched_verifytcb.c sched_releasetcb.c
|
||||
sched_verifytcb.c sched_releasetcb.c task_posixspawn.c
|
||||
|
||||
SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \
|
||||
sched_setscheduler.c sched_getscheduler.c \
|
||||
@ -67,6 +67,10 @@ ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
|
||||
SCHED_SRCS += sched_reprioritize.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
|
||||
SCHED_SRCS += task_reparent.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SCHED_WAITPID),y)
|
||||
SCHED_SRCS += sched_waitpid.c
|
||||
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
|
||||
|
@ -268,6 +268,9 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start,
|
||||
int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]);
|
||||
void task_exithook(FAR _TCB *tcb, int status);
|
||||
int task_deletecurrent(void);
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
int task_reparent(pid_t oldpid, pid_t newpid, pid_t chpid);
|
||||
#endif
|
||||
#ifndef CONFIG_CUSTOM_STACK
|
||||
int kernel_thread(FAR const char *name, int priority, int stack_size,
|
||||
main_t entry, FAR const char *argv[]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* libc/string/lib_ps.c
|
||||
* sched/task_posixspawn.c
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
@ -50,8 +50,9 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
#include <nuttx/spawn.h>
|
||||
|
||||
#include "spawn/spawn.h"
|
||||
#include "os_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
@ -86,7 +87,7 @@ static struct spawn_parms_s g_ps_parms;
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ps_semtake and ps_semgive
|
||||
* Name: spawn_semtake and spawn_semgive
|
||||
*
|
||||
* Description:
|
||||
* Give and take semaphores
|
||||
@ -100,7 +101,7 @@ static struct spawn_parms_s g_ps_parms;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ps_semtake(FAR sem_t *sem)
|
||||
static void spawn_semtake(FAR sem_t *sem)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -112,10 +113,10 @@ static void ps_semtake(FAR sem_t *sem)
|
||||
while (ret != 0);
|
||||
}
|
||||
|
||||
#define ps_semgive(sem) sem_post(sem)
|
||||
#define spawn_semgive(sem) sem_post(sem)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ps_exec
|
||||
* Name: spawn_exec
|
||||
*
|
||||
* Description:
|
||||
* Execute the task from the file system.
|
||||
@ -153,9 +154,9 @@ static void ps_semtake(FAR sem_t *sem)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ps_exec(FAR pid_t *pidp, FAR const char *path,
|
||||
FAR const posix_spawnattr_t *attr,
|
||||
FAR char *const argv[])
|
||||
static int 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;
|
||||
@ -420,7 +421,23 @@ static int spawn_proxy(int argc, char *argv[])
|
||||
{
|
||||
/* Start the task */
|
||||
|
||||
ret = ps_exec(g_ps_parms.pid, g_ps_parms.path, attr, g_ps_parms.argv);
|
||||
ret = spawn_exec(g_ps_parms.pid, g_ps_parms.path, attr,
|
||||
g_ps_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, 0, *g_ps_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
|
||||
@ -429,9 +446,9 @@ static int spawn_proxy(int argc, char *argv[])
|
||||
|
||||
g_ps_parms.result = ret;
|
||||
#ifndef CONFIG_SCHED_WAITPID
|
||||
ps_semgive(&g_ps_execsem);
|
||||
spawn_semgive(&g_ps_execsem);
|
||||
#endif
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -566,7 +583,7 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
|
||||
if (file_actions == NULL || *file_actions == NULL)
|
||||
#endif
|
||||
{
|
||||
return ps_exec(pid, path, attr, argv);
|
||||
return spawn_exec(pid, path, attr, argv);
|
||||
}
|
||||
|
||||
/* Otherwise, we will have to go through an intermediary/proxy task in order
|
||||
@ -582,7 +599,7 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
|
||||
|
||||
/* Get exclusive access to the global parameter structure */
|
||||
|
||||
ps_semtake(&g_ps_parmsem);
|
||||
spawn_semtake(&g_ps_parmsem);
|
||||
|
||||
/* Populate the parameter structure */
|
||||
|
||||
@ -601,22 +618,33 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
|
||||
int errcode = errno;
|
||||
|
||||
sdbg("ERROR: sched_getparam failed: %d\n", errcode);
|
||||
ps_semgive(&g_ps_parmsem);
|
||||
spawn_semgive(&g_ps_parmsem);
|
||||
return errcode;
|
||||
}
|
||||
|
||||
/* Start the intermediary/proxy task at the same priority as the parent task. */
|
||||
/* Disable pre-emption so that the proxy does not run until we waitpid
|
||||
* is called. This is probably unnecessary since the 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("spawn_proxy", param.sched_priority,
|
||||
CONFIG_POSIX_SPAWN_STACKSIZE, (main_t)spawn_proxy,
|
||||
(FAR const char **)NULL);
|
||||
if (proxy < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
ret = get_errno();
|
||||
sdbg("ERROR: Failed to start spawn_proxy: %d\n", ret);
|
||||
|
||||
sdbg("ERROR: Failed to start spawn_proxy: %d\n", errcode);
|
||||
ps_semgive(&g_ps_parmsem);
|
||||
return errcode;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Wait for the proxy to complete its job */
|
||||
@ -625,15 +653,21 @@ int posix_spawn(FAR pid_t *pid, FAR const char *path,
|
||||
ret = waitpid(proxy, &status, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
sdbg("ERROR: waitpid() failed: %d\n", errno);
|
||||
sdbg("ERROR: waitpid() failed: %d\n", errno);
|
||||
goto errout_with_lock;
|
||||
}
|
||||
#else
|
||||
ps_semtake(&g_ps_execsem);
|
||||
spawn_semtake(&g_ps_execsem);
|
||||
#endif
|
||||
|
||||
/* Get the result and relinquish our access to the parameter structure */
|
||||
|
||||
ret = g_ps_parms.result;
|
||||
ps_semgive(&g_ps_parmsem);
|
||||
return ret;
|
||||
|
||||
errout_with_lock:
|
||||
#ifdef CONFIG_SCHED_WAITPID
|
||||
sched_unlock();
|
||||
#endif
|
||||
spawn_semgive(&g_ps_parmsem);
|
||||
return ret;
|
||||
}
|
145
sched/task_reparent.c
Normal file
145
sched/task_reparent.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*****************************************************************************
|
||||
* sched/task_reparent.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 <errno.h>
|
||||
|
||||
#include "os_internal.h"
|
||||
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
|
||||
/*****************************************************************************
|
||||
* Private Functions
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public Functions
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: task_reparent
|
||||
*
|
||||
* Description:
|
||||
* Change the parent of a task.
|
||||
*
|
||||
* Parameters:
|
||||
* oldpid - PID of the old parent task (0 if this task)
|
||||
* newpid - PID ot the new parent task (0 for the parent of this task)
|
||||
* chpid - PID of the child to be reparented.
|
||||
*
|
||||
* Return Value:
|
||||
* 0 (OK) on success; A negated errno value on failure.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int task_reparent(pid_t oldpid, pid_t newpid, pid_t chpid)
|
||||
{
|
||||
_TCB *oldtcb;
|
||||
_TCB *newtcb;
|
||||
_TCB *chtcb;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* If oldpid is zero, then we are parent task. */
|
||||
|
||||
if (oldpid == 0)
|
||||
{
|
||||
oldpid = getpid();
|
||||
}
|
||||
|
||||
/* Get the current parent task's TCB */
|
||||
|
||||
oldtcb = sched_gettcb(oldpid);
|
||||
if (!oldtcb)
|
||||
{
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
/* Disable interrupts so that nothing can change from this point */
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* If newpid is zero, then new is the parent of oldpid. */
|
||||
|
||||
if (newpid == 0)
|
||||
{
|
||||
newpid = oldtcb->parent;
|
||||
}
|
||||
|
||||
/* Get the new parent task's TCB */
|
||||
|
||||
newtcb = sched_gettcb(newpid);
|
||||
if (!newtcb)
|
||||
{
|
||||
ret = -ESRCH;
|
||||
goto errout_with_ints;
|
||||
}
|
||||
|
||||
/* Get the child tasks TCB */
|
||||
|
||||
chtcb = sched_gettcb(chpid);
|
||||
if (!chtcb)
|
||||
{
|
||||
ret = -ECHILD;
|
||||
goto errout_with_ints;
|
||||
}
|
||||
|
||||
/* Verify that oldpid is the parent of chpid */
|
||||
|
||||
if (chtcb->parent != oldpid)
|
||||
{
|
||||
ret = -ECHILD;
|
||||
goto errout_with_ints;
|
||||
}
|
||||
|
||||
/* Okay, reparent the child */
|
||||
|
||||
DEBUGASSERT(oldtcb->nchildren > 0);
|
||||
chtcb->parent = newpid;
|
||||
oldtcb->nchildren--;
|
||||
newtcb->nchildren++;
|
||||
ret = OK;
|
||||
|
||||
errout_with_ints:
|
||||
irqrestore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCHED_HAVE_PARENT */
|
@ -43,6 +43,8 @@
|
||||
"prctl","sys/prctl.h", "CONFIG_TASK_NAME_SIZE > 0","int","int","..."
|
||||
"clock_systimer","nuttx/clock.h","!defined(CONFIG_DISABLE_CLOCK)","uint32_t"
|
||||
"poll","poll.h","!defined(CONFIG_DISABLE_POLL) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","FAR struct pollfd*","nfds_t","int"
|
||||
"posix_spawnp", defined(CONFIG_BINFMT_EXEPATH), "int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []"
|
||||
"posix_spawn", !defined(CONFIG_BINFMT_EXEPATH), "int","FAR pid_t *","FAR const char *","FAR const posix_spawn_file_actions_t *","FAR const posix_spawnattr_t *","FAR char *const []","FAR char *const []"
|
||||
"pthread_barrier_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*"
|
||||
"pthread_barrier_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*","FAR const pthread_barrierattr_t*","unsigned int"
|
||||
"pthread_barrier_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_barrier_t*"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
Loading…
Reference in New Issue
Block a user