kernel/sched: CPU mask affinity/pinning API

This adds a simple implementation of SMP CPU affinity to Zephyr.  The
API is simple and doesn't try to invent abstractions like "cpu sets".
Each thread has an enable/disable flag associated with each CPU in the
system, and the bits can be turned on and off (for threads that are
not currently runnable, of course) using an easy three-function API.

Because the implementation picked requires enumerating runnable
threads in priority order looking for one that match the current CPU,
this is not a good fit for the SCALABLE or MULTIQ scheduler backends,
so it currently can be enabled only for SCHED_DUMB (which is the
default anyway).  Fancier algorithms do exist, but even the best of
them scale as O(N_CPUS), so aren't quite constant time and often
require significant memory overhead to keep separate lists for
different cpus/sets.

The intended use here is for apps that want to "pin" threads to
specific CPUs for latency control, or conversely to prevent certain
threads from taking time on specific CPUs to leave them free for fast
response.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2019-01-30 15:00:42 -08:00 committed by Anas Nashif
commit ab46b1b3c5
5 changed files with 145 additions and 2 deletions

View file

@ -452,6 +452,12 @@ struct _thread_base {
/* Recursive count of irq_lock() calls */
u8_t global_lock_count;
#endif
#ifdef CONFIG_SCHED_CPU_MASK
/* "May run on" bits for each CPU */
u8_t cpu_mask;
#endif
/* data returned by APIs */
@ -1035,6 +1041,52 @@ __syscall void k_thread_priority_set(k_tid_t thread, int prio);
__syscall void k_thread_deadline_set(k_tid_t thread, int deadline);
#endif
#ifdef CONFIG_SCHED_CPU_MASK
/**
* @brief Sets all CPU enable masks to zero
*
* After this returns, the thread will no longer be schedulable on any
* CPUs. The thread must not be currently runnable.
*
* @param thread Thread to operate upon
* @return Zero on success, otherwise error code
*/
int k_thread_cpu_mask_clear(k_tid_t thread);
/**
* @brief Sets all CPU enable masks to one
*
* After this returns, the thread will be schedulable on any CPU. The
* thread must not be currently runnable.
*
* @param thread Thread to operate upon
* @return Zero on success, otherwise error code
*/
int k_thread_cpu_mask_enable_all(k_tid_t thread);
/**
* @brief Enable thread to run on specified CPU
*
* The thread must not be currently runnable.
*
* @param thread Thread to operate upon
* @param cpu CPU index
* @return Zero on success, otherwise error code
*/
int k_thread_cpu_mask_enable(k_tid_t thread, int cpu);
/**
* @brief Prevent thread to run on specified CPU
*
* The thread must not be currently runnable.
*
* @param thread Thread to operate upon
* @param cpu CPU index
* @return Zero on success, otherwise error code
*/
int k_thread_cpu_mask_disable(k_tid_t thread, int cpu);
#endif
/**
* @brief Suspend a thread.
*