text: /****************************************************************************
   * 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 <nuttx/config.h>
  
  #include <sys/types.h>
  #include <stdint.h>
  #include <queue.h>
  #include <sched.h>
  #include <signal.h>
  #include <semaphore.h>
  #include <time.h>
  
  #include <nuttx/clock.h>
  #include <nuttx/irq.h>
  #include <nuttx/tls.h>
  #include <nuttx/wdog.h>
  #include <nuttx/mm/shm.h>
  #include <nuttx/fs/fs.h>
  #include <nuttx/net/net.h>
  
  #include <arch/arch.h>
  
  /****************************************************************************
   * 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 IDLE_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 << 8)                      /* Bit 7: Locked to this CPU */
  #define TCB_FLAG_SIGNAL_ACTION     (1 << 9)                      /* Bit 8: In a signal handler */
  #define TCB_FLAG_SYSCALL           (1 << 10)                     /* Bit 9: In a system call */
  #define TCB_FLAG_EXIT_PROCESSING   (1 << 11)                     /* Bit 10: Exitting */
  #define TCB_FLAG_FREE_STACK        (1 << 12)                     /* Bit 12: Free stack after exit */
  #define TCB_FLAG_MEM_CHECK         (1 << 13)                     /* Bit 13: Memory check */
                                                                   /* Bits 14-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
  
  #ifdef CONFIG_DEBUG_TCBINFO
  #  define TCB_PID_OFF                offsetof(struct tcb_s, pid)
  #  define TCB_STATE_OFF              offsetof(struct tcb_s, task_state)
  #  define TCB_PRI_OFF                offsetof(struct tcb_s, sched_priority)
  #if CONFIG_TASK_NAME_SIZE > 0
  #  define TCB_NAME_OFF               offsetof(struct tcb_s, name)
  #else
  #  define TCB_NAME_OFF               0
  #endif
  #  define TCB_REGS_OFF               offsetof(struct tcb_s, xcp.regs)
  #  define TCB_REG_OFF(reg)           (reg * sizeof(uint32_t))
  #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 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 *stack_base_ptr;              /* Adjusted initial stack pointer      */
                                           /* after the frame has been removed    */
                                           /* from the stack.                     */
  };
  
  /* 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            */
  #endif
    pid_t tg_pid;                     /* The ID of the task within the group      */
    pid_t tg_ppid;                    /* This is the ID of the parent thread      */
    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     */
  #else
    uint16_t tg_nchildren;                  /* This is the number active children */
  #endif
  #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 ***************************************************/
  
    FAR struct task_info_s *tg_info;
  
    /* 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         */
  
  #ifdef CONFIG_FILE_STREAM
    /* 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_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    */
    uint8_t  sched_priority;               /* Current priority of the thread  */
    uint8_t  init_priority;                /* Initial priority of the thread  */
  
    start_t  start;                        /* Thread start function           */
    entry_t  entry;                        /* Entry Point into the thread     */
  
    uint8_t  task_state;                   /* Current state 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 */
    FAR struct semholder_s *holdsem;       /* List of held semaphores         */
  #endif
  
  #ifdef CONFIG_SMP
    uint8_t  cpu;                          /* CPU index if running/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 *stack_base_ptr;              /* Adjusted initial stack pointer  */
                                           /* after the frame has been        */
                                           /* removed from the stack.         */
  
    /* 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
  
    /* CPU load monitoring support ********************************************/
  
  #ifdef CONFIG_SCHED_CPULOAD
    uint32_t ticks;                        /* Number of ticks on this thread */
  #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        */
    uint32_t run_start;                    /* Time when thread begin run          */
    uint32_t run_max;                      /* Max time thread run                 */
  #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
  };
  
  /* 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_trampoline_t trampoline;       /* User-space pthread startup function */
    pthread_addr_t arg;                    /* Startup argument                    */
    FAR void *joininfo;                    /* Detach-able info to support join    */
  };
  #endif /* !CONFIG_DISABLE_PTHREAD */
  
  /* struct tcbinfo_s *********************************************************/
  
  /* The structure save key filed offset of tcb_s while can be used by
   * debuggers to parse the tcb information
   */
  
  #ifdef CONFIG_DEBUG_TCBINFO
  begin_packed_struct struct tcbinfo_s
  {
    uint16_t pid_off;                      /* Offset of tcb.pid               */
    uint16_t state_off;                    /* Offset of tcb.task_state        */
    uint16_t pri_off;                      /* Offset of tcb.sched_priority    */
    uint16_t name_off;                     /* Offset of tcb.name              */
    uint16_t regs_off;                     /* Offset of tcb.regs              */
    uint16_t basic_num;                    /* Num of genernal regs            */
    uint16_t total_num;                    /* Num of regs in tcbinfo.reg_offs */
  
    /* Offset pointer of xcp.regs, order in GDB org.gnu.gdb.xxx feature.
     * Please refer:
     * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html
     * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features
     * -.html
     * value UINT16_MAX: This regsiter was not priovided by NuttX
     */
  
    begin_packed_struct
    union
    {
      uint8_t             u[8];
      FAR const uint16_t *p;
    }
    end_packed_struct reg_off;
  } end_packed_struct;
  #endif
  
  /* 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. */
  
  EXTERN uint32_t g_premp_max[CONFIG_SMP_NCPUS];
  EXTERN uint32_t g_crit_max[CONFIG_SMP_NCPUS];
  #endif /* CONFIG_SCHED_CRITMONITOR */
  
  #ifdef CONFIG_DEBUG_TCBINFO
  EXTERN const struct tcbinfo_s g_tcbinfo;
  #endif
  
  /****************************************************************************
   * 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);
  #ifdef CONFIG_FILE_STREAM
  FAR struct streamlist *nxsched_get_streams(void);
  #endif /* CONFIG_FILE_STREAM */
  
  /****************************************************************************
   * 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
   *    - Allocate and initialize the stack
   *    - 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:
   *    - 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);
  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, -1 is interpreted as the calling task.
   *   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 */
  