mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-06-01 02:55:07 +08:00
Add framework to support task groups
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5562 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -57,6 +57,14 @@
|
|||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
/* Configuration ****************************************************************/
|
||||||
|
/* Task groups currently only supported for retention of child status */
|
||||||
|
|
||||||
|
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
|
||||||
|
# define HAVE_TASK_GROUP 1
|
||||||
|
#else
|
||||||
|
# undef HAVE_TASK_GROUP
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Task Management Definitins ***************************************************/
|
/* Task Management Definitins ***************************************************/
|
||||||
|
|
||||||
@@ -64,7 +72,7 @@
|
|||||||
|
|
||||||
#define MAX_LOCK_COUNT 127
|
#define MAX_LOCK_COUNT 127
|
||||||
|
|
||||||
/* Values for the _TCB flags flag bits */
|
/* Values for the _TCB flags bits */
|
||||||
|
|
||||||
#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */
|
#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */
|
||||||
#define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT)
|
#define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT)
|
||||||
@@ -74,7 +82,10 @@
|
|||||||
#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */
|
#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */
|
||||||
#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */
|
#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */
|
||||||
#define TCB_FLAG_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */
|
#define TCB_FLAG_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */
|
||||||
#define TCB_FLAG_NOCLDWAIT (1 << 5) /* Bit 5: Do not retain child exit status */
|
|
||||||
|
/* Values for struct task_group tg_flags */
|
||||||
|
|
||||||
|
#define GROUP_FLAG_NOCLDWAIT (1 << 0) /* Bit 0: Do not retain child exit status */
|
||||||
|
|
||||||
/* Values for struct child_status_s ch_flags */
|
/* Values for struct child_status_s ch_flags */
|
||||||
|
|
||||||
@@ -159,6 +170,7 @@ typedef CODE void (*onexitfunc_t)(int exitcode, FAR void *arg);
|
|||||||
|
|
||||||
typedef struct msgq_s msgq_t;
|
typedef struct msgq_s msgq_t;
|
||||||
|
|
||||||
|
/* struct environ_s **************************************************************/
|
||||||
/* The structure used to maintain environment variables */
|
/* The structure used to maintain environment variables */
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_ENVIRON
|
#ifndef CONFIG_DISABLE_ENVIRON
|
||||||
@@ -173,6 +185,7 @@ typedef struct environ_s environ_t;
|
|||||||
# define SIZEOF_ENVIRON_T(alloc) (sizeof(environ_t) + alloc - 1)
|
# define SIZEOF_ENVIRON_T(alloc) (sizeof(environ_t) + alloc - 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* struct child_status_s *********************************************************/
|
||||||
/* This structure is used to maintin information about child tasks.
|
/* This structure is used to maintin information about child tasks.
|
||||||
* pthreads work differently, they have join information. This is
|
* pthreads work differently, they have join information. This is
|
||||||
* only for child tasks.
|
* only for child tasks.
|
||||||
@@ -189,6 +202,7 @@ struct child_status_s
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* struct dspace_s ***************************************************************/
|
||||||
/* This structure describes a reference counted D-Space region. This must be a
|
/* This structure describes a reference counted D-Space region. This must be a
|
||||||
* separately allocated "break-away" structure that can be owned by a task and
|
* separately allocated "break-away" structure that can be owned by a task and
|
||||||
* any pthreads created by the task.
|
* any pthreads created by the task.
|
||||||
@@ -214,6 +228,58 @@ struct dspace_s
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* struct task_group_s ***********************************************************/
|
||||||
|
/* All threads created by pthread_create belong in the same task group (along with
|
||||||
|
* the thread of the original task). struct task_group_s is a shared, "breakaway"
|
||||||
|
* structure referenced by each TCB.
|
||||||
|
*
|
||||||
|
* This structure should contain *all* resources shared by tasks and threads that
|
||||||
|
* belong to the same task group:
|
||||||
|
*
|
||||||
|
* Child exit status
|
||||||
|
* Environment varibles
|
||||||
|
* PIC data space and address environments
|
||||||
|
* File descriptors
|
||||||
|
* FILE streams
|
||||||
|
* Sockets
|
||||||
|
*
|
||||||
|
* Currenty, however, this implementation only applies to child exit status.
|
||||||
|
*
|
||||||
|
* Each instance of struct task_group_s is reference counted. Each instance is
|
||||||
|
* created with a reference count of one. The reference incremeneted when each
|
||||||
|
* thread joins the group and decremented when each thread exits, leaving the
|
||||||
|
* group. When the refernce count decrements to zero, the struc task_group_s
|
||||||
|
* is free.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
struct task_group_s
|
||||||
|
{
|
||||||
|
uint16_t tg_crefs; /* Count of threads sharing this data */
|
||||||
|
uint8_t tg_flags; /* See GROUP_FLAG_* definitions */
|
||||||
|
|
||||||
|
/* Child exit status **********************************************************/
|
||||||
|
|
||||||
|
FAR struct child_status_s *tg_children; /* Head of a list of child status */
|
||||||
|
|
||||||
|
/* Environment varibles *******************************************************/
|
||||||
|
/* Not yet (see type environ_t) */
|
||||||
|
|
||||||
|
/* PIC data space and address environments */
|
||||||
|
/* Not yet (see struct dspace_s) */
|
||||||
|
|
||||||
|
/* File descriptors */
|
||||||
|
/* Not yet (see struct filelist) */
|
||||||
|
|
||||||
|
/* FILE streams */
|
||||||
|
/* Not yet (see streamlist) */
|
||||||
|
|
||||||
|
/* Sockets */
|
||||||
|
/* Not yet (see struct socketlist) */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* _TCB **************************************************************************/
|
||||||
/* This is the task control block (TCB). Each task or thread is represented by
|
/* This is the task control block (TCB). Each task or thread is represented by
|
||||||
* a TCB. The TCB is the heart of the NuttX task-control logic.
|
* a TCB. The TCB is the heart of the NuttX task-control logic.
|
||||||
*/
|
*/
|
||||||
@@ -225,14 +291,18 @@ struct _TCB
|
|||||||
FAR struct _TCB *flink; /* Doubly linked list */
|
FAR struct _TCB *flink; /* Doubly linked list */
|
||||||
FAR struct _TCB *blink;
|
FAR struct _TCB *blink;
|
||||||
|
|
||||||
|
/* Task Group *****************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
FAR struct task_group_s *group; /* Pointer to shared task group data */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Task Management Fields *****************************************************/
|
/* Task Management Fields *****************************************************/
|
||||||
|
|
||||||
pid_t pid; /* This is the ID of the thread */
|
pid_t pid; /* This is the ID of the thread */
|
||||||
#ifdef CONFIG_SCHED_HAVE_PARENT /* Support parent-child relationship */
|
#ifdef CONFIG_SCHED_HAVE_PARENT /* Support parent-child relationship */
|
||||||
pid_t parent; /* This is the ID of the parent thread */
|
pid_t parent; /* This is the ID of the parent thread */
|
||||||
#ifdef CONFIG_SCHED_CHILD_STATUS /* Retain child thread status */
|
#ifndef CONFIG_SCHED_CHILD_STATUS /* Retain child thread status */
|
||||||
FAR struct child_status_s *children; /* Head of a list of child status */
|
|
||||||
#else
|
|
||||||
uint16_t nchildren; /* This is the number active children */
|
uint16_t nchildren; /* This is the number active children */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -118,11 +118,11 @@ static uint16_t poll_interrupt(FAR struct uip_driver_s *dev, FAR void *conn,
|
|||||||
|
|
||||||
nllvdbg("flags: %04x\n", flags);
|
nllvdbg("flags: %04x\n", flags);
|
||||||
|
|
||||||
DEBUGASSERT(info && info->psock && info->fds);
|
DEBUGASSERT(!info || (info->psock && info->fds));
|
||||||
|
|
||||||
/* 'priv' might be null in some race conditions (?) */
|
/* 'priv' might be null in some race conditions (?) */
|
||||||
|
|
||||||
if (info->fds)
|
if (info)
|
||||||
{
|
{
|
||||||
pollevent_t eventset = 0;
|
pollevent_t eventset = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ SCHED_SRCS += sched_waitid.c sched_wait.c
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
GRP_SRCS = group_create.c group_join.c group_leave.c
|
||||||
|
|
||||||
ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c
|
ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c
|
||||||
ENV_SRCS += env_findvar.c env_removevar.c
|
ENV_SRCS += env_findvar.c env_removevar.c
|
||||||
ENV_SRCS += env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c
|
ENV_SRCS += env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c
|
||||||
@@ -169,8 +171,9 @@ IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c
|
|||||||
KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c
|
KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c
|
||||||
KMM_SRCS = kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c
|
KMM_SRCS = kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c
|
||||||
|
|
||||||
CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(SCHED_SRCS) $(WDOG_SRCS) $(TIME_SRCS) \
|
CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(GRP_SRCS) $(SCHED_SRCS) $(WDOG_SRCS)
|
||||||
$(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS) $(IRQ_SRCS)
|
CSRCS += $(TIME_SRCS) $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS)
|
||||||
|
CSRCS += $(IRQ_SRCS)
|
||||||
|
|
||||||
ifneq ($(CONFIG_DISABLE_CLOCK),y)
|
ifneq ($(CONFIG_DISABLE_CLOCK),y)
|
||||||
CSRCS += $(CLOCK_SRCS)
|
CSRCS += $(CLOCK_SRCS)
|
||||||
|
|||||||
+5
-11
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/env_dup.c
|
* sched/env_dup.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
* exact duplicate of the parent task's environment.
|
* exact duplicate of the parent task's environment.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* ptcb The tcb to receive the newly allocated copy of the parspecifiedent
|
* ptcb The tcb to receive the newly allocated copy of the parent
|
||||||
* TCB's environment structure with reference count equal to one
|
* TCB's environment structure with reference count equal to one
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
@@ -80,16 +80,12 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int env_dup(FAR _TCB *ptcb)
|
int env_dup(FAR _TCB *ptcb)
|
||||||
{
|
|
||||||
int ret = OK;
|
|
||||||
if (!ptcb )
|
|
||||||
{
|
|
||||||
ret = -EINVAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
FAR _TCB *parent = (FAR _TCB*)g_readytorun.head;
|
FAR _TCB *parent = (FAR _TCB*)g_readytorun.head;
|
||||||
environ_t *envp = NULL;
|
environ_t *envp = NULL;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
DEBUGASSERT(ptcb);
|
||||||
|
|
||||||
/* Pre-emption must be disabled throughout the following because the
|
/* Pre-emption must be disabled throughout the following because the
|
||||||
* environment may be shared.
|
* environment may be shared.
|
||||||
@@ -121,8 +117,6 @@ int env_dup(FAR _TCB *ptcb)
|
|||||||
|
|
||||||
ptcb->envp = envp;
|
ptcb->envp = envp;
|
||||||
sched_unlock();
|
sched_unlock();
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* sched/group_create.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 <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Name: group_create
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Create and initialize a new task group structure for the specified TCB.
|
||||||
|
* This function is called as part of the task creation sequence.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* tcb - The tcb in need of the task group.
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* 0 (OK) on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* Called during task creation in a safe context. No special precautions
|
||||||
|
* are required here.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
int group_create(FAR _TCB *tcb)
|
||||||
|
{
|
||||||
|
FAR struct task_group_s *group;
|
||||||
|
|
||||||
|
DEBUGASSERT(tcb && !tcb->group);
|
||||||
|
|
||||||
|
/* Allocate the group structure */
|
||||||
|
|
||||||
|
group = (FAR struct task_group_s *)kzalloc(sizeof(struct task_group_s));
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the group structure and assign it to the tcb */
|
||||||
|
|
||||||
|
group->tg_crefs = 1;
|
||||||
|
tcb->group = group;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_TASK_GROUP */
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* sched/group_join.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 <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "os_internal.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Name: group_join
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Copy the group structure reference from one TCB to another, incrementing
|
||||||
|
* the refrence count on the group. This function is called when a pthread
|
||||||
|
* is produced within the task group so that the pthread can share the
|
||||||
|
* resources of the task group.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* tcb - The TCB of the new "child" task that need to join the group.
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* - The parent task from which the group will be inherited is the task at
|
||||||
|
* the thead of the ready to run list.
|
||||||
|
* - Called during thread creation in a safe context. No special precautions
|
||||||
|
* are required here.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void group_join(FAR _TCB *tcb)
|
||||||
|
{
|
||||||
|
FAR _TCB *ptcb = (FAR _TCB *)g_readytorun.head;
|
||||||
|
|
||||||
|
DEBUGASSERT(ptcb && tcb && ptcb->group && !tcb->group);
|
||||||
|
|
||||||
|
/* Copy the group reference from the parent to the child, incrementing the
|
||||||
|
* reference count.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tcb->group = ptcb->group;
|
||||||
|
ptcb->group->tg_crefs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_TASK_GROUP */
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* sched/group_leave.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 <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "os_internal.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Name: group_leave
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Release a reference on a group. This function is called when a task or
|
||||||
|
* thread exits. It decrements the reference count on the group. If the
|
||||||
|
* reference count decrements to zero, then it frees the group and all of
|
||||||
|
* resources contained in the group.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* tcb - The TCB of the task that is exiting.
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* Called during task deletion in a safe context. No special precautions
|
||||||
|
* are required here.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void group_leave(FAR _TCB *tcb)
|
||||||
|
{
|
||||||
|
FAR struct task_group_s *group;
|
||||||
|
|
||||||
|
DEBUGASSERT(tcb);
|
||||||
|
|
||||||
|
/* Make sure that we have a group */
|
||||||
|
|
||||||
|
group = tcb->group;
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
/* Would the reference count decrement to zero? */
|
||||||
|
|
||||||
|
if (group->tg_crefs > 1)
|
||||||
|
{
|
||||||
|
/* No.. just decrement the reference count and return */
|
||||||
|
|
||||||
|
group->tg_crefs--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Yes.. Release all of the resource contained within the group */
|
||||||
|
/* Free all un-reaped child exit status */
|
||||||
|
|
||||||
|
task_removechildren(tcb);
|
||||||
|
|
||||||
|
/* Release the group container itself */
|
||||||
|
|
||||||
|
sched_free(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcb->group = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_TASK_GROUP */
|
||||||
@@ -268,7 +268,20 @@ 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[]);
|
int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]);
|
||||||
void task_exithook(FAR _TCB *tcb, int status);
|
void task_exithook(FAR _TCB *tcb, int status);
|
||||||
int task_deletecurrent(void);
|
int task_deletecurrent(void);
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||||
|
int task_reparent(pid_t ppid, pid_t chpid);
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
int group_create(FAR _TCB *tcb);
|
||||||
|
void group_join(FAR _TCB *tcb);
|
||||||
|
void group_leave(FAR _TCB *tcb);
|
||||||
|
#else
|
||||||
|
# define group_create(tcb)
|
||||||
|
# define group_join(tcb)
|
||||||
|
# define group_leave(tcb)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_CHILD_STATUS
|
#ifdef CONFIG_SCHED_CHILD_STATUS
|
||||||
void weak_function task_initialize(void);
|
void weak_function task_initialize(void);
|
||||||
FAR struct child_status_s *task_allocchild(void);
|
FAR struct child_status_s *task_allocchild(void);
|
||||||
@@ -279,8 +292,8 @@ FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid);
|
|||||||
FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid);
|
FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid);
|
||||||
void task_removechildren(FAR _TCB *tcb);
|
void task_removechildren(FAR _TCB *tcb);
|
||||||
#endif
|
#endif
|
||||||
int task_reparent(pid_t ppid, pid_t chpid);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_CUSTOM_STACK
|
#ifndef CONFIG_CUSTOM_STACK
|
||||||
int kernel_thread(FAR const char *name, int priority, int stack_size,
|
int kernel_thread(FAR const char *name, int priority, int stack_size,
|
||||||
main_t entry, FAR const char *argv[]);
|
main_t entry, FAR const char *argv[]);
|
||||||
|
|||||||
+11
-1
@@ -202,6 +202,9 @@ const tasklist_t g_tasklisttable[NUM_TASK_STATES] =
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static FAR _TCB g_idletcb;
|
static FAR _TCB g_idletcb;
|
||||||
|
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
|
||||||
|
static struct task_group_s g_idlegroup;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This is the name of the idle task */
|
/* This is the name of the idle task */
|
||||||
|
|
||||||
@@ -280,13 +283,20 @@ void os_start(void)
|
|||||||
g_idletcb.argv[0] = (char*)g_idlename;
|
g_idletcb.argv[0] = (char*)g_idlename;
|
||||||
#endif /* CONFIG_TASK_NAME_SIZE */
|
#endif /* CONFIG_TASK_NAME_SIZE */
|
||||||
|
|
||||||
|
/* Join the IDLE group */
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
g_idlegroup.tg_crefs = 1;
|
||||||
|
g_idlegroup.tg_flags = GROUP_FLAG_NOCLDWAIT;
|
||||||
|
g_idletcb.group = &g_idlegroup;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Then add the idle task's TCB to the head of the ready to run list */
|
/* Then add the idle task's TCB to the head of the ready to run list */
|
||||||
|
|
||||||
dq_addfirst((FAR dq_entry_t*)&g_idletcb, (FAR dq_queue_t*)&g_readytorun);
|
dq_addfirst((FAR dq_entry_t*)&g_idletcb, (FAR dq_queue_t*)&g_readytorun);
|
||||||
|
|
||||||
/* Initialize the processor-specific portion of the TCB */
|
/* Initialize the processor-specific portion of the TCB */
|
||||||
|
|
||||||
g_idletcb.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NOCLDWAIT);
|
|
||||||
up_initial_state(&g_idletcb);
|
up_initial_state(&g_idletcb);
|
||||||
|
|
||||||
/* Initialize the semaphore facility(if in link). This has to be done
|
/* Initialize the semaphore facility(if in link). This has to be done
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
#if CONFIG_RR_INTERVAL > 0
|
#if CONFIG_RR_INTERVAL > 0
|
||||||
int policy;
|
int policy;
|
||||||
#endif
|
#endif
|
||||||
|
int errcode;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
/* If attributes were not supplied, use the default attributes */
|
/* If attributes were not supplied, use the default attributes */
|
||||||
@@ -268,6 +269,12 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Join the parent's task group */
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
group_join(ptcb);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Share the address environment of the parent task. NOTE: Only tasks
|
/* Share the address environment of the parent task. NOTE: Only tasks
|
||||||
* created throught the nuttx/binfmt loaders may have an address
|
* created throught the nuttx/binfmt loaders may have an address
|
||||||
* environment.
|
* environment.
|
||||||
@@ -277,8 +284,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
ret = up_addrenv_share((FAR const _TCB *)g_readytorun.head, ptcb);
|
ret = up_addrenv_share((FAR const _TCB *)g_readytorun.head, ptcb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
sched_releasetcb(ptcb);
|
errcode = -ret;
|
||||||
return -ret;
|
goto errout_with_tcb;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -287,8 +294,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
ret = sched_setuppthreadfiles(ptcb);
|
ret = sched_setuppthreadfiles(ptcb);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
sched_releasetcb(ptcb);
|
errcode = ret;
|
||||||
return ret;
|
goto errout_with_tcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Share the parent's envionment */
|
/* Share the parent's envionment */
|
||||||
@@ -300,8 +307,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
pjoin = (FAR join_t*)kzalloc(sizeof(join_t));
|
pjoin = (FAR join_t*)kzalloc(sizeof(join_t));
|
||||||
if (!pjoin)
|
if (!pjoin)
|
||||||
{
|
{
|
||||||
sched_releasetcb(ptcb);
|
errcode = ENOMEM;
|
||||||
return ENOMEM;
|
goto errout_with_tcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the stack for the TCB */
|
/* Allocate the stack for the TCB */
|
||||||
@@ -309,9 +316,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
ret = up_create_stack(ptcb, attr->stacksize);
|
ret = up_create_stack(ptcb, attr->stacksize);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
sched_releasetcb(ptcb);
|
errcode = ENOMEM;
|
||||||
sched_free(pjoin);
|
goto errout_with_join;
|
||||||
return ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should we use the priority and scheduler specified in the
|
/* Should we use the priority and scheduler specified in the
|
||||||
@@ -360,9 +366,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
TCB_FLAG_TTYPE_PTHREAD);
|
TCB_FLAG_TTYPE_PTHREAD);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
sched_releasetcb(ptcb);
|
errcode = EBUSY;
|
||||||
sched_free(pjoin);
|
goto errout_with_join;
|
||||||
return EBUSY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure the TCB for a pthread receiving on parameter
|
/* Configure the TCB for a pthread receiving on parameter
|
||||||
@@ -440,10 +445,18 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
|
|||||||
dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks);
|
dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks);
|
||||||
(void)sem_destroy(&pjoin->data_sem);
|
(void)sem_destroy(&pjoin->data_sem);
|
||||||
(void)sem_destroy(&pjoin->exit_sem);
|
(void)sem_destroy(&pjoin->exit_sem);
|
||||||
sched_releasetcb(ptcb);
|
|
||||||
sched_free(pjoin);
|
errcode = EIO;
|
||||||
ret = EIO;
|
goto errout_with_join;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
errout_with_join:
|
||||||
|
sched_free(pjoin);
|
||||||
|
ptcb->joininfo = NULL;
|
||||||
|
|
||||||
|
errout_with_tcb:
|
||||||
|
sched_releasetcb(ptcb);
|
||||||
|
return errcode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
* sched/sched_releasetcb.c
|
* sched/sched_releasetcb.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -177,6 +177,11 @@ int sched_releasetcb(FAR _TCB *tcb)
|
|||||||
ret = up_addrenv_release(tcb);
|
ret = up_addrenv_release(tcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Leave the group (if we did not already leady in task_exithook.c) */
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
group_leave(tcb);
|
||||||
|
#endif
|
||||||
/* And, finally, release the TCB itself */
|
/* And, finally, release the TCB itself */
|
||||||
|
|
||||||
sched_free(tcb);
|
sched_free(tcb);
|
||||||
|
|||||||
@@ -197,9 +197,9 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
|
|||||||
#ifdef CONFIG_SCHED_CHILD_STATUS
|
#ifdef CONFIG_SCHED_CHILD_STATUS
|
||||||
/* Does this task retain child status? */
|
/* Does this task retain child status? */
|
||||||
|
|
||||||
retains = ((rtcb->flags && TCB_FLAG_NOCLDWAIT) == 0);
|
retains = ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0);
|
||||||
|
|
||||||
if (rtcb->children == NULL && retains)
|
if (rtcb->group->tg_children == NULL && retains)
|
||||||
{
|
{
|
||||||
/* There are no children */
|
/* There are no children */
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
|
|||||||
* instead).
|
* instead).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(!retains || rtcb->children);
|
DEBUGASSERT(!retains || rtcb->group->tg_children);
|
||||||
if (idtype == P_ALL)
|
if (idtype == P_ALL)
|
||||||
{
|
{
|
||||||
/* We are waiting for any child to exit */
|
/* We are waiting for any child to exit */
|
||||||
|
|||||||
@@ -312,9 +312,9 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
|||||||
#ifdef CONFIG_SCHED_CHILD_STATUS
|
#ifdef CONFIG_SCHED_CHILD_STATUS
|
||||||
/* Does this task retain child status? */
|
/* Does this task retain child status? */
|
||||||
|
|
||||||
retains = ((rtcb->flags && TCB_FLAG_NOCLDWAIT) == 0);
|
retains = ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0);
|
||||||
|
|
||||||
if (rtcb->children == NULL && retains)
|
if (rtcb->group->tg_children == NULL && retains)
|
||||||
{
|
{
|
||||||
err = ECHILD;
|
err = ECHILD;
|
||||||
goto errout_with_errno;
|
goto errout_with_errno;
|
||||||
@@ -381,7 +381,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
|||||||
* chilren.
|
* chilren.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(!retains || rtcb->children);
|
DEBUGASSERT(!retains || rtcb->group->tg_children);
|
||||||
if (retains && (child = task_exitchild(rtcb)) != NULL)
|
if (retains && (child = task_exitchild(rtcb)) != NULL)
|
||||||
{
|
{
|
||||||
/* A child has exited. Apparently we missed the signal.
|
/* A child has exited. Apparently we missed the signal.
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *
|
|||||||
|
|
||||||
/* Mark that status should be not be retained */
|
/* Mark that status should be not be retained */
|
||||||
|
|
||||||
rtcb->flags |= TCB_FLAG_NOCLDWAIT;
|
rtcb->group->tg_flags |= GROUP_FLAG_NOCLDWAIT;
|
||||||
|
|
||||||
/* Free all pending exit status */
|
/* Free all pending exit status */
|
||||||
|
|
||||||
|
|||||||
@@ -111,10 +111,11 @@ static struct child_pool_s g_child_pool;
|
|||||||
static void task_dumpchildren(FAR _TCB *tcb, FAR const char *msg)
|
static void task_dumpchildren(FAR _TCB *tcb, FAR const char *msg)
|
||||||
{
|
{
|
||||||
FAR struct child_status_s *child;
|
FAR struct child_status_s *child;
|
||||||
|
FAR struct task_group_s *group = tcb->group;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dbg("Parent TCB=%p: %s\n", tcb, msg);
|
dbg("Parent TCB=%p group=%p: %s\n", tcb, group, msg);
|
||||||
for (i = 0, child = tcb->children; child; i++, child = child->flink)
|
for (i = 0, child = group->tg_children; child; i++, child = child->flink)
|
||||||
{
|
{
|
||||||
dbg(" %d. ch_flags=%02x ch_pid=%d ch_status=%d\n",
|
dbg(" %d. ch_flags=%02x ch_pid=%d ch_status=%d\n",
|
||||||
i, child->ch_flags, child->ch_pid, child->ch_status);
|
i, child->ch_flags, child->ch_pid, child->ch_status);
|
||||||
@@ -250,10 +251,12 @@ void task_freechild(FAR struct child_status_s *child)
|
|||||||
|
|
||||||
void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child)
|
void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child)
|
||||||
{
|
{
|
||||||
|
FAR struct task_group_s *group = tcb->group;
|
||||||
|
|
||||||
/* Add the entry into the TCB list of children */
|
/* Add the entry into the TCB list of children */
|
||||||
|
|
||||||
child->flink = tcb->children;
|
child->flink = group->tg_children;
|
||||||
tcb->children = child;
|
group->tg_children = child;
|
||||||
|
|
||||||
task_dumpchildren(tcb, "task_addchild");
|
task_dumpchildren(tcb, "task_addchild");
|
||||||
}
|
}
|
||||||
@@ -282,11 +285,12 @@ void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child)
|
|||||||
|
|
||||||
FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
|
FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
|
||||||
{
|
{
|
||||||
|
FAR struct task_group_s *group = tcb->group;
|
||||||
FAR struct child_status_s *child;
|
FAR struct child_status_s *child;
|
||||||
|
|
||||||
/* Find the status structure with the matching PID */
|
/* Find the status structure with the matching PID */
|
||||||
|
|
||||||
for (child = tcb->children; child; child = child->flink)
|
for (child = group->tg_children; child; child = child->flink)
|
||||||
{
|
{
|
||||||
if (child->ch_pid == pid)
|
if (child->ch_pid == pid)
|
||||||
{
|
{
|
||||||
@@ -318,11 +322,12 @@ FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
|
|||||||
|
|
||||||
FAR struct child_status_s *task_exitchild(FAR _TCB *tcb)
|
FAR struct child_status_s *task_exitchild(FAR _TCB *tcb)
|
||||||
{
|
{
|
||||||
|
FAR struct task_group_s *group = tcb->group;
|
||||||
FAR struct child_status_s *child;
|
FAR struct child_status_s *child;
|
||||||
|
|
||||||
/* Find the status structure of any child task that has exitted. */
|
/* Find the status structure of any child task that has exitted. */
|
||||||
|
|
||||||
for (child = tcb->children; child; child = child->flink)
|
for (child = group->tg_children; child; child = child->flink)
|
||||||
{
|
{
|
||||||
if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
|
if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
|
||||||
{
|
{
|
||||||
@@ -357,12 +362,13 @@ FAR struct child_status_s *task_exitchild(FAR _TCB *tcb)
|
|||||||
|
|
||||||
FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
|
FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
|
||||||
{
|
{
|
||||||
|
FAR struct task_group_s *group = tcb->group;
|
||||||
FAR struct child_status_s *curr;
|
FAR struct child_status_s *curr;
|
||||||
FAR struct child_status_s *prev;
|
FAR struct child_status_s *prev;
|
||||||
|
|
||||||
/* Find the status structure with the matching PID */
|
/* Find the status structure with the matching PID */
|
||||||
|
|
||||||
for (prev = NULL, curr = tcb->children;
|
for (prev = NULL, curr = group->tg_children;
|
||||||
curr;
|
curr;
|
||||||
prev = curr, curr = curr->flink)
|
prev = curr, curr = curr->flink)
|
||||||
{
|
{
|
||||||
@@ -384,7 +390,7 @@ FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tcb->children = curr->flink;
|
group->tg_children = curr->flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
curr->flink = NULL;
|
curr->flink = NULL;
|
||||||
@@ -414,18 +420,19 @@ FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
|
|||||||
|
|
||||||
void task_removechildren(FAR _TCB *tcb)
|
void task_removechildren(FAR _TCB *tcb)
|
||||||
{
|
{
|
||||||
|
FAR struct task_group_s *group = tcb->group;
|
||||||
FAR struct child_status_s *curr;
|
FAR struct child_status_s *curr;
|
||||||
FAR struct child_status_s *next;
|
FAR struct child_status_s *next;
|
||||||
|
|
||||||
/* Remove all child structures for the TCB and return them to the freelist */
|
/* Remove all child structures for the TCB and return them to the freelist */
|
||||||
|
|
||||||
for (curr = tcb->children; curr; curr = next)
|
for (curr = group->tg_children; curr; curr = next)
|
||||||
{
|
{
|
||||||
next = curr->flink;
|
next = curr->flink;
|
||||||
task_freechild(curr);
|
task_freechild(curr);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcb->children = NULL;
|
group->tg_children = NULL;
|
||||||
task_dumpchildren(tcb, "task_removechildren");
|
task_dumpchildren(tcb, "task_removechildren");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
|
|||||||
{
|
{
|
||||||
FAR _TCB *tcb;
|
FAR _TCB *tcb;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int errcode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Allocate a TCB for the new task. */
|
/* Allocate a TCB for the new task. */
|
||||||
@@ -115,15 +116,28 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
|
|||||||
tcb = (FAR _TCB*)kzalloc(sizeof(_TCB));
|
tcb = (FAR _TCB*)kzalloc(sizeof(_TCB));
|
||||||
if (!tcb)
|
if (!tcb)
|
||||||
{
|
{
|
||||||
|
errcode = ENOMEM;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a new task group */
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
ret = group_create(tcb);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
errcode = -ret;
|
||||||
|
goto errout_with_tcb;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Associate file descriptors with the new task */
|
/* Associate file descriptors with the new task */
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
ret = sched_setuptaskfiles(tcb);
|
ret = sched_setuptaskfiles(tcb);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
|
errcode = -ret;
|
||||||
goto errout_with_tcb;
|
goto errout_with_tcb;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -138,6 +152,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
|
|||||||
ret = up_create_stack(tcb, stack_size);
|
ret = up_create_stack(tcb, stack_size);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
|
errcode = -ret;
|
||||||
goto errout_with_tcb;
|
goto errout_with_tcb;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -147,6 +162,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
|
|||||||
ret = task_schedsetup(tcb, priority, task_start, entry, ttype);
|
ret = task_schedsetup(tcb, priority, task_start, entry, ttype);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
|
errcode = -ret;
|
||||||
goto errout_with_tcb;
|
goto errout_with_tcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +179,8 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
|
|||||||
ret = task_activate(tcb);
|
ret = task_activate(tcb);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
|
errcode = get_errno();
|
||||||
|
|
||||||
/* The TCB was added to the active task list by task_schedsetup() */
|
/* The TCB was added to the active task list by task_schedsetup() */
|
||||||
|
|
||||||
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
|
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
|
||||||
@@ -175,7 +193,7 @@ errout_with_tcb:
|
|||||||
sched_releasetcb(tcb);
|
sched_releasetcb(tcb);
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
errno = ENOMEM;
|
set_errno(errcode);
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+70
-40
@@ -197,39 +197,28 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||||
static inline void task_sigchild(FAR _TCB *tcb, int status)
|
static inline void task_sigchild(FAR _TCB *ptcb, FAR _TCB *ctcb, int status)
|
||||||
{
|
{
|
||||||
FAR _TCB *ptcb;
|
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
|
|
||||||
/* Only exiting tasks should generate SIGCHLD. pthreads use other
|
/* Only the final exiting thread in a task group should generate SIGCHLD.
|
||||||
* mechansims.
|
* If task groups are not supported then we will report SIGCHLD when the
|
||||||
|
* task exits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
|
|
||||||
{
|
|
||||||
/* Keep things stationary through the following */
|
|
||||||
|
|
||||||
sched_lock();
|
|
||||||
|
|
||||||
/* Get the TCB of the receiving task */
|
|
||||||
|
|
||||||
ptcb = sched_gettcb(tcb->parent);
|
|
||||||
if (!ptcb)
|
|
||||||
{
|
|
||||||
/* The parent no longer exists... bail */
|
|
||||||
|
|
||||||
sched_unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_CHILD_STATUS
|
#ifdef CONFIG_SCHED_CHILD_STATUS
|
||||||
/* Check if the parent task has suppressed retention of child exit
|
if (ctcb->group->tg_crefs == 1)
|
||||||
|
#else
|
||||||
|
if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SCHED_CHILD_STATUS
|
||||||
|
/* Check if the parent task group has suppressed retention of child exit
|
||||||
* status information. Only 'tasks' report exit status, not pthreads.
|
* status information. Only 'tasks' report exit status, not pthreads.
|
||||||
* pthreads have a different mechanism.
|
* pthreads have a different mechanism.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((ptcb->flags & TCB_FLAG_NOCLDWAIT) == 0)
|
if ((ptcb->group->tg_flags & GROUP_FLAG_NOCLDWAIT) == 0)
|
||||||
{
|
{
|
||||||
FAR struct child_status_s *child;
|
FAR struct child_status_s *child;
|
||||||
|
|
||||||
@@ -255,15 +244,6 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
|
|||||||
ptcb->nchildren--;
|
ptcb->nchildren--;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set the parent to an impossible PID. We do this because under
|
|
||||||
* certain conditions, task_exithook() can be called multiple times.
|
|
||||||
* If this function is called again, sched_gettcb() will fail on the
|
|
||||||
* invalid parent PID above, nchildren will be decremented once and
|
|
||||||
* all will be well.
|
|
||||||
*/
|
|
||||||
|
|
||||||
tcb->parent = INVALID_PROCESS_ID;
|
|
||||||
|
|
||||||
/* Create the siginfo structure. We don't actually know the cause.
|
/* Create the siginfo structure. We don't actually know the cause.
|
||||||
* That is a bug. Let's just say that the child task just exit-ted
|
* That is a bug. Let's just say that the child task just exit-ted
|
||||||
* for now.
|
* for now.
|
||||||
@@ -272,7 +252,7 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
|
|||||||
info.si_signo = SIGCHLD;
|
info.si_signo = SIGCHLD;
|
||||||
info.si_code = CLD_EXITED;
|
info.si_code = CLD_EXITED;
|
||||||
info.si_value.sival_ptr = NULL;
|
info.si_value.sival_ptr = NULL;
|
||||||
info.si_pid = tcb->pid;
|
info.si_pid = ctcb->pid;
|
||||||
info.si_status = status;
|
info.si_status = status;
|
||||||
|
|
||||||
/* Send the signal. We need to use this internal interface so that we
|
/* Send the signal. We need to use this internal interface so that we
|
||||||
@@ -280,11 +260,59 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
(void)sig_received(ptcb, &info);
|
(void)sig_received(ptcb, &info);
|
||||||
sched_unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# define task_sigchild(tcb,status)
|
# define task_sigchild(ptct,ctcb,status)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: task_leavegroup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Send the SIGCHILD signal to the parent thread
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||||
|
static inline void task_leavegroup(FAR _TCB *ctcb, int status)
|
||||||
|
{
|
||||||
|
FAR _TCB *ptcb;
|
||||||
|
|
||||||
|
/* Keep things stationary throughout the following */
|
||||||
|
|
||||||
|
sched_lock();
|
||||||
|
|
||||||
|
/* Get the TCB of the receiving, parent task. We do this early to
|
||||||
|
* handle multiple calls to task_leavegroup. ctcb->parent is set to an
|
||||||
|
* invalid value below and the following call will fail if we are
|
||||||
|
* called again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ptcb = sched_gettcb(ctcb->parent);
|
||||||
|
if (!ptcb)
|
||||||
|
{
|
||||||
|
/* The parent no longer exists... bail */
|
||||||
|
|
||||||
|
sched_unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send SIGCHLD to all members of the parent's task group */
|
||||||
|
|
||||||
|
task_sigchild(ptcb, ctcb, status);
|
||||||
|
|
||||||
|
/* Set the parent to an impossible PID. We do this because under certain
|
||||||
|
* conditions, task_exithook() can be called multiple times. If this
|
||||||
|
* function is called again, sched_gettcb() will fail on the invalid
|
||||||
|
* parent PID above and all will be well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ctcb->parent = INVALID_PROCESS_ID;
|
||||||
|
sched_unlock();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define task_leavegroup(ctcb,status)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -363,9 +391,9 @@ void task_exithook(FAR _TCB *tcb, int status)
|
|||||||
|
|
||||||
task_onexit(tcb, status);
|
task_onexit(tcb, status);
|
||||||
|
|
||||||
/* Send SIGCHLD to the parent of the exit-ing task */
|
/* Leave the task group */
|
||||||
|
|
||||||
task_sigchild(tcb, status);
|
task_leavegroup(tcb, status);
|
||||||
|
|
||||||
/* Wakeup any tasks waiting for this task to exit */
|
/* Wakeup any tasks waiting for this task to exit */
|
||||||
|
|
||||||
@@ -379,10 +407,12 @@ void task_exithook(FAR _TCB *tcb, int status)
|
|||||||
(void)lib_flushall(tcb->streams);
|
(void)lib_flushall(tcb->streams);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Discard any un-reaped child status (no zombies here!) */
|
/* Leave the task group. Perhaps discarding any un-reaped child
|
||||||
|
* status (no zombies here!)
|
||||||
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
|
#ifdef HAVE_TASK_GROUP
|
||||||
task_removechildren(tcb);
|
group_leave(tcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Free all file-related resources now. This gets called again
|
/* Free all file-related resources now. This gets called again
|
||||||
|
|||||||
+41
-11
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/task_init.c
|
* sched/task_init.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -42,6 +42,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
|
|
||||||
#include "os_internal.h"
|
#include "os_internal.h"
|
||||||
@@ -102,10 +104,10 @@
|
|||||||
* parameters are required, argv may be NULL.
|
* parameters are required, argv may be NULL.
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* OK on success; ERROR on failure. (See task_schedsetup() for possible
|
* OK on success; ERROR on failure with errno set appropriately. (See
|
||||||
* failure conditions). On failure, the caller is responsible for freeing
|
* task_schedsetup() for possible failure conditions). On failure, the
|
||||||
* the stack memory and for calling sched_releasetcb() to free the TCB
|
* caller is responsible for freeing the stack memory and for calling
|
||||||
* (which could be in most any state).
|
* sched_releasetcb() to free the TCB (which could be in most any state).
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@@ -118,14 +120,28 @@ int task_init(FAR _TCB *tcb, const char *name, int priority,
|
|||||||
main_t entry, const char *argv[])
|
main_t entry, const char *argv[])
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
int errcode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Create a new task group */
|
||||||
|
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
ret = group_create(tcb);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
errcode = -ret;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Associate file descriptors with the new task */
|
/* Associate file descriptors with the new task */
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
if (sched_setuptaskfiles(tcb) != OK)
|
ret = sched_setuptaskfiles(tcb);
|
||||||
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ERROR;
|
errcode = -ret;
|
||||||
|
goto errout_with_group;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -143,13 +159,27 @@ int task_init(FAR _TCB *tcb, const char *name, int priority,
|
|||||||
|
|
||||||
ret = task_schedsetup(tcb, priority, task_start, entry,
|
ret = task_schedsetup(tcb, priority, task_start, entry,
|
||||||
TCB_FLAG_TTYPE_TASK);
|
TCB_FLAG_TTYPE_TASK);
|
||||||
if (ret == OK)
|
if (ret < OK)
|
||||||
{
|
{
|
||||||
|
errcode = -ret;
|
||||||
|
goto errout_with_env;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup to pass parameters to the new task */
|
/* Setup to pass parameters to the new task */
|
||||||
|
|
||||||
(void)task_argsetup(tcb, name, argv);
|
(void)task_argsetup(tcb, name, argv);
|
||||||
}
|
return OK;
|
||||||
|
|
||||||
return ret;
|
errout_with_env:
|
||||||
|
env_release(tcb);
|
||||||
|
|
||||||
|
errout_with_group:
|
||||||
|
#ifdef HAVE_TASK_GROUP
|
||||||
|
group_leave(tcb);
|
||||||
|
|
||||||
|
errout:
|
||||||
|
#endif
|
||||||
|
set_errno(errcode);
|
||||||
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,11 +138,11 @@ int task_reparent(pid_t ppid, pid_t chpid)
|
|||||||
child = task_removechild(otcb, chpid);
|
child = task_removechild(otcb, chpid);
|
||||||
if (child)
|
if (child)
|
||||||
{
|
{
|
||||||
/* Has the new parent supressed child exit status? */
|
/* Has the new parent's task group supressed child exit status? */
|
||||||
|
|
||||||
if ((ptcb->flags && TCB_FLAG_NOCLDWAIT) == 0)
|
if ((ptcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0)
|
||||||
{
|
{
|
||||||
/* No.. Add the child status entry to the new parent TCB */
|
/* No.. Add the child status entry to the new parent's task group */
|
||||||
|
|
||||||
task_addchild(ptcb, child);
|
task_addchild(ptcb, child);
|
||||||
}
|
}
|
||||||
@@ -159,11 +159,11 @@ int task_reparent(pid_t ppid, pid_t chpid)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This would not be an error if the original parent has
|
/* This would not be an error if the original parent's task group has
|
||||||
* suppressed child exit status.
|
* suppressed child exit status.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = ((otcb->flags && TCB_FLAG_NOCLDWAIT) == 0) ? -ENOENT : OK;
|
ret = ((otcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0) ? -ENOENT : OK;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
DEBUGASSERT(otcb->nchildren > 0);
|
DEBUGASSERT(otcb->nchildren > 0);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* sched/task_setup.c
|
* sched/task_setup.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -179,13 +179,11 @@ static inline void task_saveparent(FAR _TCB *tcb, uint8_t ttype)
|
|||||||
tcb->parent = rtcb->pid;
|
tcb->parent = rtcb->pid;
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_CHILD_STATUS
|
#ifdef CONFIG_SCHED_CHILD_STATUS
|
||||||
/* Exit status only needs to be retained for the case of tasks, however.
|
/* Tasks can also suppress retention of their child status by applying
|
||||||
* Tasks can also suppress retention of their child status by applying
|
* the SA_NOCLDWAIT flag with sigaction().
|
||||||
* the SA_NOCLDWAIT flag with sigaction()/
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ttype == TCB_FLAG_TTYPE_TASK &&
|
if ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0)
|
||||||
(rtcb->flags && TCB_FLAG_NOCLDWAIT) == 0)
|
|
||||||
{
|
{
|
||||||
FAR struct child_status_s *child;
|
FAR struct child_status_s *child;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user