From 592eaca1409e55407e980f71b2ec604ca3610ba5 Mon Sep 17 00:00:00 2001 From: Glenn Elliott Date: Tue, 21 Jun 2011 01:29:34 -0400 Subject: Avoid needlessly costly migrations. CONFIG_SCHED_CPU_AFFINITY Given a choice between several available CPUs (unlinked) on which to schedule a task, let the scheduler select the CPU closest to where that task was previously scheduled. Hopefully, this will reduce cache migration penalties. Notes: SCHED_CPU_AFFINITY is dependent upon x86 (only x86 is supported at this time). Also PFair/PD^2 does not make use of this feature. Signed-off-by: Andrea Bastoni --- include/litmus/affinity.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 include/litmus/affinity.h (limited to 'include/litmus/affinity.h') diff --git a/include/litmus/affinity.h b/include/litmus/affinity.h new file mode 100644 index 000000000000..5eee0eaa170d --- /dev/null +++ b/include/litmus/affinity.h @@ -0,0 +1,79 @@ +#ifndef __LITMUS_AFFINITY_H +#define __LITMUS_AFFINITY_H + +#include + +/* + L1 (instr) = depth 0 + L1 (data) = depth 1 + L2 = depth 2 + L3 = depth 3 + */ +#define NUM_CACHE_LEVELS 4 + +struct neighborhood +{ + unsigned int size[NUM_CACHE_LEVELS]; + cpumask_var_t neighbors[NUM_CACHE_LEVELS]; +}; + +/* topology info is stored redundently in a big array for fast lookups */ +extern struct neighborhood neigh_info[NR_CPUS]; + +void init_topology(void); /* called by Litmus module's _init_litmus() */ + +/* Works like: +void get_nearest_available_cpu( + cpu_entry_t* nearest, + cpu_entry_t* start, + cpu_entry_t* entries, + int release_master) + +Set release_master = -1 for no RM. + +We use a macro here to exploit the fact that C-EDF and G-EDF +have similar structures for their cpu_entry_t structs, even though +they do not share a common base-struct. The macro allows us to +avoid code duplication. + +TODO: Factor out the job-to-processor linking from C/G-EDF into +a reusable "processor mapping". (See B.B.'s RTSS'09 paper & +dissertation.) + */ +#define get_nearest_available_cpu(nearest, start, entries, release_master) \ +{ \ + (nearest) = NULL; \ + if (!(start)->linked) { \ + (nearest) = (start); \ + } else { \ + int __level; \ + int __cpu; \ + struct neighborhood* __neighbors = &neigh_info[(start)->cpu]; \ + \ + for (__level = 0; (__level < NUM_CACHE_LEVELS) && !(nearest); ++__level) { \ + if (__neighbors->size[__level] > 1) { \ + for_each_cpu(__cpu, __neighbors->neighbors[__level]) { \ + if (__cpu != (release_master)) { \ + cpu_entry_t* __entry = &per_cpu((entries), __cpu); \ + if (!__entry->linked) { \ + (nearest) = __entry; \ + break; \ + } \ + } \ + } \ + } else if (__neighbors->size[__level] == 0) { \ + break; \ + } \ + } \ + } \ + \ + if ((nearest)) { \ + TRACE("P%d is closest available CPU to P%d\n", \ + (nearest)->cpu, (start)->cpu); \ + } else { \ + TRACE("Could not find an available CPU close to P%d\n", \ + (start)->cpu); \ + } \ +} + +#endif -- cgit v1.2.2