SMP: A few preliminary data structure definitions

This commit is contained in:
Gregory Nutt 2016-02-10 11:45:26 -06:00
parent f5a3b1e89d
commit 47a5663f8c
5 changed files with 141 additions and 17 deletions

2
arch

@ -1 +1 @@
Subproject commit 958e4d09fc413d88893881eee612d901b779e057
Subproject commit 0ddf09674eb2115ecfedaa82e21a2c43fc09d127

@ -1 +1 @@
Subproject commit 05856eb712badecadbdbd7803c868ebd0b2de451
Subproject commit 81a10b64ed544684bb975e218e09ab5bc8aaf445

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/arch.h
*
* Copyright (C) 2007-2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -1636,6 +1636,52 @@ int up_timer_cancel(FAR struct timespec *ts);
int up_timer_start(FAR const struct timespec *ts);
#endif
/****************************************************************************
* Multiple CPU support
****************************************************************************/
/****************************************************************************
* Name: up_testset
*
* Description:
* Perform and atomic test and set operation on the provided spinlock.
*
* Input Parameters:
* lock - The address of spinlock object.
*
* Returned Value:
* The spinlock is always locked upon return. The value of previous value
* of the spinlock variable is returned, either SP_LOCKED if the spinlock
* as previously locked (meaning that the test-and-set operation failed to
* obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked
* (meaning that we successfully obtained the lock)
*
****************************************************************************/
/* See prototype in include/nuttx/spinlock.h */
/****************************************************************************
* Name: up_cpundx
*
* Description:
* Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that
* corresponds to the currently executing CPU.
*
* Input Parameters:
* None
*
* Returned Value:
* An integer index in the range of 0 through (CONFIG_SMP_NCPUS-1) that
* corresponds to the currently executing CPU.
*
****************************************************************************/
#ifdef CONFIG_SMP
int up_cpundx(void);
#else
# define up_cpundx() (0)
#endif
/****************************************************************************
* Name: up_romgetc
*

View File

@ -81,17 +81,53 @@
* 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).
* 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.
/* This is the list of all tasks that are ready to run. This is a
* prioritized list with head of the list holding the highest priority
* (unassigned) task. In the non-SMP cae, the head of this list is the
* currently active task and the tail of this list, the lowest priority
* task, is always the IDLE task.
*/
volatile dq_queue_t g_readytorun;
#ifdef CONFIG_SMP
/* In order to support SMP, the function of the g_readytorun list changes,
* The g_readytorun is still used but in the SMP cae it will contain only:
*
* - Only tasks/threads that are eligible to run, but not currently running,
* and
* - Tasks/threads that have not been assigned to a CPU.
*
* Otherwise, the TCB will be reatined in an assigned task list,
* g_assignedtasks. As its name suggests, on 'g_assignedtasks queue for CPU
* 'n' would contain only tasks/threads that are assigned to CPU 'n'. Tasks/
* threads would be assigned a particular CPU by one of two mechanisms:
*
* - (Semi-)permanently through an RTOS interfaces such as
* pthread_attr_setaffinity(), or
* - Temporarily through scheduling logic when a previously unassigned task
* is made to run.
*
* Tasks/threads that are assigned to a CPU via an interface like
* pthread_attr_setaffinity() would never go into the g_readytorun list, but
* would only go into the g_assignedtasks[n] list for the CPU 'n' to which
* the thread has been assigned. Hence, the g_readytorun list would hold
* only unassigned tasks/threads.
*
* Like the g_readytorun list in in non-SMP case, each g_assignedtask[] list
* is prioritized: The head of the list is the currently active task on this
* CPU. Tasks after the active task are ready-to-run and assigned to this
* CPU. The tail of this assigned task list, the lowest priority task, is
* always the CPU's IDLE task.
*/
volatile dq_queue_t g_assignedtasks[CONFIG_SMP_NCPUS];
#endif
/* 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

View File

@ -1,7 +1,7 @@
/****************************************************************************
* sched/sched/sched.h
*
* Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -47,6 +47,7 @@
#include <queue.h>
#include <sched.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
/****************************************************************************
@ -68,9 +69,14 @@
* These macros are intended to support a future SMP implementation.
*/
#define current_task(cpu) ((FAR struct tcb_s *)g_readytorun.head)
#define this_cpu() (0)
#define this_task() (current_task(this_cpu))
#ifdef CONFIG_SMP
# define current_task(cpu) ((FAR struct tcb_s *)g_assignedtasks[cpu].head)
# define this_cpu() up_cpundx()
#else
# define current_task(cpu) ((FAR struct tcb_s *)g_readytorun.head)
# define this_cpu() (0)
#endif
#define this_task() (current_task(this_cpu()))
/****************************************************************************
* Public Type Definitions
@ -117,17 +123,53 @@ struct tasklist_s
* 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).
* 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.
/* This is the list of all tasks that are ready to run. This is a
* prioritized list with head of the list holding the highest priority
* (unassigned) task. In the non-SMP cae, the head of this list is the
* currently active task and the tail of this list, the lowest priority
* task, is always the IDLE task.
*/
extern volatile dq_queue_t g_readytorun;
#ifdef CONFIG_SMP
/* In order to support SMP, the function of the g_readytorun list changes,
* The g_readytorun is still used but in the SMP cae it will contain only:
*
* - Only tasks/threads that are eligible to run, but not currently running,
* and
* - Tasks/threads that have not been assigned to a CPU.
*
* Otherwise, the TCB will be reatined in an assigned task list,
* g_assignedtasks. As its name suggests, on 'g_assignedtasks queue for CPU
* 'n' would contain only tasks/threads that are assigned to CPU 'n'. Tasks/
* threads would be assigned a particular CPU by one of two mechanisms:
*
* - (Semi-)permanently through an RTOS interfaces such as
* pthread_attr_setaffinity(), or
* - Temporarily through scheduling logic when a previously unassigned task
* is made to run.
*
* Tasks/threads that are assigned to a CPU via an interface like
* pthread_attr_setaffinity() would never go into the g_readytorun list, but
* would only go into the g_assignedtasks[n] list for the CPU 'n' to which
* the thread has been assigned. Hence, the g_readytorun list would hold
* only unassigned tasks/threads.
*
* Like the g_readytorun list in in non-SMP case, each g_assignedtask[] list
* is prioritized: The head of the list is the currently active task on this
* CPU. Tasks after the active task are ready-to-run and assigned to this
* CPU. The tail of this assigned task list, the lowest priority task, is
* always the CPU's IDLE task.
*/
extern volatile dq_queue_t g_assignedtasks[CONFIG_SMP_NCPUS];
#endif
/* 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