/******************************************************************************** * include/nuttx/sched.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ********************************************************************************/ #ifndef __INCLUDE_NUTTX_SCHED_H #define __INCLUDE_NUTTX_SCHED_H /******************************************************************************** * Included Files ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /******************************************************************************** * Pre-processor Definitions ********************************************************************************/ /* Configuration ****************************************************************/ /* Task groups currently only supported for retention of child status */ #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_GROUP_MEMBERS 1 #endif /* We don't need group members if support for pthreads is disabled */ #ifdef CONFIG_DISABLE_PTHREAD # undef HAVE_GROUP_MEMBERS #endif /* Sporadic scheduling */ #ifndef CONFIG_SCHED_SPORADIC_MAXREPL # define CONFIG_SCHED_SPORADIC_MAXREPL 3 #endif /* Task Management Definitions **************************************************/ /* Special task IDS. Any negative PID is invalid. */ #define NULL_TASK_PROCESS_ID (pid_t)0 #define INVALID_PROCESS_ID (pid_t)-1 /* 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_DEFERRED (1 << 3) /* Bit 3: Deferred (vs asynch) cancellation type */ #define TCB_FLAG_CANCEL_PENDING (1 << 4) /* Bit 4: Pthread cancel is pending */ #define TCB_FLAG_POLICY_SHIFT (5) /* Bit 5-6: Scheduling policy */ #define TCB_FLAG_POLICY_MASK (3 << TCB_FLAG_POLICY_SHIFT) # define TCB_FLAG_SCHED_FIFO (0 << TCB_FLAG_POLICY_SHIFT) /* FIFO scheding policy */ # define TCB_FLAG_SCHED_RR (1 << TCB_FLAG_POLICY_SHIFT) /* Round robin scheding policy */ # define TCB_FLAG_SCHED_SPORADIC (2 << TCB_FLAG_POLICY_SHIFT) /* Sporadic scheding policy */ # define TCB_FLAG_SCHED_OTHER (3 << TCB_FLAG_POLICY_SHIFT) /* Other scheding policy */ #define TCB_FLAG_CPU_LOCKED (1 << 7) /* Bit 7: Locked to this CPU */ #define TCB_FLAG_SIGNAL_ACTION (1 << 8) /* Bit 8: In a signal handler */ #define TCB_FLAG_SYSCALL (1 << 9) /* Bit 9: In a system call */ #define TCB_FLAG_EXIT_PROCESSING (1 << 10) /* Bit 10: Exitting */ /* Bits 11-15: Available */ /* Values for struct task_group tg_flags */ #define GROUP_FLAG_NOCLDWAIT (1 << 0) /* Bit 0: Do not retain child exit status */ #define GROUP_FLAG_ADDRENV (1 << 1) /* Bit 1: Group has an address environment */ #define GROUP_FLAG_PRIVILEGED (1 << 2) /* Bit 2: Group is privileged */ #define GROUP_FLAG_DELETED (1 << 3) /* Bit 3: Group has been deleted but not yet freed */ /* Bits 4-7: Available */ /* 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 << 2) /* Bit 2: The child thread has exit'ed */ /* Bits 3-7: Available */ /* Sporadic scheduler flags */ #define SPORADIC_FLAG_ALLOCED (1 << 0) /* Bit 0: Timer is allocated */ #define SPORADIC_FLAG_MAIN (1 << 1) /* Bit 1: The main timer */ #define SPORADIC_FLAG_REPLENISH (1 << 2) /* Bit 2: Replenishment cycle */ /* Bits 3-7: Available */ /* Most internal nxsched_* interfaces are not available in the user space in * PROTECTED and KERNEL builds. In that context, the application semaphore * interfaces must be used. The differences between the two sets of * interfaces are: (1) the nxsched_* interfaces do not cause cancellation * points and (2) they do not modify the errno variable. * * This is only important when compiling libraries (libc or libnx) that are * used both by the OS (libkc.a and libknx.a) or by the applications * (libc.a and libnx.a). In that case, the correct interface must be * used for the build context. * * REVISIT: In the flat build, the same functions must be used both by * the OS and by applications. We have to use the normal user functions * in this case or we will fail to set the errno or fail to create the * cancellation point. */ #if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) # define _SCHED_GETPARAM(t,p) nxsched_get_param(t,p) # define _SCHED_SETPARAM(t,p) nxsched_set_param(t,p) # define _SCHED_GETSCHEDULER(t) nxsched_get_scheduler(t) # define _SCHED_SETSCHEDULER(t,s,p) nxsched_set_scheduler(t,s,p) # define _SCHED_GETAFFINITY(t,c,m) nxsched_get_affinity(t,c,m) # define _SCHED_SETAFFINITY(t,c,m) nxsched_set_affinity(t,c,m) # define _SCHED_ERRNO(r) (-(r)) # define _SCHED_ERRVAL(r) (r) #else # define _SCHED_GETPARAM(t,p) sched_getparam(t,p) # define _SCHED_SETPARAM(t,p) sched_setparam(t,p) # define _SCHED_GETSCHEDULER(t) sched_getscheduler(t) # define _SCHED_SETSCHEDULER(t,s,p) sched_setscheduler(t,s,p) # define _SCHED_GETAFFINITY(t,c,m) sched_getaffinity(t,c,m) # define _SCHED_SETAFFINITY(t,c,m) sched_setaffinity(t,c,m) # define _SCHED_ERRNO(r) errno # define _SCHED_ERRVAL(r) (-errno) #endif /* The number of callback can be saved */ #if defined(CONFIG_SCHED_ONEXIT_MAX) # define CONFIG_SCHED_EXIT_MAX CONFIG_SCHED_ONEXIT_MAX #elif defined(CONFIG_SCHED_ATEXIT_MAX) # define CONFIG_SCHED_EXIT_MAX CONFIG_SCHED_ATEXIT_MAX #endif #if defined(CONFIG_SCHED_EXIT_MAX) && CONFIG_SCHED_EXIT_MAX < 1 # error "CONFIG_SCHED_EXIT_MAX < 1" #endif /******************************************************************************** * 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 */ #ifdef CONFIG_SMP TSTATE_TASK_ASSIGNED, /* READY-TO-RUN - Not running, but assigned to a CPU */ #endif 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 */ TSTATE_WAIT_SIG, /* BLOCKED - Waiting for a signal */ #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 #ifdef CONFIG_SIG_SIGSTOP_ACTION TSTATE_TASK_STOPPED, /* BLOCKED - Waiting for SIGCONT */ #endif NUM_TASK_STATES /* Must be last */ }; typedef enum tstate_e tstate_t; /* The following definitions are determined by tstate_t. Ordering of values * in the enumeration is important! */ #define FIRST_READY_TO_RUN_STATE TSTATE_TASK_READYTORUN #define LAST_READY_TO_RUN_STATE TSTATE_TASK_RUNNING #define FIRST_ASSIGNED_STATE TSTATE_TASK_ASSIGNED #define LAST_ASSIGNED_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 /* struct sporadic_s ************************************************************/ #ifdef CONFIG_SCHED_SPORADIC /* This structure represents one replenishment interval. This is what is * received by each timeout handler. */ struct sporadic_s; struct replenishment_s { FAR struct tcb_s *tcb; /* The parent TCB structure */ struct wdog_s timer; /* Timer dedicated to this interval */ uint32_t budget; /* Current budget time */ uint8_t flags; /* See SPORADIC_FLAG_* definitions */ }; /* This structure is an allocated "plug-in" to the main TCB structure. It is * allocated when the sporadic scheduling policy is assigned to a thread. Thus, * in the context of numerous threads of varying policies, there the overhead * from this significant allocation is only borne by the threads with the * sporadic scheduling policy. */ struct sporadic_s { bool suspended; /* Thread is currently suspended */ uint8_t hi_priority; /* Sporadic high priority */ uint8_t low_priority; /* Sporadic low priority */ uint8_t max_repl; /* Maximum number of replenishments */ uint8_t nrepls; /* Number of active replenishments */ uint32_t repl_period; /* Sporadic replenishment period */ uint32_t budget; /* Sporadic execution budget period */ clock_t eventtime; /* Time thread suspended or [re-]started */ /* This is the last interval timer activated */ FAR struct replenishment_s *active; /* This is the list of replenishment interval timers */ struct replenishment_s replenishments[CONFIG_SCHED_SPORADIC_MAXREPL]; }; #endif /* CONFIG_SCHED_SPORADIC */ /* struct child_status_s ********************************************************/ /* This structure is used to maintain 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_* defns */ pid_t ch_pid; /* Child task ID */ int ch_status; /* Child exit status */ }; #endif /* struct pthread_cleanup_s *****************************************************/ /* This structure describes one element of the pthread cleanup stack */ #ifdef CONFIG_PTHREAD_CLEANUP struct pthread_cleanup_s { pthread_cleanup_t pc_cleaner; /* Cleanup callback address */ FAR void *pc_arg; /* Argument that accompanies the callback */ }; #endif /* type tls_ndxset_t ************************************************************/ /* Smallest addressable type that can hold the entire configured number of TLS * data indexes. */ #if CONFIG_TLS_NELEM > 0 # if CONFIG_TLS_NELEM > 32 # error Too many TLS elements # elif CONFIG_TLS_NELEM > 16 typedef uint32_t tls_ndxset_t; # elif CONFIG_TLS_NELEM > 8 typedef uint16_t tls_ndxset_t; # else typedef uint8_t tls_ndxset_t; # endif #endif /* type grpid_t *****************************************************************/ /* The task group ID */ typedef int16_t grpid_t; /* 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 kmm_malloc(), or it may be virtual address associated * with an address environment (if CONFIG_ARCH_ADDRENV=y). */ FAR uint8_t *region; }; #endif /* struct stackinfo_s ***********************************************************/ /* Used to report stack information */ struct stackinfo_s { 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 */ /* Needed to deallocate stack */ FAR void *adj_stack_ptr; /* Adjusted stack_alloc_ptr for HW */ /* The initial stack pointer value */ }; /* struct exitinfo_s ************************************************************/ struct exitinfo_s { union { #ifdef CONFIG_SCHED_ATEXIT atexitfunc_t at; #endif #ifdef CONFIG_SCHED_ONEXIT onexitfunc_t on; #endif } func; #ifdef CONFIG_SCHED_ONEXIT FAR void *arg; #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 * structure referenced by the TCB of each thread that is a member of the task * group. * * This structure should contain *all* resources shared by tasks and threads that * belong to the same task group: * * Child exit status * Environment variables * PIC data space and address environments * File descriptors * FILE streams * Sockets * Address environments. * * Each instance of struct task_group_s is reference counted. Each instance is * created with a reference count of one. The reference incremented when each * thread joins the group and decremented when each thread exits, leaving the * group. When the reference count decrements to zero, the struct task_group_s * is free. */ #ifndef CONFIG_DISABLE_PTHREAD struct join_s; /* Forward reference */ /* Defined in sched/pthread/pthread.h */ #endif #ifdef CONFIG_BINFMT_LOADABLE struct binary_s; /* Forward reference */ /* Defined in include/nuttx/binfmt/binfmt.h */ #endif struct task_group_s { #if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) struct task_group_s *flink; /* Supports a singly linked list */ grpid_t tg_grpid; /* The ID of this task group */ #endif #ifdef HAVE_GROUP_MEMBERS grpid_t tg_pgrpid; /* 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 */ /* User identity **************************************************************/ #ifdef CONFIG_SCHED_USER_IDENTITY uid_t tg_uid; /* User identity */ gid_t tg_gid; /* User group identity */ #endif /* 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 /* [at|on]exit support ********************************************************/ #ifdef CONFIG_SCHED_EXIT_MAX struct exitinfo_s tg_exit[CONFIG_SCHED_EXIT_MAX]; #endif #ifdef CONFIG_BINFMT_LOADABLE /* Loadable module support ****************************************************/ FAR struct binary_s *tg_bininfo; /* Describes resources used by program */ #endif #ifdef CONFIG_SCHED_HAVE_PARENT /* Child exit status **********************************************************/ #ifdef CONFIG_SCHED_CHILD_STATUS FAR struct child_status_s *tg_children; /* Head of a list of child status */ #endif #ifndef HAVE_GROUP_MEMBERS /* REVISIT: What if parent thread exits? Should use tg_pgrpid. */ pid_t tg_ppid; /* This is the ID of the parent thread */ #ifndef CONFIG_SCHED_CHILD_STATUS uint16_t tg_nchildren; /* This is the number active children */ #endif #endif /* HAVE_GROUP_MEMBERS */ #endif /* CONFIG_SCHED_HAVE_PARENT */ #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) /* waitpid support ************************************************************/ /* Simple mechanism used only when there is no support for SIGCHLD */ uint8_t tg_nwaiters; /* Number of waiters */ uint8_t tg_waitflags; /* User flags for waitpid behavior */ sem_t tg_exitsem; /* Support for waitpid */ FAR int *tg_statloc; /* Location to return exit status */ #endif #ifndef CONFIG_DISABLE_PTHREAD /* Pthreads *******************************************************************/ /* 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 */ #endif /* Thread local storage *******************************************************/ #if CONFIG_TLS_NELEM > 0 tls_ndxset_t tg_tlsset; /* Set of TLS data indexes allocated */ #endif /* POSIX Signal Control Fields ************************************************/ sq_queue_t tg_sigactionq; /* List of actions for signals */ sq_queue_t tg_sigpendingq; /* List of pending signals */ #ifdef CONFIG_SIG_DEFAULT sigset_t tg_sigdefault; /* Set of signals set to the default action */ #endif #ifndef CONFIG_DISABLE_ENVIRON /* Environment variables ******************************************************/ size_t tg_envsize; /* Size of environment string allocation */ FAR char *tg_envp; /* Allocated environment strings */ #endif #ifndef CONFIG_DISABLE_POSIX_TIMERS /* Interval timer *************************************************************/ timer_t itimer; #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 ***********************************************************/ struct filelist tg_filelist; /* Maps file descriptor to file */ #if CONFIG_NFILE_STREAMS > 0 /* 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. */ #ifdef CONFIG_MM_KERNEL_HEAP FAR struct streamlist *tg_streamlist; #else struct streamlist tg_streamlist; /* Holds C buffered I/O info */ #endif #endif #ifdef CONFIG_NET /* Sockets ********************************************************************/ struct socketlist tg_socketlist; /* Maps socket descriptor to socket */ #endif #ifndef CONFIG_DISABLE_MQUEUE /* POSIX Named Message Queue Fields *******************************************/ sq_queue_t tg_msgdesq; /* List of opened message queues */ #endif #ifdef CONFIG_ARCH_ADDRENV /* Address Environment ********************************************************/ group_addrenv_t tg_addrenv; /* Task group address environment */ #endif #ifdef CONFIG_MM_SHM /* Shared Memory **************************************************************/ struct group_shm_s tg_shm; /* Task shared memory logic */ #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. */ struct tcb_s { /* Fields used to support list management *************************************/ FAR struct tcb_s *flink; /* Doubly linked list */ FAR struct tcb_s *blink; /* Task Group *****************************************************************/ FAR struct task_group_s *group; /* Pointer to shared task group data */ /* Task Management Fields *****************************************************/ pid_t pid; /* This is the ID of the thread */ start_t start; /* Thread start function */ entry_t entry; /* Entry Point into the thread */ uint8_t sched_priority; /* Current priority of the thread */ uint8_t init_priority; /* Initial 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 */ #ifdef CONFIG_SMP uint8_t cpu; /* CPU index if running or assigned */ cpu_set_t affinity; /* Bit set of permitted CPUs */ #endif uint16_t flags; /* Misc. general status flags */ int16_t lockcount; /* 0=preemptible (not-locked) */ #ifdef CONFIG_IRQCOUNT int16_t irqcount; /* 0=Not in critical section */ #endif #ifdef CONFIG_CANCELLATION_POINTS int16_t cpcount; /* Nested cancellation point count */ #endif int16_t errcode; /* Used to pass error information */ #if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC) int32_t timeslice; /* RR timeslice OR Sporadic budget */ /* interval remaining */ #endif #ifdef CONFIG_SCHED_SPORADIC FAR struct sporadic_s *sporadic; /* Sporadic scheduling parameters */ #endif struct wdog_s waitdog; /* All timed waits use this timer */ /* Stack-Related Fields *******************************************************/ 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 */ /* Needed to deallocate stack */ FAR void *adj_stack_ptr; /* Adjusted stack_alloc_ptr for HW */ /* The initial stack pointer value */ /* 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 ************************************************/ sigset_t sigprocmask; /* Signals that are blocked */ sigset_t sigwaitmask; /* Waiting for pending 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 */ /* POSIX Named Message Queue Fields *******************************************/ #ifndef CONFIG_DISABLE_MQUEUE FAR struct mqueue_inode_s *msgwaitq; /* Waiting for this message queue */ #endif /* Robust mutex support *******************************************************/ #if !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_PTHREAD_MUTEX_UNSAFE) FAR struct pthread_mutex_s *mhead; /* List of mutexes held by thread */ #endif /* Clean-up stack *************************************************************/ #ifdef CONFIG_PTHREAD_CLEANUP /* tos - The index to the next available entry at the top of the stack. * stack - The pre-allocated clean-up stack memory. */ uint8_t tos; struct pthread_cleanup_s stack[CONFIG_PTHREAD_CLEANUP_STACKSIZE]; #endif /* Pre-emption monitor support ************************************************/ #ifdef CONFIG_SCHED_CRITMONITOR uint32_t premp_start; /* Time when preemption disabled */ uint32_t premp_max; /* Max time preemption disabled */ uint32_t crit_start; /* Time critical section entered */ uint32_t crit_max; /* Max time in critical section */ #endif /* State save areas ***********************************************************/ /* The form and content of these fields are platform-specific. */ struct xcptcontext xcp; /* Interrupt register save area */ #if CONFIG_TASK_NAME_SIZE > 0 char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NUL terminator) */ #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 /* [Re-]start name + start-up parameters **************************************/ FAR char **argv; /* Name+start-up parameters */ }; /* 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 */ }; #endif /* !CONFIG_DISABLE_PTHREAD */ /* This is the callback type used by nxsched_foreach() */ typedef CODE void (*nxsched_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 #ifdef CONFIG_SCHED_CRITMONITOR /* Maximum time with pre-emption disabled or within critical section. */ #ifdef CONFIG_SMP_NCPUS EXTERN uint32_t g_premp_max[CONFIG_SMP_NCPUS]; EXTERN uint32_t g_crit_max[CONFIG_SMP_NCPUS]; #else EXTERN uint32_t g_premp_max[1]; EXTERN uint32_t g_crit_max[1]; #endif #endif /* CONFIG_SCHED_CRITMONITOR */ /******************************************************************************** * Public Function Prototypes ********************************************************************************/ /******************************************************************************** * Name: nxsched_self * * Description: * Return the current threads TCB. Basically, this function just wraps the * head of the ready-to-run list and manages access to the TCB from outside * of the sched/ sub-directory. * ********************************************************************************/ FAR struct tcb_s *nxsched_self(void); /******************************************************************************** * Name: nxsched_foreach * * Description: * Enumerate over each task and provide the TCB of each task to a user * callback functions. * * NOTE: This function examines the TCB and calls each handler within a * critical section. However, that critical section is released and * reacquired for each TCB. When it is released, there may be changes in * tasking. If the caller requires absolute stability through the * traversal, then the caller should establish the critical section BEFORE * calling this function. * * Input Parameters: * handler - The function to be called with the TCB of * each task * * Returned Value: * None * ********************************************************************************/ void nxsched_foreach(nxsched_foreach_t handler, FAR void *arg); /******************************************************************************** * Name: nxsched_get_tcb * * Description: * Given a task ID, this function will return the a pointer to the * corresponding TCB (or NULL if there is no such task ID). * * NOTE: This function holds a critical section while examining TCB data * data structures but releases that critical section before returning. * When it is released, the TCB may become unstable. If the caller * requires absolute stability while using the TCB, then the caller * should establish the critical section BEFORE calling this function and * hold that critical section as long as necessary. * ********************************************************************************/ FAR struct tcb_s *nxsched_get_tcb(pid_t pid); /******************************************************************************** * Name: nxsched_releasepid * * Description: * When a task is destroyed, this function must be called to make its * process ID available for re-use. * ********************************************************************************/ int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype); /* File system helpers **********************************************************/ /* These functions all extract lists from the group structure associated with the * currently executing task. */ FAR struct filelist *nxsched_get_files(void); #if CONFIG_NFILE_STREAMS > 0 FAR struct streamlist *nxsched_get_streams(void); #endif /* CONFIG_NFILE_STREAMS */ #ifdef CONFIG_NET FAR struct socketlist *nxsched_get_sockets(void); #endif /******************************************************************************** * Name: nxtask_init * * Description: * This function initializes a Task Control Block (TCB) in preparation for * starting a new thread. It performs a subset of the functionality of * task_create() * * Unlike task_create(): * 1. Allocate the TCB. The pre-allocated TCB is passed in argv. * 2. Allocate the stack. The pre-allocated stack is passed in argv. * 3. Activate the task. This must be done by calling nxtask_activate(). * * Certain fields of the pre-allocated TCB may be set to change the * nature of the created task. For example: * * - Task type may be set in the TCB flags to create kernel thread * * Input Parameters: * tcb - Address of the new task's TCB * name - Name of the new task (not used) * priority - Priority of the new task * stack - Start of the pre-allocated stack * stack_size - Size (in bytes) of the stack allocated * entry - Application start point of the new task * argv - A pointer to an array of input parameters. The array * should be terminated with a NULL argv[] value. If no * parameters are required, argv may be NULL. * * Returned Value: * OK on success; negative error value on failure appropriately. (See * nxtask_setup_scheduler() for possible failure conditions). On failure, * the caller is responsible for freeing the stack memory and for calling * nxsched_release_tcb() to free the TCB (which could be in most any * state). * ********************************************************************************/ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, FAR void *stack, uint32_t stack_size, main_t entry, FAR char * const argv[]); /******************************************************************************** * Name: nxtask_uninit * * Description: * Undo all operations on a TCB performed by task_init() and release the * TCB by calling kmm_free(). This is intended primarily to support * error recovery operations after a successful call to task_init() such * was when a subsequent call to task_activate fails. * * Caution: Freeing of the TCB itself might be an unexpected side-effect. * * Input Parameters: * tcb - Address of the TCB initialized by task_init() * * Returned Value: * OK on success; negative error value on failure appropriately. * ********************************************************************************/ void nxtask_uninit(FAR struct task_tcb_s *tcb); /******************************************************************************** * Name: nxtask_activate * * Description: * This function activates tasks initialized by nxtask_setup_scheduler(). * Without activation, a task is ineligible for execution by the * scheduler. * * Input Parameters: * tcb - The TCB for the task for the task (same as the nxtask_init * argument). * * Returned Value: * None * ********************************************************************************/ void nxtask_activate(FAR struct tcb_s *tcb); /******************************************************************************** * Name: nxtask_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. * * Input Parameters: * 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. * * Returned Value: * None * ********************************************************************************/ #ifdef CONFIG_SCHED_STARTHOOK void nxtask_starthook(FAR struct task_tcb_s *tcb, starthook_t starthook, FAR void *arg); #endif /******************************************************************************** * Name: nxtask_startup * * Description: * This function is the user-space, task startup function. It is called * from up_task_start() in user-mode. * * Input Parameters: * entrypt - The user-space address of the task entry point * argc and argv - Standard arguments for the task entry point * * Returned Value: * None. This function does not return. * ********************************************************************************/ #ifndef CONFIG_BUILD_KERNEL void nxtask_startup(main_t entrypt, int argc, FAR char *argv[]); #endif /******************************************************************************** * Internal vfork support. The overall sequence is: * * 1) User code calls vfork(). vfork() is provided in architecture-specific * code. * 2) vfork()and calls nxtask_setup_vfork(). * 3) nxtask_setup_vfork() 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 input 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 nxtask_start_vfork() * 6) nxtask_start_vfork() then executes the child thread. * * nxtask_abort_vfork() may be called if an error occurs between steps 3 and 6. * ********************************************************************************/ FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr, size_t *argsize); pid_t nxtask_start_vfork(FAR struct task_tcb_s *child); void nxtask_abort_vfork(FAR struct task_tcb_s *child, int errcode); /******************************************************************************** * Name: group_exitinfo * * Description: * This function may be called to when a task is loaded into memory. It * will setup the to automatically unload the module when the task exits. * * Input Parameters: * pid - The task ID of the newly loaded task * bininfo - This structure allocated with kmm_malloc(). This memory * persists until the task exits and will be used unloads * the module from memory. * * Returned Value: * This is a NuttX internal function so it follows the convention that * 0 (OK) is returned on success and a negated errno is returned on * failure. * ********************************************************************************/ #ifdef CONFIG_BINFMT_LOADABLE struct binary_s; /* Forward reference */ int group_exitinfo(pid_t pid, FAR struct binary_s *bininfo); #endif /******************************************************************************** * Name: nxsched_resume_scheduler * * Description: * Called by architecture specific implementations that block task execution. * This function prepares the scheduler for the thread that is about to be * restarted. * * Input Parameters: * tcb - The TCB of the thread to be restarted. * * Returned Value: * None * ********************************************************************************/ #if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_RESUMESCHEDULER) void nxsched_resume_scheduler(FAR struct tcb_s *tcb); #else # define nxsched_resume_scheduler(tcb) #endif /******************************************************************************** * Name: nxsched_suspend_scheduler * * Description: * Called by architecture specific implementations to resume task execution. * This function performs scheduler operations for the thread that is about to * be suspended. * * Input Parameters: * tcb - The TCB of the thread to be restarted. * * Returned Value: * None * ********************************************************************************/ #ifdef CONFIG_SCHED_SUSPENDSCHEDULER void nxsched_suspend_scheduler(FAR struct tcb_s *tcb); #else # define nxsched_suspend_scheduler(tcb) #endif /******************************************************************************** * Name: nxsched_get_param * * Description: * This function gets the scheduling priority of the task specified by * pid. It is identical in function, differing only in its return value: * This function does not modify the errno variable. * * This is a non-standard, internal OS function and is not intended for * use by application logic. Applications should use the standard * sched_getparam(). * * Input Parameters: * pid - the task ID of the task. If pid is zero, the priority * of the calling task is returned. * param - A structure whose member sched_priority is the integer * priority. The task's priority is copied to the sched_priority * element of this structure. * * Returned Value: * 0 (OK) if successful, otherwise a negated errno value is returned to * indicate the nature of the failure.. * * This function can fail if param is null (EINVAL) or if pid does * not correspond to any task (ESRCH). * ********************************************************************************/ struct sched_param; /* Forward reference */ int nxsched_get_param (pid_t pid, FAR struct sched_param *param); /******************************************************************************** * Name: nxsched_set_param * * Description: * This function sets the priority of a specified task. It is identical * to the function sched_setparam(), differing only in its return value: * This function does not modify the errno variable. * * NOTE: Setting a task's priority to the same value has a similar effect * to sched_yield() -- The task will be moved to after all other tasks * with the same priority. * * This is a non-standard, internal OS function and is not intended for * use by application logic. Applications should use the standard * sched_setparam(). * * Input Parameters: * pid - the task ID of the task to reprioritize. If pid is zero, the * priority of the calling task is changed. * param - A structure whose member sched_priority is the integer priority. * The range of valid priority numbers is from SCHED_PRIORITY_MIN * through SCHED_PRIORITY_MAX. * * Returned Value: * 0 (OK) if successful, otherwise a negated errno value is returned to * indicate the nature of the failure.. * * EINVAL The parameter 'param' is invalid or does not make sense for the * current scheduling policy. * EPERM The calling task does not have appropriate privileges. * ESRCH The task whose ID is pid could not be found. * ********************************************************************************/ struct sched_param; /* Forward reference */ int nxsched_set_param(pid_t pid, FAR const struct sched_param *param); /******************************************************************************** * Name: nxsched_get_scheduler * * Description: * sched_getscheduler() returns the scheduling policy currently * applied to the task identified by pid. If pid equals zero, the * policy of the calling task will be retrieved. * * This functions is identical to the function sched_getscheduler(), * differing only in its return value: This function does not modify * the errno variable. * * This is a non-standard, internal OS function and is not intended for * use by application logic. Applications should use the standard * sched_getscheduler(). * * Input Parameters: * pid - the task ID of the task to query. If pid is zero, the * calling task is queried. * * Returned Value: * On success, sched_getscheduler() returns the policy for the task * (either SCHED_FIFO or SCHED_RR). On error, a negated errno value * returned: * * ESRCH The task whose ID is pid could not be found. * ********************************************************************************/ int nxsched_get_scheduler(pid_t pid); /******************************************************************************** * Name: nxsched_set_scheduler * * Description: * nxsched_set_scheduler() sets both the scheduling policy and the priority * for the task identified by pid. If pid equals zero, the scheduler of * the calling task will be set. The parameter 'param' holds the priority * of the thread under the new policy. * * nxsched_set_scheduler() is identical to the function sched_getparam(), * differing only in its return value: This function does not modify the * errno variable. * * This is a non-standard, internal OS function and is not intended for * use by application logic. Applications should use the standard * sched_getparam(). * * Input Parameters: * pid - the task ID of the task to modify. If pid is zero, the calling * task is modified. * policy - Scheduling policy requested (either SCHED_FIFO or SCHED_RR) * param - A structure whose member sched_priority is the new priority. * The range of valid priority numbers is from SCHED_PRIORITY_MIN * through SCHED_PRIORITY_MAX. * * Returned Value: * On success, nxsched_set_scheduler() returns OK (zero). On error, a * negated errno value is returned: * * EINVAL The scheduling policy is not one of the recognized policies. * ESRCH The task whose ID is pid could not be found. * ********************************************************************************/ int nxsched_set_scheduler(pid_t pid, int policy, FAR const struct sched_param *param); /******************************************************************************** * Name: nxsched_get_affinity * * Description: * nxsched_get_affinity() writes the affinity mask of the thread whose ID * is pid into the cpu_set_t pointed to by mask. The cpusetsize * argument specifies the size (in bytes) of mask. If pid is zero, then * the mask of the calling thread is returned. * * nxsched_get_affinity() is identical to the function sched_getaffinity(), * differing only in its return value: This function does not modify the * errno variable. * * This is a non-standard, internal OS function and is not intended for * use by application logic. Applications should use the standard * sched_getparam(). * * Input Parameters: * pid - The ID of thread whose affinity set will be retrieved. * cpusetsize - Size of mask. MUST be sizeofcpu_set_t(). * mask - The location to return the thread's new affinity set. * * Returned Value: * Zero (OK) if successful. Otherwise, a negated errno value is returned: * * ESRCH The task whose ID is pid could not be found. * ********************************************************************************/ #ifdef CONFIG_SMP int nxsched_get_affinity(pid_t pid, size_t cpusetsize, FAR cpu_set_t *mask); #endif /******************************************************************************** * Name: nxsched_set_affinity * * Description: * sched_setaffinity() sets the CPU affinity mask of the thread whose ID * is pid to the value specified by mask. If pid is zero, then the * calling thread is used. The argument cpusetsize is the length (i * bytes) of the data pointed to by mask. Normally this argument would * be specified as sizeof(cpu_set_t). * * If the thread specified by pid is not currently running on one of the * CPUs specified in mask, then that thread is migrated to one of the * CPUs specified in mask. * * nxsched_set_affinity() is identical to the function sched_setparam(), * differing only in its return value: This function does not modify * the errno variable. This is a non-standard, internal OS function and * is not intended for use by application logic. Applications should * use the standard sched_setparam(). * * Input Parameters: * pid - The ID of thread whose affinity set will be modified. * cpusetsize - Size of mask. MUST be sizeofcpu_set_t(). * mask - The location to return the thread's new affinity set. * * Returned Value: * Zero (OK) if successful. Otherwise, a negated errno value is returned: * * ESRCH The task whose ID is pid could not be found. * ********************************************************************************/ #ifdef CONFIG_SMP int nxsched_set_affinity(pid_t pid, size_t cpusetsize, FAR const cpu_set_t *mask); #endif /******************************************************************************** * Name: nxsched_get_stackinfo * * Description: * Report information about a thread's stack allocation. * * Input Parameters: * pid - Identifies the thread to query. Zero is interpreted as the * the calling thread * stackinfo - User-provided location to return the stack information. * * Returned Value: * Zero (OK) if successful. Otherwise, a negated errno value is returned. * * -ENOENT Returned if pid does not refer to an active task * -EACCES The calling thread does not have privileges to access the * stack of the thread associated with the pid. * ********************************************************************************/ int nxsched_get_stackinfo(pid_t pid, FAR struct stackinfo_s *stackinfo); /******************************************************************************** * Name: nx_wait/nx_waitid/nx_waitpid ********************************************************************************/ #ifdef CONFIG_SCHED_WAITPID pid_t nx_wait(FAR int *stat_loc); int nx_waitid(int idtype, id_t id, FAR siginfo_t *info, int options); pid_t nx_waitpid(pid_t pid, FAR int *stat_loc, int options); #endif #undef EXTERN #if defined(__cplusplus) } #endif #endif /* __ASSEMBLY__ */ #endif /* __INCLUDE_NUTTX_SCHED_H */