summaryrefslogblamecommitdiff
path: root/nuttx/sched/init/os_start.c
blob: f48bea318f503da641c8514c4db98fc4fd07a306 (plain) (tree)
1
2
3
4
5
                                                                             
                        
  
                                                               
                                           










                                                                       
                                                                     















                                                                        
                                                                              
 
                                                                             
                 
                                                                              
 
                       
                     
                    

                    


                            
                        
                         
                           
                       
                         
                          
                           
                        
 
                         
                           
                       
                                 
                             
                           
      
                              
                             
      
                         
                         
                     
                      
                         
      
                       
 
                                                                             
                            
                                                                              
 
                                                                             
                            
                                                                              
 
                                                                             
                   
                                                                              
 
                                                                              




                                                                             


                      


                                                                         

   
                                 
 



                                                                            

   
                                   


                                                                            
                                          


                                                                         
                              
                                       
      




                                                                       
                             
                                           
      




                                                                       
                             
                                          
      
 





                                                                             



                                                                     
                                    
 



                                                                         

   

                                     

                                                                          

                                    


                                                                 
                         

                                                   
  



                                                            

                                           

   
                                             







                                                            
                                                          
 




                                                                   
                                                            
                              

                                                           

                             
   

                                                                   
      
                    
   

                                                                 

  
                                                                             
                    
                                                                              

                                                                           

                                                                             

   
                                       
 

                                       
                                                 
 

                                               
                               
 
                                                                             
                              
                                                                              
 
                                                                             
                   
                                                                              
 
                                                                             



                                                                            







                                                                            
  
                                                                              


                   

        
                    
 
                                                                              




                                  
                              
                               

                             

                                   
      


                             
                            
                             

                                                                          

                            



                                                               
                                        






                                                      

                                             
 
                                                                              






                                                                       


                                                      
                                                   
 

                              
                             
                                                                   









                                                                          
                             
                                      
     
                                          
                                  
                        
                              


                                                                         
                                                                           


                                                            
                                   
 
                                                                              

                                                                       

     
                   
 

                                     
   
                         
                     
 
                             



                                                                           
                                              
                                           
      
 
                            




                                                                             
                                          
      









                                                                           
   
 
                                                                           

                                          







                                

                                                                 
                                
                             
      



                       








                                                                  

                                                                     
                                
                               
      



                         
                                   
                                
                               
      
     
                         
     
      
 
                              

                                                   
                                
                             
      


                       
      
 
                             

                                                                
                                
                            
      


                      
      
 
                              

                                                                 
                                
                                 
      


                           
      
 
                                

                                                                     
                  
      
 
                 

                                     
                   

      







                                                                   





                                        

                                                                         

     
                   
 
                                                                              
                      


                                                               

      
                                                                  


                                                                  
 
                                                
      
 
                      



                                                                   
                                            
                                                       

      
                                                                              
                                                    
 
                            
 
                                                                              

                                                                 
                                

          


                                                                          
                                                                     
         





                                                                          





                                                                            

         
                                  

                                    
                              
         
      

                                                                



                
/****************************************************************************
 * sched/init/os_start.c
 *
 *   Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include  <sys/types.h>
#include  <stdbool.h>
#include  <string.h>
#include  <assert.h>
#include  <debug.h>

#include  <nuttx/arch.h>
#include  <nuttx/compiler.h>
#include <nuttx/sched.h>
#include  <nuttx/fs/fs.h>
#include  <nuttx/net/net.h>
#include  <nuttx/lib.h>
#include  <nuttx/mm/mm.h>
#include  <nuttx/mm/shm.h>
#include  <nuttx/kmalloc.h>
#include  <nuttx/init.h>

#include  "sched/sched.h"
#include  "signal/signal.h"
#include  "wdog/wdog.h"
#include  "semaphore/semaphore.h"
#ifndef CONFIG_DISABLE_MQUEUE
# include "mqueue/mqueue.h"
#endif
#ifndef CONFIG_DISABLE_PTHREAD
# include "pthread/pthread.h"
#endif
#include  "clock/clock.h"
#include  "timer/timer.h"
#include  "irq/irq.h"
#ifdef HAVE_TASK_GROUP
#include  "group/group.h"
#endif
#include  "init/init.h"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/****************************************************************************
 * Private Type Declarations
 ****************************************************************************/

/****************************************************************************
 * Global Variables
 ****************************************************************************/

/* Task Lists ***************************************************************/
/* The state of a task is indicated both by the task_state field of the TCB
 * and by a series of task lists.  All of these tasks lists are declared
 * below. Although it is not always necessary, most of these lists are
 * prioritized so that common list handling logic can be used (only the
 * g_readytorun, the g_pendingtasks, and the g_waitingforsemaphore lists need
 * to be prioritized).
 */

/* This is the list of all tasks that are ready to run.  The head of this
 * list is the currently active task; the tail of this list is always the
 * IDLE task.
 */

volatile dq_queue_t g_readytorun;

/* This is the list of all tasks that are ready-to-run, but cannot be placed
 * in the g_readytorun list because:  (1) They are higher priority than the
 * currently active task at the head of the g_readytorun list, and (2) the
 * currently active task has disabled pre-emption.
 */

volatile dq_queue_t g_pendingtasks;

/* This is the list of all tasks that are blocked waiting for a semaphore */

volatile dq_queue_t g_waitingforsemaphore;

/* This is the list of all tasks that are blocked waiting for a signal */

#ifndef CONFIG_DISABLE_SIGNALS
volatile dq_queue_t g_waitingforsignal;
#endif

/* This is the list of all tasks that are blocked waiting for a message
 * queue to become non-empty.
 */

#ifndef CONFIG_DISABLE_MQUEUE
volatile dq_queue_t g_waitingformqnotempty;
#endif

/* This is the list of all tasks that are blocked waiting for a message
 * queue to become non-full.
 */

#ifndef CONFIG_DISABLE_MQUEUE
volatile dq_queue_t g_waitingformqnotfull;
#endif

/* This is the list of all tasks that are blocking waiting for a page fill */

#ifdef CONFIG_PAGING
volatile dq_queue_t g_waitingforfill;
#endif

/* This the list of all tasks that have been initialized, but not yet
 * activated. NOTE:  This is the only list that is not prioritized.
 */

volatile dq_queue_t g_inactivetasks;

/* These are lists of dayed memory deallocations that need to be handled
 * within the IDLE loop or worker thread.  These deallocations get queued
 * by sched_kufree and sched_kfree() if the OS needs to deallocate memory
 * while it is within an interrupt handler.
 */

volatile sq_queue_t g_delayed_kufree;

#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
     defined(CONFIG_MM_KERNEL_HEAP)
volatile sq_queue_t g_delayed_kfree;
#endif

/* This is the value of the last process ID assigned to a task */

volatile pid_t g_lastpid;

/* The following hash table is used for two things:
 *
 * 1. This hash table greatly speeds the determination of
 *    a new unique process ID for a task, and
 * 2. Is used to quickly map a process ID into a TCB.
 * It has the side effects of using more memory and limiting
 *
 * the number of tasks to CONFIG_MAX_TASKS.
 */

struct pidhash_s g_pidhash[CONFIG_MAX_TASKS];

/* This is a table of task lists.  This table is indexed by
 * the task state enumeration type (tstate_t) and provides
 * a pointer to the associated static task list (if there
 * is one) as well as a boolean indication as to if the list
 * is an ordered list or not.
 */

const struct tasklist_s g_tasklisttable[NUM_TASK_STATES] =
{
  { NULL,                    false },  /* TSTATE_TASK_INVALID */
  { &g_pendingtasks,         true  },  /* TSTATE_TASK_PENDING */
  { &g_readytorun,           true  },  /* TSTATE_TASK_READYTORUN */
  { &g_readytorun,           true  },  /* TSTATE_TASK_RUNNING */
  { &g_inactivetasks,        false },  /* TSTATE_TASK_INACTIVE */
  { &g_waitingforsemaphore,  true  }   /* TSTATE_WAIT_SEM */
#ifndef CONFIG_DISABLE_SIGNALS
  ,
  { &g_waitingforsignal,     false }  /* TSTATE_WAIT_SIG */
#endif
#ifndef CONFIG_DISABLE_MQUEUE
  ,
  { &g_waitingformqnotempty, true  },  /* TSTATE_WAIT_MQNOTEMPTY */
  { &g_waitingformqnotfull,  true  }   /* TSTATE_WAIT_MQNOTFULL */
#endif
#ifdef CONFIG_PAGING
  ,
  { &g_waitingforfill,       true  }   /* TSTATE_WAIT_PAGEFILL */
#endif
};

/****************************************************************************
 * Private Variables
 ****************************************************************************/
/* This is the task control block for this thread of execution. This thread
 * of execution is the IDLE task.  NOTE:  the system boots into the IDLE
 * task.  The IDLE task spawns the user initialization task and that user
 * initialization task is responsible for bringing up the rest of the system.
 */

static FAR struct task_tcb_s g_idletcb;

/* This is the name of the idle task */

static FAR const char g_idlename[] = "Idle Task";

/* This the IDLE idle threads argument list. */

static FAR char *g_idleargv[2];

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/****************************************************************************
 * Public Functions
 ****************************************************************************/

/****************************************************************************
 * Name: os_start
 *
 * Description:
 *   This function is called to initialize the operating system and to spawn
 *   the user initialization thread of execution.  This is the initial entry
 *   point into NuttX
 *
 * Input Parameters:
 *   None
 *
 * Returned value:
 *   Does not return.
 *
 ****************************************************************************/

void os_start(void)
{
  int i;

  slldbg("Entry\n");

  /* Initialize RTOS Data ***************************************************/
  /* Initialize all task lists */

  dq_init(&g_readytorun);
  dq_init(&g_pendingtasks);
  dq_init(&g_waitingforsemaphore);
#ifndef CONFIG_DISABLE_SIGNALS
  dq_init(&g_waitingforsignal);
#endif
#ifndef CONFIG_DISABLE_MQUEUE
  dq_init(&g_waitingformqnotfull);
  dq_init(&g_waitingformqnotempty);
#endif
#ifdef CONFIG_PAGING
  dq_init(&g_waitingforfill);
#endif
  dq_init(&g_inactivetasks);
  sq_init(&g_delayed_kufree);
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
     defined(CONFIG_MM_KERNEL_HEAP)
  sq_init(&g_delayed_kfree);
#endif

  /* Initialize the logic that determine unique process IDs. */

  g_lastpid = 0;
  for (i = 0; i < CONFIG_MAX_TASKS; i++)
    {
      g_pidhash[i].tcb = NULL;
      g_pidhash[i].pid = INVALID_PROCESS_ID;
    }

  /* Assign the process ID of ZERO to the idle task */

  g_pidhash[PIDHASH(0)].tcb = &g_idletcb.cmn;
  g_pidhash[PIDHASH(0)].pid = 0;

  /* Initialize the IDLE task TCB *******************************************/
  /* Initialize a TCB for this thread of execution.  NOTE:  The default
   * value for most components of the g_idletcb are zero.  The entire
   * structure is set to zero.  Then only the (potentially) non-zero
   * elements are initialized. NOTE:  The idle task is the only task in
   * that has pid == 0 and sched_priority == 0.
   */

  bzero((void*)&g_idletcb, sizeof(struct task_tcb_s));
  g_idletcb.cmn.task_state = TSTATE_TASK_RUNNING;
  g_idletcb.cmn.entry.main = (main_t)os_start;
  g_idletcb.cmn.flags      = TCB_FLAG_TTYPE_KERNEL;

  /* Set the IDLE task name */

#if CONFIG_TASK_NAME_SIZE > 0
  strncpy(g_idletcb.cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE-1);
#endif /* CONFIG_TASK_NAME_SIZE */

  /* Configure the task name in the argument list.  The IDLE task does
   * not really have an argument list, but this name is still useful
   * for things like the NSH PS command.
   *
   * In the kernel mode build, the arguments are saved on the task's stack
   * and there is no support that yet.
   */

#if CONFIG_TASK_NAME_SIZE > 0
  g_idleargv[0]  = g_idletcb.cmn.name;
#else
  g_idleargv[0]  = (FAR char *)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
  g_idleargv[1]  = NULL;
  g_idletcb.argv = g_idleargv;

  /* Then add the idle task's TCB to the head of the ready to run list */

  dq_addfirst((FAR dq_entry_t*)&g_idletcb, (FAR dq_queue_t*)&g_readytorun);

  /* Initialize the processor-specific portion of the TCB */

  up_initial_state(&g_idletcb.cmn);

  /* Initialize RTOS facilities *********************************************/
  /* Initialize the semaphore facility.  This has to be done very early
   * because many subsystems depend upon fully functional semaphores.
   */

  sem_initialize();

  /* Initialize the memory manager */

  {
    FAR void *heap_start;
    size_t heap_size;

#ifdef MM_KERNEL_USRHEAP_INIT
    /* Get the user-mode heap from the platform specific code and configure
     * the user-mode memory allocator.
     */

    up_allocate_heap(&heap_start, &heap_size);
    kumm_initialize(heap_start, heap_size);
#endif

#ifdef CONFIG_MM_KERNEL_HEAP
    /* Get the kernel-mode heap from the platform specific code and configure
     * the kernel-mode memory allocator.
     */

    up_allocate_kheap(&heap_start, &heap_size);
    kmm_initialize(heap_start, heap_size);
#endif

#ifdef CONFIG_MM_PGALLOC
    /* If there is a page allocator in the configuration, then get the page
     * heap information from the platform-specific code and configure the
     * page allocator.
     */

    up_allocate_pgheap(&heap_start, &heap_size);
    mm_pginitialize(heap_start, heap_size);
#endif
  }

#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
  /* Initialize tasking data structures */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (task_initialize != NULL)
#endif
    {
      task_initialize();
    }
#endif

  /* Initialize the interrupt handling subsystem (if included) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (irq_initialize != NULL)
#endif
    {
      irq_initialize();
    }

  /* Initialize the watchdog facility (if included in the link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (wd_initialize != NULL)
#endif
    {
      wd_initialize();
    }

  /* Initialize the POSIX timer facility (if included in the link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (clock_initialize != NULL)
#endif
    {
      clock_initialize();
    }

#ifndef CONFIG_DISABLE_POSIX_TIMERS
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (timer_initialize != NULL)
#endif
    {
      timer_initialize();
    }
#endif

#ifndef CONFIG_DISABLE_SIGNALS
  /* Initialize the signal facility (if in link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (sig_initialize != NULL)
#endif
    {
      sig_initialize();
    }
#endif

#ifndef CONFIG_DISABLE_MQUEUE
  /* Initialize the named message queue facility (if in link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (mq_initialize != NULL)
#endif
    {
      mq_initialize();
    }
#endif

#ifndef CONFIG_DISABLE_PTHREAD
  /* Initialize the thread-specific data facility (if in link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (pthread_initialize != NULL)
#endif
    {
      pthread_initialize();
    }
#endif

#if CONFIG_NFILE_DESCRIPTORS > 0
  /* Initialize the file system (needed to support device drivers) */

  fs_initialize();
#endif

#ifdef CONFIG_NET
  /* Initialize the network system */

  net_initialize();
#endif

  /* The processor specific details of running the operating system
   * will be handled here.  Such things as setting up interrupt
   * service routines and starting the clock are some of the things
   * that are different for each  processor and hardware platform.
   */

  up_initialize();

#ifdef CONFIG_MM_SHM
  /* Initialize shared memory support */

  shm_initialize();
#endif

  /* Initialize the C libraries.  This is done last because the libraries
   * may depend on the above.
   */

  lib_initialize();

  /* IDLE Group Initialization **********************************************/
#ifdef HAVE_TASK_GROUP
  /* Allocate the IDLE group */

  DEBUGVERIFY(group_allocate(&g_idletcb, g_idletcb.cmn.flags));
#endif

#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
  /* Create stdout, stderr, stdin on the IDLE task.  These will be
   * inherited by all of the threads created by the IDLE task.
   */

  DEBUGVERIFY(group_setupidlefiles(&g_idletcb));
#endif

#ifdef HAVE_TASK_GROUP
  /* Complete initialization of the IDLE group.  Suppress retention
   * of child status in the IDLE group.
   */

  DEBUGVERIFY(group_initialize(&g_idletcb));
  g_idletcb.cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT;
#endif

  /* Bring Up the System ****************************************************/
  /* Create initial tasks and bring-up the system */

  DEBUGVERIFY(os_bringup());

  /* The IDLE Loop **********************************************************/
  /* When control is return to this point, the system is idle. */

  sdbg("Beginning Idle Loop\n");
  for (;;)
    {
      /* Perform garbage collection (if it is not being done by the worker
       * thread).  This cleans-up memory de-allocations that were queued
       * because they could not be freed in that execution context (for
       * example, if the memory was freed from an interrupt handler).
       */

#ifndef CONFIG_SCHED_WORKQUEUE
      /* We must have exclusive access to the memory manager to do this
       * BUT the idle task cannot wait on a semaphore.  So we only do
       * the cleanup now if we can get the semaphore -- this should be
       * possible because if the IDLE thread is running, no other task is!
       *
       * WARNING: This logic could have undesirable side-effects if priority
       * inheritance is enabled.  Imaginee the possible issues if the
       * priority of the IDLE thread were to get boosted!  Moral: If you
       * use priority inheritance, then you should also enable the work
       * queue so that is done in a safer context.
       */

      if (kmm_trysemaphore() == 0)
        {
          sched_garbagecollection();
          kmm_givesemaphore();
        }
#endif

      /* Perform any processor-specific idle state operations */

      up_idle();
    }
}