nuttx/include/nuttx/sched.h

706 lines
27 KiB
C

/********************************************************************************
* include/nuttx/sched.h
*
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************/
#ifndef __INCLUDE_NUTTX_SCHED_H
#define __INCLUDE_NUTTX_SCHED_H
/********************************************************************************
* Included Files
********************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <queue.h>
#include <signal.h>
#include <semaphore.h>
#include <pthread.h>
#include <mqueue.h>
#include <time.h>
#include <nuttx/irq.h>
#include <nuttx/fs/fs.h>
#include <nuttx/net/net.h>
/********************************************************************************
* Pre-processor Definitions
********************************************************************************/
/* Configuration ****************************************************************/
/* Task groups currently only supported for retention of child status */
#undef HAVE_TASK_GROUP
#undef HAVE_GROUP_MEMBERS
/* We need a group an group members if we are supporting the parent/child
* relationship.
*/
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
# define HAVE_TASK_GROUP 1
# define HAVE_GROUP_MEMBERS 1
/* We need a group (but not members) if any other resources are shared within
* a task group. NOTE: that we essentially always need a task group and that
* managing this definition adds a lot of overhead just to handle a corner-
* case very minimal system!
*/
#else
# if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SCHED_HAVE_PARENT)
# define HAVE_TASK_GROUP 1 /* pthreads with parent*/
# elif !defined(CONFIG_DISABLE_ENVIRON)
# define HAVE_TASK_GROUP 1 /* Environment variables */
# elif !defined(CONFIG_DISABLE_SIGNALS)
# define HAVE_TASK_GROUP 1 /* Signals */
# elif defined(CONFIG_SCHED_ATEXIT)
# define HAVE_TASK_GROUP 1 /* Group atexit() function */
# elif defined(CONFIG_SCHED_ONEXIT)
# define HAVE_TASK_GROUP 1 /* Group on_exit() function */
# elif defined(CONFIG_SCHED_WAITPID)
# define HAVE_TASK_GROUP 1 /* Group waitpid() function */
# elif CONFIG_NFILE_DESCRIPTORS > 0
# define HAVE_TASK_GROUP 1 /* File descriptors */
# elif CONFIG_NFILE_STREAMS > 0
# define HAVE_TASK_GROUP 1 /* Standard C buffered I/O */
# elif CONFIG_NSOCKET_DESCRIPTORS > 0
# define HAVE_TASK_GROUP 1 /* Sockets */
# elif !defined(CONFIG_DISABLE_MQUEUE)
# define HAVE_TASK_GROUP 1 /* Message queues */
# endif
#endif
/* In any event, we don't need group members if support for pthreads is disabled */
#ifdef CONFIG_DISABLE_PTHREAD
# undef HAVE_GROUP_MEMBERS
#endif
/* Task Management Definitions **************************************************/
/* This is the maximum number of times that a lock can be set */
#define MAX_LOCK_COUNT 127
/* Values for the struct tcb_s flags bits */
#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_TASK (0 << TCB_FLAG_TTYPE_SHIFT) /* Normal user task */
# define TCB_FLAG_TTYPE_PTHREAD (1 << TCB_FLAG_TTYPE_SHIFT) /* User pthread */
# define TCB_FLAG_TTYPE_KERNEL (2 << TCB_FLAG_TTYPE_SHIFT) /* Kernel thread */
#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_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */
#define TCB_FLAG_EXIT_PROCESSING (1 << 5) /* Bit 5: Exitting */
/* 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 */
#define CHILD_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: child thread type */
#define CHILD_FLAG_TTYPE_MASK (3 << CHILD_FLAG_TTYPE_SHIFT)
# define CHILD_FLAG_TTYPE_TASK (0 << CHILD_FLAG_TTYPE_SHIFT) /* Normal user task */
# define CHILD_FLAG_TTYPE_PTHREAD (1 << CHILD_FLAG_TTYPE_SHIFT) /* User pthread */
# define CHILD_FLAG_TTYPE_KERNEL (2 << CHILD_FLAG_TTYPE_SHIFT) /* Kernel thread */
#define CHILD_FLAG_EXITED (1 << 0) /* Bit 2: The child thread has exit'ed */
/********************************************************************************
* Public Type Definitions
********************************************************************************/
#ifndef __ASSEMBLY__
/* General Task Management Types ************************************************/
/* This is the type of the task_state field of the TCB. NOTE: the order and
* content of this enumeration is critical since there are some OS tables indexed
* by these values. The range of values is assumed to fit into a uint8_t in
* struct tcb_s.
*/
enum tstate_e
{
TSTATE_TASK_INVALID = 0, /* INVALID - The TCB is uninitialized */
TSTATE_TASK_PENDING, /* READY_TO_RUN - Pending preemption unlock */
TSTATE_TASK_READYTORUN, /* READY-TO-RUN - But not running */
TSTATE_TASK_RUNNING, /* READY_TO_RUN - And running */
TSTATE_TASK_INACTIVE, /* BLOCKED - Initialized but not yet activated */
TSTATE_WAIT_SEM, /* BLOCKED - Waiting for a semaphore */
#ifndef CONFIG_DISABLE_SIGNALS
TSTATE_WAIT_SIG, /* BLOCKED - Waiting for a signal */
#endif
#ifndef CONFIG_DISABLE_MQUEUE
TSTATE_WAIT_MQNOTEMPTY, /* BLOCKED - Waiting for a MQ to become not empty. */
TSTATE_WAIT_MQNOTFULL, /* BLOCKED - Waiting for a MQ to become not full. */
#endif
#ifdef CONFIG_PAGING
TSTATE_WAIT_PAGEFILL, /* BLOCKED - Waiting for page fill */
#endif
NUM_TASK_STATES /* Must be last */
};
typedef enum tstate_e tstate_t;
/* The following definitions are determined by tstate_t */
#define FIRST_READY_TO_RUN_STATE TSTATE_TASK_READYTORUN
#define LAST_READY_TO_RUN_STATE TSTATE_TASK_RUNNING
#define FIRST_BLOCKED_STATE TSTATE_TASK_INACTIVE
#define LAST_BLOCKED_STATE (NUM_TASK_STATES-1)
/* The following is the form of a thread start-up function */
typedef CODE void (*start_t)(void);
/* This is the entry point into the main thread of the task or into a created
* pthread within the task.
*/
union entry_u
{
pthread_startroutine_t pthread;
main_t main;
};
typedef union entry_u entry_t;
/* This is the type of the function called at task startup */
#ifdef CONFIG_SCHED_STARTHOOK
typedef CODE void (*starthook_t)(FAR void *arg);
#endif
/* These are the types of the functions that are executed with exit() is called
* (if registered via atexit() on on_exit()).
*/
#ifdef CONFIG_SCHED_ATEXIT
typedef CODE void (*atexitfunc_t)(void);
#endif
#ifdef CONFIG_SCHED_ONEXIT
typedef CODE void (*onexitfunc_t)(int exitcode, FAR void *arg);
#endif
/* POSIX Message queue */
typedef struct msgq_s msgq_t;
/* struct child_status_s *********************************************************/
/* This structure is used to maintin information about child tasks.
* pthreads work differently, they have join information. This is
* only for child tasks.
*/
#ifdef CONFIG_SCHED_CHILD_STATUS
struct child_status_s
{
FAR struct child_status_s *flink;
uint8_t ch_flags; /* Child status: See CHILD_FLAG_* definitions */
pid_t ch_pid; /* Child task ID */
int ch_status; /* Child exit status */
};
#endif
/* struct dspace_s ***************************************************************/
/* 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
* any pthreads created by the task.
*/
#ifdef CONFIG_PIC
struct dspace_s
{
/* The life of the structure allocation is determined by this reference
* count. This count is number of threads that shared the same D-Space.
* This includes the parent task as well as any pthreads created by the
* parent task or any of its child threads.
*/
uint16_t crefs;
/* This is the allocated D-Space memory region. This may be a physical
* address allocated with kmalloc(), or it may be virtual address associated
* with an address environment (if CONFIG_ADDRENV=y).
*/
FAR uint8_t *region;
};
#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
#ifndef CONFIG_DISABLE_PTHREAD
struct join_s; /* Forward reference */
/* Defined in pthread_internal.h */
#endif
struct task_group_s
{
#ifdef HAVE_GROUP_MEMBERS
struct task_group_s *flink; /* Supports a singly linked list */
gid_t tg_gid; /* The ID of this task group */
gid_t tg_pgid; /* The ID of the parent task group */
#endif
#if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SCHED_HAVE_PARENT)
pid_t tg_task; /* The ID of the task within the group */
#endif
uint8_t tg_flags; /* See GROUP_FLAG_* definitions */
/* Group membership ***********************************************************/
uint8_t tg_nmembers; /* Number of members in the group */
#ifdef HAVE_GROUP_MEMBERS
uint8_t tg_mxmembers; /* Number of members in allocation */
FAR pid_t *tg_members; /* Members of the group */
#endif
/* atexit/on_exit support ****************************************************/
#if defined(CONFIG_SCHED_ATEXIT) && !defined(CONFIG_SCHED_ONEXIT)
# if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1
atexitfunc_t tg_atexitfunc[CONFIG_SCHED_ATEXIT_MAX];
# else
atexitfunc_t tg_atexitfunc; /* Called when exit is called. */
# endif
#endif
#ifdef CONFIG_SCHED_ONEXIT
# if defined(CONFIG_SCHED_ONEXIT_MAX) && CONFIG_SCHED_ONEXIT_MAX > 1
onexitfunc_t tg_onexitfunc[CONFIG_SCHED_ONEXIT_MAX];
FAR void *tg_onexitarg[CONFIG_SCHED_ONEXIT_MAX];
# else
onexitfunc_t tg_onexitfunc; /* Called when exit is called. */
FAR void *tg_onexitarg; /* The argument passed to the function */
# endif
#endif
/* Child exit status **********************************************************/
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
FAR struct child_status_s *tg_children; /* Head of a list of child status */
#endif
/* waitpid support ************************************************************/
/* Simple mechanism used only when there is no support for SIGCHLD */
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
sem_t tg_exitsem; /* Support for waitpid */
int *tg_statloc; /* Location to return exit status */
#endif
/* Pthreads *******************************************************************/
#ifndef CONFIG_DISABLE_PTHREAD
/* Pthread join Info: */
sem_t tg_joinsem; /* Mutually exclusive access to join data */
FAR struct join_s *tg_joinhead; /* Head of a list of join data */
FAR struct join_s *tg_jointail; /* Tail of a list of join data */
uint8_t tg_nkeys; /* Number pthread keys allocated */
#endif
/* POSIX Signal Control Fields ************************************************/
#ifndef CONFIG_DISABLE_SIGNALS
sq_queue_t sigpendingq; /* List of pending signals */
#endif
/* Environment variables ******************************************************/
#ifndef CONFIG_DISABLE_ENVIRON
size_t tg_envsize; /* Size of environment string allocation */
FAR char *tg_envp; /* Allocated environment strings */
#endif
/* PIC data space and address environments ************************************/
/* Logically the PIC data space belongs here (see struct dspace_s). The
* current logic needs review: There are differences in the away that the
* life of the PIC data is managed.
*/
/* File descriptors ***********************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
struct filelist tg_filelist; /* Maps file descriptor to file */
#endif
/* FILE streams ***************************************************************/
/* In a flat, single-heap build. The stream list is allocated with this
* structure. But kernel mode with a kernel allocator, it must be separately
* allocated using a user-space allocator.
*/
#if CONFIG_NFILE_STREAMS > 0
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
FAR struct streamlist *tg_streamlist;
#else
struct streamlist tg_streamlist; /* Holds C buffered I/O info */
#endif
#endif
/* Sockets ********************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
struct socketlist tg_socketlist; /* Maps socket descriptor to socket */
#endif
/* POSIX Named Message Queue Fields *******************************************/
#ifndef CONFIG_DISABLE_MQUEUE
sq_queue_t tg_msgdesq; /* List of opened message queues */
#endif
};
#endif
/* struct tcb_s ******************************************************************/
/* This is the common part of the task control block (TCB). The TCB is the heart
* of the NuttX task-control logic. Each task or thread is represented by a TCB
* that includes these common definitions.
*/
FAR struct wdog_s; /* Forward reference */
struct tcb_s
{
/* Fields used to support list management *************************************/
FAR struct tcb_s *flink; /* Doubly linked list */
FAR struct tcb_s *blink;
/* Task Group *****************************************************************/
#ifdef HAVE_TASK_GROUP
FAR struct task_group_s *group; /* Pointer to shared task group data */
#endif
/* Task Management Fields *****************************************************/
pid_t pid; /* This is the ID of the thread */
#ifdef CONFIG_SCHED_HAVE_PARENT /* Support parent-child relationship */
#ifndef HAVE_GROUP_MEMBERS /* Don't know pids of group members */
pid_t ppid; /* This is the ID of the parent thread */
#ifndef CONFIG_SCHED_CHILD_STATUS /* Retain child thread status */
uint16_t nchildren; /* This is the number active children */
#endif
#endif
#endif /* CONFIG_SCHED_HAVE_PARENT */
start_t start; /* Thread start function */
entry_t entry; /* Entry Point into the thread */
uint8_t sched_priority; /* Current priority of the thread */
#ifdef CONFIG_PRIORITY_INHERITANCE
# if CONFIG_SEM_NNESTPRIO > 0
uint8_t npend_reprio; /* Number of nested reprioritizations */
uint8_t pend_reprios[CONFIG_SEM_NNESTPRIO];
# endif
uint8_t base_priority; /* "Normal" priority of the thread */
#endif
uint8_t task_state; /* Current state of the thread */
uint16_t flags; /* Misc. general status flags */
int16_t lockcount; /* 0=preemptable (not-locked) */
#if CONFIG_RR_INTERVAL > 0
int timeslice; /* RR timeslice interval remaining */
#endif
FAR struct wdog_s *waitdog; /* All timed waits used this wdog */
/* Stack-Related Fields *******************************************************/
#ifndef CONFIG_CUSTOM_STACK
size_t adj_stack_size; /* Stack size after adjustment */
/* for hardware, processor, etc. */
/* (for debug purposes only) */
FAR void *stack_alloc_ptr; /* Pointer to allocated stack */
/* Need to deallocate stack */
FAR void *adj_stack_ptr; /* Adjusted stack_alloc_ptr for HW */
/* The initial stack pointer value */
#endif
/* External Module Support ****************************************************/
#ifdef CONFIG_PIC
FAR struct dspace_s *dspace; /* Allocated area for .bss and .data */
#endif
/* POSIX Semaphore Control Fields *********************************************/
sem_t *waitsem; /* Semaphore ID waiting on */
/* POSIX Signal Control Fields ************************************************/
#ifndef CONFIG_DISABLE_SIGNALS
sigset_t sigprocmask; /* Signals that are blocked */
sigset_t sigwaitmask; /* Waiting for pending signals */
sq_queue_t sigactionq; /* List of actions for signals */
sq_queue_t sigpendactionq; /* List of pending signal actions */
sq_queue_t sigpostedq; /* List of posted signals */
siginfo_t sigunbinfo; /* Signal info when task unblocked */
#endif
/* POSIX Named Message Queue Fields *******************************************/
#ifndef CONFIG_DISABLE_MQUEUE
FAR msgq_t *msgwaitq; /* Waiting for this message queue */
#endif
/* Library related fields *****************************************************/
int pterrno; /* Current per-thread errno */
/* State save areas ***********************************************************/
/* The form and content of these fields are processor-specific. */
struct xcptcontext xcp; /* Interrupt register save area */
#if CONFIG_TASK_NAME_SIZE > 0
char name[CONFIG_TASK_NAME_SIZE]; /* Task name */
#endif
};
/* struct task_tcb_s *************************************************************/
/* This is the particular form of the task control block (TCB) structure used by
* tasks (and kernel threads). There are two TCB forms: one for pthreads and
* one for tasks. Both share the common TCB fields (which must appear at the
* top of the structure) plus additional fields unique to tasks and threads.
* Having separate structures for tasks and pthreads adds some complexity, but
* saves memory in that it prevents pthreads from being burdened with the
* overhead required for tasks (and vice versa).
*/
struct task_tcb_s
{
/* Common TCB fields **********************************************************/
struct tcb_s cmn; /* Common TCB fields */
/* Task Management Fields *****************************************************/
#ifdef CONFIG_SCHED_STARTHOOK
starthook_t starthook; /* Task startup function */
FAR void *starthookarg; /* The argument passed to the function */
#endif
/* Values needed to restart a task ********************************************/
uint8_t init_priority; /* Initial priority of the task */
#if !defined(CONFIG_CUSTOM_STACK) && defined(CONFIG_NUTTX_KERNEL)
/* In the kernel mode build, the arguments are saved on the task's stack */
FAR char **argv; /* Name+start-up parameters */
#else
/* Otherwise, the arguments are strdup'ed and the argv[] is statically */
/* defined here: */
char *argv[CONFIG_MAX_TASK_ARGS+1]; /* Name+start-up parameters */
#endif
};
/* struct pthread_tcb_s **********************************************************/
/* This is the particular form of the task control block (TCB) structure used by
* pthreads. There are two TCB forms: one for pthreads and one for tasks. Both
* share the common TCB fields (which must appear at the top of the structure)
* plus additional fields unique to tasks and threads. Having separate structures
* for tasks and pthreads adds some complexity, but saves memory in that it
* prevents pthreads from being burdened with the overhead required for tasks
* (and vice versa).
*/
#ifndef CONFIG_DISABLE_PTHREAD
struct pthread_tcb_s
{
/* Common TCB fields **********************************************************/
struct tcb_s cmn; /* Common TCB fields */
/* Task Management Fields *****************************************************/
pthread_addr_t arg; /* Startup argument */
FAR void *joininfo; /* Detach-able info to support join */
/* POSIX Thread Specific Data *************************************************/
#if CONFIG_NPTHREAD_KEYS > 0
FAR void *pthread_data[CONFIG_NPTHREAD_KEYS];
#endif
};
#endif /* !CONFIG_DISABLE_PTHREAD */
/* This is the callback type used by sched_foreach() */
typedef void (*sched_foreach_t)(FAR struct tcb_s *tcb, FAR void *arg);
#endif /* __ASSEMBLY__ */
/********************************************************************************
* Public Data
********************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/********************************************************************************
* Public Function Prototypes
********************************************************************************/
/* TCB helpers ******************************************************************/
/* sched_self() returns the TCB of the currently running task (i.e., the
* caller)
*/
FAR struct tcb_s *sched_self(void);
/* sched_foreach will enumerate over each task and provide the TCB of each task
* or thread to a callback function. Interrupts will be disabled throughout
* this enumeration!
*/
void sched_foreach(sched_foreach_t handler, FAR void *arg);
/* Give a task ID, look up the corresponding TCB */
FAR struct tcb_s *sched_gettcb(pid_t pid);
/* File system helpers **********************************************************/
/* These functions all extract lists from the group structure assocated with the
* currently executing task.
*/
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct filelist *sched_getfiles(void);
#if CONFIG_NFILE_STREAMS > 0
FAR struct streamlist *sched_getstreams(void);
#endif /* CONFIG_NFILE_STREAMS */
#endif /* CONFIG_NFILE_DESCRIPTORS */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
FAR struct socketlist *sched_getsockets(void);
#endif /* CONFIG_NSOCKET_DESCRIPTORS */
/********************************************************************************
* Name: task_starthook
*
* Description:
* Configure a start hook... a function that will be called on the thread
* of the new task before the new task's main entry point is called.
* The start hook is useful, for example, for setting up automatic
* configuration of C++ constructors.
*
* Inputs:
* tcb - The new, unstarted task task that needs the start hook
* starthook - The pointer to the start hook function
* arg - The argument to pass to the start hook function.
*
* Return:
* None
*
********************************************************************************/
#ifdef CONFIG_SCHED_STARTHOOK
void task_starthook(FAR struct task_tcb_s *tcb, starthook_t starthook,
FAR void *arg);
#endif
/********************************************************************************
* Internal vfork support. The overall sequence is:
*
* 1) User code calls vfork(). vfork() is provided in architecture-specific
* code.
* 2) vfork()and calls task_vforksetup().
* 3) task_vforksetup() allocates and configures the child task's TCB. This
* consists of:
* - Allocation of the child task's TCB.
* - Initialization of file descriptors and streams
* - Configuration of environment variables
* - Setup the intput parameters for the task.
* - Initialization of the TCB (including call to up_initial_state()
* 4) vfork() provides any additional operating context. vfork must:
* - Allocate and initialize the stack
* - Initialize special values in any CPU registers that were not
* already configured by up_initial_state()
* 5) vfork() then calls task_vforkstart()
* 6) task_vforkstart() then executes the child thread.
*
* task_vforkabort() may be called if an error occurs between steps 3 and 6.
*
********************************************************************************/
FAR struct task_tcb_s *task_vforksetup(start_t retaddr);
pid_t task_vforkstart(FAR struct task_tcb_s *child);
void task_vforkabort(FAR struct task_tcb_s *child, int errcode);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __INCLUDE_NUTTX_SCHED_H */