706 lines
27 KiB
C
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 */
|