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:
patacongo 2013-01-18 01:52:42 +00:00
parent e222dcd354
commit 3888a00d2d
16 changed files with 235 additions and 42 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -41,7 +41,7 @@
#include <spawn.h>
#include "spawn/spawn.h"
#include <nuttx/spawn.h>
/****************************************************************************
* Global Functions

View File

@ -44,7 +44,7 @@
#include <assert.h>
#include <errno.h>
#include "spawn/spawn.h"
#include <nuttx/spawn.h>
/****************************************************************************
* Global Functions

View File

@ -44,7 +44,7 @@
#include <assert.h>
#include <errno.h>
#include "spawn/spawn.h"
#include <nuttx/spawn.h>
/****************************************************************************
* Global Functions

View File

@ -45,7 +45,7 @@
#include <assert.h>
#include <errno.h>
#include "spawn/spawn.h"
#include <nuttx/spawn.h>
/****************************************************************************
* Global Functions

View File

@ -43,7 +43,7 @@
#include <spawn.h>
#include <assert.h>
#include "spawn/spawn.h"
#include <nuttx/spawn.h>
/****************************************************************************
* Global Functions

View File

@ -43,7 +43,7 @@
#include <assert.h>
#include <debug.h>
#include "spawn/spawn.h"
#include <nuttx/spawn.h>
#ifdef CONFIG_DEBUG

View File

@ -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)

View File

@ -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[]);

View File

@ -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
View 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 */

View File

@ -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.