Add a CPU affinity set to the TCB if SMP is enable and use this CPU set as a mask for determining which CPUs the thread may run on. Add an affinity field to the attrributes to permit controlling which CPUs a pthread may run on. Implements pthread_att_setaffinity_np() and pthread_attr_getaffinity_np().

This commit is contained in:
Gregory Nutt 2016-02-19 17:33:35 -06:00
parent 2075eb7932
commit a633353ec3
28 changed files with 174 additions and 355 deletions

View file

@ -11505,3 +11505,11 @@
pthread_attr_setaffinity_np(), pthread_attr_getaffinity_np(),
pthread_setaffinity_np(), and pthread_getaffinity_np(). No implementation
is yet in place (2016-02-19).
* sched/sched_cpuselect.c, include/nuttx/sched.h, and other files. Add
a CPU affinity set to the TCB if SMP is enabled and use this CPU set as
a mask for determining which CPUs the thread may run on (2016-02-19).
* libc/pthread, sched/pthread/pthread_start.c, and include/pthread.h:
Add an affinity field to the attrributes to permit controlling
which CPUs a pthread may run on. Implements pthread_att_setaffinity_np()
and pthread_attr_getaffinity_np() (2016-02-19).

View file

@ -57,7 +57,24 @@
# define PTHREAD_DEFAULT_POLICY SCHED_RR
#endif
#ifdef CONFIG_SCHED_SPORADIC
/* A lot of hassle to use the old-fashioned struct initializers. But this
* gives us backward compatibility with some very old compilers.
*/
#if defined(CONFIG_SCHED_SPORADIC) && defined(CONFIG_SMP)
# define PTHREAD_ATTR_INITIALIZER \
{ \
PTHREAD_DEFAULT_PRIORITY, /* priority */ \
PTHREAD_DEFAULT_POLICY, /* policy */ \
PTHREAD_EXPLICIT_SCHED, /* inheritsched */ \
0, /* low_priority */ \
0, /* max_repl */ \
0, /* affinity */ \
PTHREAD_STACK_DEFAULT, /* stacksize */ \
{0, 0}, /* repl_period */ \
{0, 0} /* budget */ \
}
#elif defined(CONFIG_SCHED_SPORADIC)
# define PTHREAD_ATTR_INITIALIZER \
{ \
PTHREAD_DEFAULT_PRIORITY, /* priority */ \
@ -69,6 +86,15 @@
{0, 0}, /* repl_period */ \
{0, 0}, /* budget */ \
}
#elif defined(CONFIG_SMP)
# define PTHREAD_ATTR_INITIALIZER \
{ \
PTHREAD_DEFAULT_PRIORITY, /* priority */ \
PTHREAD_DEFAULT_POLICY, /* policy */ \
PTHREAD_EXPLICIT_SCHED, /* inheritsched */ \
0, /* affinity */ \
PTHREAD_STACK_DEFAULT, /* stacksize */ \
}
#else
# define PTHREAD_ATTR_INITIALIZER \
{ \

View file

@ -148,7 +148,7 @@
# 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_ASSIGNED (1 << 6) /* Bit 6: Assigned to a CPU */
#define TCB_FLAG_CPU_LOCKED (1 << 6) /* Bit 6: Locked to this CPU */
#define TCB_FLAG_EXIT_PROCESSING (1 << 7) /* Bit 7: Exitting */
/* Bits 8-15: Available */
@ -562,6 +562,7 @@ struct tcb_s
uint8_t task_state; /* Current state of the thread */
#ifdef CONFIG_SMP
uint8_t cpu; /* CPU index if running or assigned */
cpu_set_t affinity; /* Bit set of permitted CPUs */
#endif
uint16_t flags; /* Misc. general status flags */
int16_t lockcount; /* 0=preemptable (not-locked) */

View file

@ -178,6 +178,10 @@ struct pthread_attr_s
uint8_t max_repl; /* Maximum pending replenishments */
#endif
#ifdef CONFIG_SMP
cpu_set_t affinity; /* Set of permitted CPUs for the thread */
#endif
size_t stacksize; /* Size of the stack allocated for the pthread */
#ifdef CONFIG_SCHED_SPORADIC

View file

@ -46,6 +46,11 @@ CSRCS += pthread_attrinit.c pthread_attrdestroy.c \
pthread_mutexattrinit.c pthread_mutexattrdestroy.c \
pthread_mutexattrgetpshared.c pthread_mutexattrsetpshared.c
ifeq ($(CONFIG_SMP),y)
CSRCS += pthread_attrgetaffinity.c pthread_attrsetaffinity.c
# CSRCS += pthread_getaffinity.c pthread_setaffinity.c
endif
ifeq ($(CONFIG_MUTEX_TYPES),y)
CSRCS += pthread_mutexattrsettype.c pthread_mutexattrgettype.c
endif

View file

@ -44,26 +44,6 @@
#include <debug.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -44,26 +44,6 @@
#include <debug.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#include <debug.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#include <debug.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -46,14 +46,6 @@
#include <nuttx/pthread.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
@ -69,14 +61,6 @@
const pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER;
#endif
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -45,26 +45,6 @@
#include <debug.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -44,26 +44,6 @@
#include <debug.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/********************************************************************************
* Pre-processor Definitions
********************************************************************************/
/********************************************************************************
* Private Type Declarations
********************************************************************************/
/********************************************************************************
* Public Data
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Function Prototypes
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/********************************************************************************
* Pre-processor Definitions
********************************************************************************/
/********************************************************************************
* Private Type Declarations
********************************************************************************/
/********************************************************************************
* Public Data
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Function Prototypes
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/********************************************************************************
* Pre-processor Definitions
********************************************************************************/
/********************************************************************************
* Private Type Declarations
********************************************************************************/
/********************************************************************************
* Public Data
********************************************************************************/
/********************************************************************************
* Private Variables
********************************************************************************/
/********************************************************************************
* Private Function Prototypes
********************************************************************************/
/********************************************************************************
* Public Functions
********************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#ifdef CONFIG_MUTEX_TYPES
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#include <errno.h>
#include <debug.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -43,26 +43,6 @@
#ifdef CONFIG_MUTEX_TYPES
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View file

@ -73,6 +73,16 @@
#endif
#include "init/init.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_SMP
/* This set of all CPUs */
# define SCHED_ALL_CPUS ((1 << CONFIG_SMP_NCPUS) - 1)
#endif /* CONFIG_SMP */
/****************************************************************************
* Public Data
****************************************************************************/
@ -452,19 +462,31 @@ void os_start(void)
}
/* Set the task flags to indicate that this is a kernel thread and, if
* configured for SMP, that this task is assigned to the correct CPU.
* configured for SMP, that this task is locked to this CPU.
*/
#ifdef CONFIG_SMP
g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_ASSIGNED);
g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_LOCKED);
g_idletcb[cpu].cmn.cpu = cpu;
#else
g_idletcb[cpu].cmn.flags = TCB_FLAG_TTYPE_KERNEL;
#endif
/* Set the IDLE task name */
#ifdef CONFIG_SMP
/* Set the affinity mask to allow the thread to run on all CPUs. No,
* this IDLE thread can only run on its assigned CPU. That is
* enforced by the TCB_FLAG_CPU_LOCKED which overrides the affinity
* mask. This is essential because all tasks inherit the affinity
* mask from their parent and, ultimately, the parent of all tasks is
* the IDLE task.
*/
g_idletcb[cpu].cmn.affinity = SCHED_ALL_CPUS;
#endif
#if CONFIG_TASK_NAME_SIZE > 0
/* Set the IDLE task name */
# ifdef CONFIG_SMP
snprintf(g_idletcb[cpu].cmn.name, CONFIG_TASK_NAME_SIZE, "CPU%d IDLE", cpu);
# else

View file

@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread/pthread_create.c
*
* Copyright (C) 2007-2009, 2011, 2013-2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011, 2013-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -404,6 +404,20 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
goto errout_with_join;
}
#ifdef CONFIG_SMP
/* pthread_schedsetup() will set the affinity mask by inheriting the
* setting from the parent task. We need to override this setting
* with the value from the pthread attributes unless that value is
* zero: Zero is the default value and simply means to inherit the
* parent thread's affinity mask.
*/
if ( attr->affinity != 0)
{
ptcb->cmn.affinity = attr->affinity;
}
#endif
/* Configure the TCB for a pthread receiving on parameter
* passed by value
*/

View file

@ -417,11 +417,11 @@ void sched_sporadic_lowpriority(FAR struct tcb_s *tcb);
#endif
#ifdef CONFIG_SMP
int sched_cpu_select(void);
int sched_cpu_select(cpu_set_t affinity);
# define sched_islocked(tcb) spin_islocked(&g_cpu_schedlock)
#else
# define sched_islocked(tcb) ((tcb)->lockcount > 0)
# define sched_cpu_select (0)
# define sched_cpu_select(a) (0)
#endif

View file

@ -176,9 +176,9 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb)
bool switched;
bool doswitch;
/* Check if the blocked TCB is already assigned to a CPU */
/* Check if the blocked TCB is locked to this CPU */
if ((btcb->flags & TCB_FLAG_CPU_ASSIGNED) != 0)
if ((btcb->flags & TCB_FLAG_CPU_LOCKED) != 0)
{
/* Yes.. that that is the CPU we must use */
@ -190,7 +190,7 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb)
* (possibly its IDLE task).
*/
cpu = sched_cpu_select();
cpu = sched_cpu_select(btcb->affinity);
}
/* Get the task currently running on the CPU (maybe the IDLE task) */
@ -207,11 +207,11 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb)
task_state = TSTATE_TASK_RUNNING;
}
/* If it will not be running, but is assigned to a CPU, then it will be in
* the asssigned state.
/* If it will not be running, but is locked to a CPU, then it will be in
* the assigned state.
*/
else if ((btcb->flags & TCB_FLAG_CPU_ASSIGNED) != 0)
else if ((btcb->flags & TCB_FLAG_CPU_LOCKED) != 0)
{
task_state = TSTATE_TASK_ASSIGNED;
cpu = btcb->cpu;
@ -328,7 +328,7 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb)
&g_cpu_irqlock);
}
/* If the following task is not assigned to this CPU, then it must
/* If the following task is not locked to this CPU, then it must
* be moved to the g_readytorun list. Since it cannot be at the
* head of the list, we can do this without invoking any heavy
* lifting machinery.
@ -337,7 +337,7 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb)
DEBUGASSERT(btcb->flink != NULL);
next = (FAR struct tcb_s *)btcb->flink;
if ((next->flags & TCB_FLAG_CPU_ASSIGNED) != 0)
if ((next->flags & TCB_FLAG_CPU_LOCKED) != 0)
{
DEBUGASSERT(next->cpu == cpu);
next->task_state = TSTATE_TASK_ASSIGNED;

View file

@ -48,6 +48,12 @@
#ifdef CONFIG_SMP
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define IMPOSSIBLE_CPU 0xff
/****************************************************************************
* Public Functions
****************************************************************************/
@ -60,7 +66,7 @@
* possbily its IDLE task.
*
* Inputs:
* None
* affinity - The set of CPUs on which the thread is permitted to run.
*
* Return Value:
* Index of the CPU with the lowest priority running task
@ -70,7 +76,7 @@
*
****************************************************************************/
int sched_cpu_select(void)
int sched_cpu_select(cpu_set_t affinity)
{
uint8_t minprio;
int cpu;
@ -81,32 +87,38 @@ int sched_cpu_select(void)
*/
minprio = SCHED_PRIORITY_MAX;
cpu = 0;
cpu = IMPOSSIBLE_CPU;
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_assignedtasks[i].head;
/* If the thread permitted to run on this CPU? */
/* If this thread is executing its IDLE task, the use it. The IDLE
* task is always the last task in the assigned task list.
*/
if (rtcb->flink == NULL)
if ((affinity & (1 << i)) != 0)
{
/* The IDLE task should always be assigned to this CPU and have
* a priority of zero.
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_assignedtasks[i].head;
/* If this thread is executing its IDLE task, the use it. The
* IDLE task is always the last task in the assigned task list.
*/
DEBUGASSERT(rtcb->sched_priority == 0);
return i;
}
else if (rtcb->sched_priority < minprio)
{
DEBUGASSERT(rtcb->sched_priority > 0);
cpu = i;
if (rtcb->flink == NULL)
{
/* The IDLE task should always be assigned to this CPU and have
* a priority of zero.
*/
DEBUGASSERT(rtcb->sched_priority == 0);
return i;
}
else if (rtcb->sched_priority < minprio)
{
DEBUGASSERT(rtcb->sched_priority > 0);
cpu = i;
}
}
}
DEBUGASSERT(cpu != IMPOSSIBLE_CPU);
return cpu;
}

View file

@ -131,7 +131,7 @@ static void sched_readytorun_setpriority(FAR struct tcb_s *tcb,
if (tcb->task_state == TSTATE_TASK_READYTORUN)
{
cpu = sched_cpu_select();
cpu = sched_cpu_select(tcb->affinity);
}
/* CASE 2b. The task is ready to run, and assigned to a CPU. An increase

View file

@ -1,7 +1,7 @@
/****************************************************************************
* sched/task/task_setup.c
*
* 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
@ -146,6 +146,38 @@ static int task_assignpid(FAR struct tcb_s *tcb)
return ERROR;
}
/****************************************************************************
* Name: task_inherit_affinity
*
* Description:
* exec(), task_create(), and vfork() all inherit the affinity mask from
* the parent thread. This is the default for pthread_create() as well
* but the affinity mask can be specified in the pthread attributes as
* well. pthread_setup() will have to fix up the affinity mask in this
* case.
*
* Parameters:
* tcb - The TCB of the new task.
*
* Returned Value:
* None
*
* Assumptions:
* The parent of the new task is the task at the head of the ready-to-run
* list.
*
****************************************************************************/
#ifdef CONFIG_SMP
static inline void task_inherit_affinity(FAR struct tcb_s *tcb)
{
FAR struct tcb_s *rtcb = this_task();
tcb->affinity = rtcb->affinity;
}
#else
# define task_inherit_affinity(tcb)
#endif
/****************************************************************************
* Name: task_saveparent
*
@ -348,11 +380,22 @@ static int thread_schedsetup(FAR struct tcb_s *tcb, int priority,
task_saveparent(tcb, ttype);
#ifdef CONFIG_SMP
/* exec(), task_create(), and vfork() all inherit the affinity mask
* from the parent thread. This is the default for pthread_create()
* as well but the affinity mask can be specified in the pthread
* attributes as well. pthread_create() will have to fix up the
* affinity mask in this case.
*/
task_inherit_affinity(tcb);
#endif
#ifndef CONFIG_DISABLE_SIGNALS
/* exec(), pthread_create(), task_create(), and vfork() all
* inherit the signal mask of the parent thread.
*/
#ifndef CONFIG_DISABLE_SIGNALS
(void)sigprocmask(SIG_SETMASK, NULL, &tcb->sigprocmask);
#endif
@ -628,8 +671,8 @@ int task_schedsetup(FAR struct task_tcb_s *tcb, int priority, start_t start,
****************************************************************************/
#ifndef CONFIG_DISABLE_PTHREAD
int pthread_schedsetup(FAR struct pthread_tcb_s *tcb, int priority, start_t start,
pthread_startroutine_t entry)
int pthread_schedsetup(FAR struct pthread_tcb_s *tcb, int priority,
start_t start, pthread_startroutine_t entry)
{
/* Perform common thread setup */