diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2011-06-21 01:29:34 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2011-08-27 11:58:39 -0400 |
commit | 592eaca1409e55407e980f71b2ec604ca3610ba5 (patch) | |
tree | 43cadd8d3f9cc150a7b108696bfabcddcff55650 /include/litmus/affinity.h | |
parent | fb8d6602af1cbc09115544056b872b976c6349c3 (diff) |
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 <bastoni@cs.unc.edu>
Diffstat (limited to 'include/litmus/affinity.h')
-rw-r--r-- | include/litmus/affinity.h | 79 |
1 files changed, 79 insertions, 0 deletions
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 @@ | |||
1 | #ifndef __LITMUS_AFFINITY_H | ||
2 | #define __LITMUS_AFFINITY_H | ||
3 | |||
4 | #include <linux/cpumask.h> | ||
5 | |||
6 | /* | ||
7 | L1 (instr) = depth 0 | ||
8 | L1 (data) = depth 1 | ||
9 | L2 = depth 2 | ||
10 | L3 = depth 3 | ||
11 | */ | ||
12 | #define NUM_CACHE_LEVELS 4 | ||
13 | |||
14 | struct neighborhood | ||
15 | { | ||
16 | unsigned int size[NUM_CACHE_LEVELS]; | ||
17 | cpumask_var_t neighbors[NUM_CACHE_LEVELS]; | ||
18 | }; | ||
19 | |||
20 | /* topology info is stored redundently in a big array for fast lookups */ | ||
21 | extern struct neighborhood neigh_info[NR_CPUS]; | ||
22 | |||
23 | void init_topology(void); /* called by Litmus module's _init_litmus() */ | ||
24 | |||
25 | /* Works like: | ||
26 | void get_nearest_available_cpu( | ||
27 | cpu_entry_t* nearest, | ||
28 | cpu_entry_t* start, | ||
29 | cpu_entry_t* entries, | ||
30 | int release_master) | ||
31 | |||
32 | Set release_master = -1 for no RM. | ||
33 | |||
34 | We use a macro here to exploit the fact that C-EDF and G-EDF | ||
35 | have similar structures for their cpu_entry_t structs, even though | ||
36 | they do not share a common base-struct. The macro allows us to | ||
37 | avoid code duplication. | ||
38 | |||
39 | TODO: Factor out the job-to-processor linking from C/G-EDF into | ||
40 | a reusable "processor mapping". (See B.B.'s RTSS'09 paper & | ||
41 | dissertation.) | ||
42 | */ | ||
43 | #define get_nearest_available_cpu(nearest, start, entries, release_master) \ | ||
44 | { \ | ||
45 | (nearest) = NULL; \ | ||
46 | if (!(start)->linked) { \ | ||
47 | (nearest) = (start); \ | ||
48 | } else { \ | ||
49 | int __level; \ | ||
50 | int __cpu; \ | ||
51 | struct neighborhood* __neighbors = &neigh_info[(start)->cpu]; \ | ||
52 | \ | ||
53 | for (__level = 0; (__level < NUM_CACHE_LEVELS) && !(nearest); ++__level) { \ | ||
54 | if (__neighbors->size[__level] > 1) { \ | ||
55 | for_each_cpu(__cpu, __neighbors->neighbors[__level]) { \ | ||
56 | if (__cpu != (release_master)) { \ | ||
57 | cpu_entry_t* __entry = &per_cpu((entries), __cpu); \ | ||
58 | if (!__entry->linked) { \ | ||
59 | (nearest) = __entry; \ | ||
60 | break; \ | ||
61 | } \ | ||
62 | } \ | ||
63 | } \ | ||
64 | } else if (__neighbors->size[__level] == 0) { \ | ||
65 | break; \ | ||
66 | } \ | ||
67 | } \ | ||
68 | } \ | ||
69 | \ | ||
70 | if ((nearest)) { \ | ||
71 | TRACE("P%d is closest available CPU to P%d\n", \ | ||
72 | (nearest)->cpu, (start)->cpu); \ | ||
73 | } else { \ | ||
74 | TRACE("Could not find an available CPU close to P%d\n", \ | ||
75 | (start)->cpu); \ | ||
76 | } \ | ||
77 | } | ||
78 | |||
79 | #endif | ||