diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-04-15 19:29:09 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-04-15 19:29:09 -0400 |
commit | 0b865246946a97dc03a81ccf55bf84acce923c4b (patch) | |
tree | bc8f16cd18e6b6a759f701508a23b698771299fa | |
parent | bb4922c968aa1a30fddd6ad9d0f750706c7b3b29 (diff) |
Infrastructure for affinity-aware k-exclusion
-rw-r--r-- | include/litmus/fdso.h | 5 | ||||
-rw-r--r-- | include/litmus/kexclu_affinity.h | 31 | ||||
-rw-r--r-- | include/litmus/rt_param.h | 5 | ||||
-rw-r--r-- | include/litmus/sched_plugin.h | 14 | ||||
-rw-r--r-- | litmus/Kconfig | 24 | ||||
-rw-r--r-- | litmus/Makefile | 2 | ||||
-rw-r--r-- | litmus/fdso.c | 6 | ||||
-rw-r--r-- | litmus/kexclu_affinity.c | 84 | ||||
-rw-r--r-- | litmus/sched_gsn_edf.c | 1 | ||||
-rw-r--r-- | litmus/sched_plugin.c | 15 |
10 files changed, 183 insertions, 4 deletions
diff --git a/include/litmus/fdso.h b/include/litmus/fdso.h index 2bff9cc3909d..baf28c47e95d 100644 --- a/include/litmus/fdso.h +++ b/include/litmus/fdso.h | |||
@@ -24,7 +24,10 @@ typedef enum { | |||
24 | IKGLP_SEM = 3, | 24 | IKGLP_SEM = 3, |
25 | KFMLP_SEM = 4, | 25 | KFMLP_SEM = 4, |
26 | 26 | ||
27 | MAX_OBJ_TYPE = 4 | 27 | IKGLP_AFF_OBS = 5, |
28 | KFMLP_AFF_OBS = 6, | ||
29 | |||
30 | MAX_OBJ_TYPE = 6 | ||
28 | } obj_type_t; | 31 | } obj_type_t; |
29 | 32 | ||
30 | struct inode_obj_id { | 33 | struct inode_obj_id { |
diff --git a/include/litmus/kexclu_affinity.h b/include/litmus/kexclu_affinity.h new file mode 100644 index 000000000000..f5b5e7b1f359 --- /dev/null +++ b/include/litmus/kexclu_affinity.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef LITMUS_AFF_OBS_H | ||
2 | #define LITMUS_AFF_OBS_H | ||
3 | |||
4 | #include <litmus/locking.h> | ||
5 | |||
6 | struct affinity_observer_ops; | ||
7 | |||
8 | struct affinity_observer | ||
9 | { | ||
10 | struct affinity_observer_ops* ops; | ||
11 | int type; | ||
12 | int ident; | ||
13 | |||
14 | struct litmus_lock* lock; // the lock under observation | ||
15 | }; | ||
16 | |||
17 | typedef int (*aff_obs_open_t)(struct affinity_observer* aff_obs, | ||
18 | void* __user arg); | ||
19 | typedef int (*aff_obs_close_t)(struct affinity_observer* aff_obs); | ||
20 | typedef void (*aff_obs_free_t)(struct affinity_observer* aff_obs); | ||
21 | |||
22 | struct affinity_observer_ops | ||
23 | { | ||
24 | aff_obs_open_t open; | ||
25 | aff_obs_close_t close; | ||
26 | aff_obs_free_t deallocate; | ||
27 | }; | ||
28 | |||
29 | struct litmus_lock* get_lock_from_od(int od); | ||
30 | |||
31 | #endif | ||
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index b4eb8ee95687..cc638e9c55d1 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
@@ -52,6 +52,11 @@ union np_flag { | |||
52 | } np; | 52 | } np; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | struct affinity_observer_args | ||
56 | { | ||
57 | int lock_od; | ||
58 | }; | ||
59 | |||
55 | /* The definition of the data that is shared between the kernel and real-time | 60 | /* The definition of the data that is shared between the kernel and real-time |
56 | * tasks via a shared page (see litmus/ctrldev.c). | 61 | * tasks via a shared page (see litmus/ctrldev.c). |
57 | * | 62 | * |
diff --git a/include/litmus/sched_plugin.h b/include/litmus/sched_plugin.h index 8e65555d9b7f..d14f705ef414 100644 --- a/include/litmus/sched_plugin.h +++ b/include/litmus/sched_plugin.h | |||
@@ -11,6 +11,10 @@ | |||
11 | #include <litmus/locking.h> | 11 | #include <litmus/locking.h> |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
15 | #include <litmus/kexclu_affinity.h> | ||
16 | #endif | ||
17 | |||
14 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
15 | 19 | ||
16 | /************************ setup/tear down ********************/ | 20 | /************************ setup/tear down ********************/ |
@@ -59,6 +63,10 @@ typedef void (*task_exit_t) (struct task_struct *); | |||
59 | typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type, | 63 | typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type, |
60 | void* __user config); | 64 | void* __user config); |
61 | 65 | ||
66 | typedef long (*allocate_affinity_observer_t) ( | ||
67 | struct affinity_observer **aff_obs, int type, | ||
68 | void* __user config); | ||
69 | |||
62 | typedef void (*increase_prio_t)(struct task_struct* t, struct task_struct* prio_inh); | 70 | typedef void (*increase_prio_t)(struct task_struct* t, struct task_struct* prio_inh); |
63 | typedef void (*decrease_prio_t)(struct task_struct* t, struct task_struct* prio_inh); | 71 | typedef void (*decrease_prio_t)(struct task_struct* t, struct task_struct* prio_inh); |
64 | typedef void (*nested_increase_prio_t)(struct task_struct* t, struct task_struct* prio_inh, | 72 | typedef void (*nested_increase_prio_t)(struct task_struct* t, struct task_struct* prio_inh, |
@@ -146,7 +154,11 @@ struct sched_plugin { | |||
146 | #ifdef CONFIG_LITMUS_DGL_SUPPORT | 154 | #ifdef CONFIG_LITMUS_DGL_SUPPORT |
147 | get_dgl_spinlock_t get_dgl_spinlock; | 155 | get_dgl_spinlock_t get_dgl_spinlock; |
148 | #endif | 156 | #endif |
149 | 157 | ||
158 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
159 | allocate_affinity_observer_t allocate_aff_obs; | ||
160 | #endif | ||
161 | |||
150 | #ifdef CONFIG_LITMUS_SOFTIRQD | 162 | #ifdef CONFIG_LITMUS_SOFTIRQD |
151 | increase_prio_klitirq_t increase_prio_klitirqd; | 163 | increase_prio_klitirq_t increase_prio_klitirqd; |
152 | decrease_prio_klitirqd_t decrease_prio_klitirqd; | 164 | decrease_prio_klitirqd_t decrease_prio_klitirqd; |
diff --git a/litmus/Kconfig b/litmus/Kconfig index 6cf4d7eaa96f..263c3ee49c15 100644 --- a/litmus/Kconfig +++ b/litmus/Kconfig | |||
@@ -60,6 +60,16 @@ config LITMUS_LOCKING | |||
60 | Say Yes if you want to include locking protocols such as the FMLP and | 60 | Say Yes if you want to include locking protocols such as the FMLP and |
61 | Baker's SRP. | 61 | Baker's SRP. |
62 | 62 | ||
63 | config LITMUS_AFFINITY_LOCKING | ||
64 | bool "Enable affinity infrastructure in k-exclusion locking protocols." | ||
65 | depends on LITMUS_LOCKING | ||
66 | default n | ||
67 | help | ||
68 | Enable affinity tracking infrastructure in k-exclusion locking protocols. | ||
69 | This only enabled the *infrastructure* not actual affinity algorithms. | ||
70 | |||
71 | If unsure, say No. | ||
72 | |||
63 | config LITMUS_NESTED_LOCKING | 73 | config LITMUS_NESTED_LOCKING |
64 | bool "Support for nested inheritance in locking protocols" | 74 | bool "Support for nested inheritance in locking protocols" |
65 | depends on LITMUS_LOCKING | 75 | depends on LITMUS_LOCKING |
@@ -291,7 +301,19 @@ config LITMUS_NVIDIA | |||
291 | depends on LITMUS_SOFTIRQD || LITMUS_PAI_SOFTIRQD | 301 | depends on LITMUS_SOFTIRQD || LITMUS_PAI_SOFTIRQD |
292 | default n | 302 | default n |
293 | help | 303 | help |
294 | Direct tasklets from NVIDIA devices to Litmus's klitirqd. | 304 | Direct tasklets from NVIDIA devices to Litmus's klitirqd |
305 | or PAI interrupt handling routines. | ||
306 | |||
307 | If unsure, say No. | ||
308 | |||
309 | config LITMUS_AFFINITY_AWARE_GPU_ASSINGMENT | ||
310 | bool "Enable affinity-aware heuristics to improve GPU assignment." | ||
311 | depends on LITMUS_NVIDIA && LITMUS_AFFINITY_LOCKING | ||
312 | default n | ||
313 | help | ||
314 | Enable several heuristics to improve the assignment | ||
315 | of GPUs to real-time tasks to reduce the overheads | ||
316 | of memory migrations. | ||
295 | 317 | ||
296 | If unsure, say No. | 318 | If unsure, say No. |
297 | 319 | ||
diff --git a/litmus/Makefile b/litmus/Makefile index 91fd32cb979d..1698afb75ec4 100644 --- a/litmus/Makefile +++ b/litmus/Makefile | |||
@@ -34,3 +34,5 @@ obj-$(CONFIG_LITMUS_NESTED_LOCKING) += rsm_lock.o ikglp_lock.o | |||
34 | obj-$(CONFIG_LITMUS_SOFTIRQD) += litmus_softirq.o | 34 | obj-$(CONFIG_LITMUS_SOFTIRQD) += litmus_softirq.o |
35 | obj-$(CONFIG_LITMUS_PAI_SOFTIRQD) += litmus_pai_softirq.o | 35 | obj-$(CONFIG_LITMUS_PAI_SOFTIRQD) += litmus_pai_softirq.o |
36 | obj-$(CONFIG_LITMUS_NVIDIA) += nvidia_info.o sched_trace_external.o | 36 | obj-$(CONFIG_LITMUS_NVIDIA) += nvidia_info.o sched_trace_external.o |
37 | |||
38 | obj-$(CONFIG_LITMUS_AFFINITY_LOCKING) += kexclu_affinity.o | ||
diff --git a/litmus/fdso.c b/litmus/fdso.c index 5ef858e59ab0..0bacea179660 100644 --- a/litmus/fdso.c +++ b/litmus/fdso.c | |||
@@ -20,12 +20,16 @@ | |||
20 | 20 | ||
21 | extern struct fdso_ops generic_lock_ops; | 21 | extern struct fdso_ops generic_lock_ops; |
22 | 22 | ||
23 | extern struct fdso_ops generic_affinity_ops; | ||
24 | |||
23 | static const struct fdso_ops* fdso_ops[] = { | 25 | static const struct fdso_ops* fdso_ops[] = { |
24 | &generic_lock_ops, /* FMLP_SEM */ | 26 | &generic_lock_ops, /* FMLP_SEM */ |
25 | &generic_lock_ops, /* KFMLP_SEM */ | ||
26 | &generic_lock_ops, /* SRP_SEM */ | 27 | &generic_lock_ops, /* SRP_SEM */ |
27 | &generic_lock_ops, /* RSM_MUTEX */ | 28 | &generic_lock_ops, /* RSM_MUTEX */ |
28 | &generic_lock_ops, /* IKGLP_SEM */ | 29 | &generic_lock_ops, /* IKGLP_SEM */ |
30 | &generic_lock_ops, /* KFMLP_SEM */ | ||
31 | &generic_affinity_ops, /* IKGLP_AFF_OBS */ | ||
32 | &generic_affinity_ops, /* KFMLP_AFF_OBS */ | ||
29 | }; | 33 | }; |
30 | 34 | ||
31 | static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) | 35 | static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) |
diff --git a/litmus/kexclu_affinity.c b/litmus/kexclu_affinity.c new file mode 100644 index 000000000000..a06df3e1acbd --- /dev/null +++ b/litmus/kexclu_affinity.c | |||
@@ -0,0 +1,84 @@ | |||
1 | #include <litmus/fdso.h> | ||
2 | #include <litmus/sched_plugin.h> | ||
3 | #include <litmus/trace.h> | ||
4 | #include <litmus/litmus.h> | ||
5 | #include <litmus/locking.h> | ||
6 | |||
7 | #include <litmus/kexclu_affinity.h> | ||
8 | |||
9 | static int create_generic_aff_obs(void** obj_ref, obj_type_t type, void* __user arg); | ||
10 | static int open_generic_aff_obs(struct od_table_entry* entry, void* __user arg); | ||
11 | static int close_generic_aff_obs(struct od_table_entry* entry); | ||
12 | static void destroy_generic_aff_obs(obj_type_t type, void* sem); | ||
13 | |||
14 | struct fdso_ops generic_affinity_ops = { | ||
15 | .create = create_generic_aff_obs, | ||
16 | .open = open_generic_aff_obs, | ||
17 | .close = close_generic_aff_obs, | ||
18 | .destroy = destroy_generic_aff_obs | ||
19 | }; | ||
20 | |||
21 | static atomic_t aff_obs_id_gen = ATOMIC_INIT(0); | ||
22 | |||
23 | static inline bool is_affinity_observer(struct od_table_entry *entry) | ||
24 | { | ||
25 | return (entry->class == &generic_affinity_ops); | ||
26 | } | ||
27 | |||
28 | static inline struct affinity_observer* get_affinity_observer(struct od_table_entry* entry) | ||
29 | { | ||
30 | BUG_ON(!is_affinity_observer(entry)); | ||
31 | return (struct affinity_observer*) entry->obj->obj; | ||
32 | } | ||
33 | |||
34 | static int create_generic_aff_obs(void** obj_ref, obj_type_t type, void* __user arg) | ||
35 | { | ||
36 | struct affinity_observer* aff_obs; | ||
37 | int err; | ||
38 | |||
39 | err = litmus->allocate_aff_obs(&aff_obs, type, arg); | ||
40 | if (err == 0) { | ||
41 | BUG_ON(!aff_obs->lock); | ||
42 | aff_obs->ident = atomic_inc_return(&aff_obs_id_gen); | ||
43 | *obj_ref = aff_obs; | ||
44 | } | ||
45 | return err; | ||
46 | } | ||
47 | |||
48 | static int open_generic_aff_obs(struct od_table_entry* entry, void* __user arg) | ||
49 | { | ||
50 | struct affinity_observer* aff_obs = get_affinity_observer(entry); | ||
51 | if (aff_obs->ops->open) | ||
52 | return aff_obs->ops->open(aff_obs, arg); | ||
53 | else | ||
54 | return 0; /* default: any task can open it */ | ||
55 | } | ||
56 | |||
57 | static int close_generic_aff_obs(struct od_table_entry* entry) | ||
58 | { | ||
59 | struct affinity_observer* aff_obs = get_affinity_observer(entry); | ||
60 | if (aff_obs->ops->close) | ||
61 | return aff_obs->ops->close(aff_obs); | ||
62 | else | ||
63 | return 0; /* default: closing succeeds */ | ||
64 | } | ||
65 | |||
66 | static void destroy_generic_aff_obs(obj_type_t type, void* obj) | ||
67 | { | ||
68 | struct affinity_observer* aff_obs = (struct affinity_observer*) obj; | ||
69 | aff_obs->ops->deallocate(aff_obs); | ||
70 | } | ||
71 | |||
72 | |||
73 | struct litmus_lock* get_lock_from_od(int od) | ||
74 | { | ||
75 | extern struct fdso_ops generic_lock_ops; | ||
76 | |||
77 | struct od_table_entry *entry = get_entry_for_od(od); | ||
78 | |||
79 | if(entry && entry->class == &generic_lock_ops) { | ||
80 | return (struct litmus_lock*) entry->obj->obj; | ||
81 | } | ||
82 | return NULL; | ||
83 | } | ||
84 | |||
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c index 37294111bb0c..1440372227c6 100644 --- a/litmus/sched_gsn_edf.c +++ b/litmus/sched_gsn_edf.c | |||
@@ -1042,6 +1042,7 @@ static void __increase_priority_inheritance(struct task_struct* t, | |||
1042 | 1042 | ||
1043 | #ifdef CONFIG_LITMUS_NESTED_LOCKING | 1043 | #ifdef CONFIG_LITMUS_NESTED_LOCKING |
1044 | /* this sanity check allows for weaker locking in protocols */ | 1044 | /* this sanity check allows for weaker locking in protocols */ |
1045 | /* TODO (klitirqd): Skip this check if 't' is a proxy thread (???) */ | ||
1045 | if(__edf_higher_prio(prio_inh, BASE, t, EFFECTIVE)) { | 1046 | if(__edf_higher_prio(prio_inh, BASE, t, EFFECTIVE)) { |
1046 | #endif | 1047 | #endif |
1047 | TRACE_TASK(t, "inherits priority from %s/%d\n", | 1048 | TRACE_TASK(t, "inherits priority from %s/%d\n", |
diff --git a/litmus/sched_plugin.c b/litmus/sched_plugin.c index 24326ce4657e..de15e80743a8 100644 --- a/litmus/sched_plugin.c +++ b/litmus/sched_plugin.c | |||
@@ -188,6 +188,14 @@ static raw_spinlock_t* litmus_dummy_get_dgl_spinlock(struct task_struct *t) | |||
188 | } | 188 | } |
189 | #endif | 189 | #endif |
190 | 190 | ||
191 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
192 | static long litmus_dummy_allocate_aff_obs(struct affinity_observer **aff_obs, | ||
193 | int type, | ||
194 | void* __user config) | ||
195 | { | ||
196 | return -ENXIO; | ||
197 | } | ||
198 | #endif | ||
191 | 199 | ||
192 | 200 | ||
193 | /* The default scheduler plugin. It doesn't do anything and lets Linux do its | 201 | /* The default scheduler plugin. It doesn't do anything and lets Linux do its |
@@ -228,6 +236,10 @@ struct sched_plugin linux_sched_plugin = { | |||
228 | #ifdef CONFIG_LITMUS_DGL_SUPPORT | 236 | #ifdef CONFIG_LITMUS_DGL_SUPPORT |
229 | .get_dgl_spinlock = litmus_dummy_get_dgl_spinlock, | 237 | .get_dgl_spinlock = litmus_dummy_get_dgl_spinlock, |
230 | #endif | 238 | #endif |
239 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
240 | .allocate_aff_obs = litmus_dummy_allocate_aff_obs, | ||
241 | #endif | ||
242 | |||
231 | .admit_task = litmus_dummy_admit_task | 243 | .admit_task = litmus_dummy_admit_task |
232 | }; | 244 | }; |
233 | 245 | ||
@@ -286,6 +298,9 @@ int register_sched_plugin(struct sched_plugin* plugin) | |||
286 | #ifdef CONFIG_LITMUS_DGL_SUPPORT | 298 | #ifdef CONFIG_LITMUS_DGL_SUPPORT |
287 | CHECK(get_dgl_spinlock); | 299 | CHECK(get_dgl_spinlock); |
288 | #endif | 300 | #endif |
301 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
302 | CHECK(allocate_aff_obs); | ||
303 | #endif | ||
289 | CHECK(admit_task); | 304 | CHECK(admit_task); |
290 | 305 | ||
291 | if (!plugin->release_at) | 306 | if (!plugin->release_at) |