diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2014-03-14 16:45:44 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2014-03-14 16:45:44 -0400 |
commit | c93d29a1d7e65a32bfa9111c93badb26b3622f13 (patch) | |
tree | d0f46adbc05ffb3e6606a1316bf6ead37c816252 | |
parent | d03c848f2b2b18e6d9a2d408c2fc2a6433dc4f91 (diff) |
Make R2DGLP use sbinheap.
This patch updates the R2DGLP implementation to use
the sbinheap data structure in cases where the max
heap size is known.
-rw-r--r-- | include/litmus/r2dglp_lock.h | 22 | ||||
-rw-r--r-- | litmus/r2dglp_lock.c | 349 |
2 files changed, 233 insertions, 138 deletions
diff --git a/include/litmus/r2dglp_lock.h b/include/litmus/r2dglp_lock.h index 2773997b0ff1..6392642c0159 100644 --- a/include/litmus/r2dglp_lock.h +++ b/include/litmus/r2dglp_lock.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <litmus/litmus.h> | 4 | #include <litmus/litmus.h> |
5 | #include <litmus/binheap.h> | 5 | #include <litmus/binheap.h> |
6 | #include <litmus/sbinheap.h> | ||
6 | #include <litmus/locking.h> | 7 | #include <litmus/locking.h> |
7 | 8 | ||
8 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 9 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
@@ -13,7 +14,9 @@ struct r2dglp_affinity; | |||
13 | typedef struct r2dglp_heap_node | 14 | typedef struct r2dglp_heap_node |
14 | { | 15 | { |
15 | struct task_struct *task; | 16 | struct task_struct *task; |
16 | struct binheap_node node; | 17 | |
18 | sbinheap_node_t snode; /* static heap node */ | ||
19 | binheap_node_t dnode; /* dynamic heap node */ | ||
17 | } r2dglp_heap_node_t; | 20 | } r2dglp_heap_node_t; |
18 | 21 | ||
19 | struct fifo_queue; | 22 | struct fifo_queue; |
@@ -28,7 +31,7 @@ typedef struct r2dglp_donee_heap_node | |||
28 | /* cross-linked with r2dglp_wait_state_t of donor */ | 31 | /* cross-linked with r2dglp_wait_state_t of donor */ |
29 | struct r2dglp_wait_state *donor_info; | 32 | struct r2dglp_wait_state *donor_info; |
30 | 33 | ||
31 | struct binheap_node node; | 34 | sbinheap_node_t snode; |
32 | } r2dglp_donee_heap_node_t; | 35 | } r2dglp_donee_heap_node_t; |
33 | 36 | ||
34 | typedef enum r2dglp_states | 37 | typedef enum r2dglp_states |
@@ -66,9 +69,9 @@ typedef struct r2dglp_wait_state { | |||
66 | 69 | ||
67 | /** Data for whilst a donor **/ | 70 | /** Data for whilst a donor **/ |
68 | /* cross-linked with donee's r2dglp_donee_heap_node_t */ | 71 | /* cross-linked with donee's r2dglp_donee_heap_node_t */ |
69 | r2dglp_donee_heap_node_t *donee_info; | 72 | r2dglp_donee_heap_node_t* donee_info; |
70 | struct nested_info prio_donation; | 73 | struct nested_info prio_donation; |
71 | struct binheap_node node; | 74 | sbinheap_node_t snode; |
72 | } r2dglp_wait_state_t; | 75 | } r2dglp_wait_state_t; |
73 | 76 | ||
74 | /* struct for FIFO mutex with priority inheritance */ | 77 | /* struct for FIFO mutex with priority inheritance */ |
@@ -110,12 +113,11 @@ struct r2dglp_semaphore | |||
110 | unsigned int max_in_fifos; | 113 | unsigned int max_in_fifos; |
111 | unsigned int nr_in_fifos; | 114 | unsigned int nr_in_fifos; |
112 | 115 | ||
113 | struct binheap top_m; /* min heap, base prio */ | 116 | struct sbinheap top_m; /* min heap, base prio */ |
114 | unsigned int top_m_size; /* number of nodes in top_m */ | ||
115 | 117 | ||
116 | struct binheap not_top_m; /* max heap, ordered by base priority */ | 118 | struct binheap not_top_m; /* max heap, ordered by base priority */ |
117 | 119 | ||
118 | struct binheap donees; /* min-heap, ordered by base priority */ | 120 | struct sbinheap donees; /* min-heap, ordered by base priority */ |
119 | 121 | ||
120 | /* cached value - pointer to shortest fifo queue */ | 122 | /* cached value - pointer to shortest fifo queue */ |
121 | struct fifo_queue *shortest_fifo_queue; | 123 | struct fifo_queue *shortest_fifo_queue; |
@@ -123,7 +125,7 @@ struct r2dglp_semaphore | |||
123 | /* data structures for holding requests */ | 125 | /* data structures for holding requests */ |
124 | struct fifo_queue *fifo_queues; /* array nr_replicas in length */ | 126 | struct fifo_queue *fifo_queues; /* array nr_replicas in length */ |
125 | struct binheap priority_queue; /* max-heap, ordered by base priority */ | 127 | struct binheap priority_queue; /* max-heap, ordered by base priority */ |
126 | struct binheap donors; /* max-heap, ordered by base priority */ | 128 | struct sbinheap donors; /* max-heap, ordered by base priority */ |
127 | 129 | ||
128 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 130 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
129 | struct r2dglp_affinity *aff_obs; /* pointer to affinity observer */ | 131 | struct r2dglp_affinity *aff_obs; /* pointer to affinity observer */ |
diff --git a/litmus/r2dglp_lock.c b/litmus/r2dglp_lock.c index e37fafb8c8cd..21545a4a42d2 100644 --- a/litmus/r2dglp_lock.c +++ b/litmus/r2dglp_lock.c | |||
@@ -28,8 +28,8 @@ int r2dglp_max_heap_base_priority_order(const struct binheap_node *a, | |||
28 | return litmus->__compare(d_a->task, BASE, d_b->task, BASE); | 28 | return litmus->__compare(d_a->task, BASE, d_b->task, BASE); |
29 | } | 29 | } |
30 | 30 | ||
31 | int r2dglp_min_heap_base_priority_order(const struct binheap_node *a, | 31 | int r2dglp_min_heap_base_priority_order(const struct sbinheap_node *a, |
32 | const struct binheap_node *b) | 32 | const struct sbinheap_node *b) |
33 | { | 33 | { |
34 | const r2dglp_heap_node_t *d_a = binheap_entry(a, r2dglp_heap_node_t, node); | 34 | const r2dglp_heap_node_t *d_a = binheap_entry(a, r2dglp_heap_node_t, node); |
35 | const r2dglp_heap_node_t *d_b = binheap_entry(b, r2dglp_heap_node_t, node); | 35 | const r2dglp_heap_node_t *d_b = binheap_entry(b, r2dglp_heap_node_t, node); |
@@ -37,18 +37,18 @@ int r2dglp_min_heap_base_priority_order(const struct binheap_node *a, | |||
37 | return litmus->__compare(d_b->task, BASE, d_a->task, BASE); | 37 | return litmus->__compare(d_b->task, BASE, d_a->task, BASE); |
38 | } | 38 | } |
39 | 39 | ||
40 | int r2dglp_donor_max_heap_base_priority_order(const struct binheap_node *a, | 40 | int r2dglp_donor_max_heap_base_priority_order(const struct sbinheap_node *a, |
41 | const struct binheap_node *b) | 41 | const struct sbinheap_node *b) |
42 | { | 42 | { |
43 | const r2dglp_wait_state_t *d_a = binheap_entry(a, r2dglp_wait_state_t, node); | 43 | const r2dglp_wait_state_t *d_a = binheap_entry(a, r2dglp_wait_state_t, node); |
44 | const r2dglp_wait_state_t *d_b = binheap_entry(b, r2dglp_wait_state_t, node); | 44 | const r2dglp_wait_state_t *d_b = binheap_entry(b, r2dglp_wait_state_t, node); |
45 | 45 | ||
46 | return litmus->__compare(d_a->task, BASE, d_b->task, BASE); | 46 | return litmus->__compare(d_a->task, BASE, d_b->task, BASE); |
47 | } | 47 | } |
48 | 48 | ||
49 | 49 | ||
50 | int r2dglp_min_heap_donee_order(const struct binheap_node *a, | 50 | int r2dglp_min_heap_donee_order(const struct sbinheap_node *a, |
51 | const struct binheap_node *b) | 51 | const struct sbinheap_node *b) |
52 | { | 52 | { |
53 | const struct task_struct *prio_a; | 53 | const struct task_struct *prio_a; |
54 | const struct task_struct *prio_b; | 54 | const struct task_struct *prio_b; |
@@ -146,7 +146,7 @@ static struct fifo_queue* r2dglp_find_shortest(struct r2dglp_semaphore *sem, | |||
146 | 146 | ||
147 | static inline struct task_struct* r2dglp_mth_highest(struct r2dglp_semaphore *sem) | 147 | static inline struct task_struct* r2dglp_mth_highest(struct r2dglp_semaphore *sem) |
148 | { | 148 | { |
149 | return binheap_top_entry(&sem->top_m, r2dglp_heap_node_t, node)->task; | 149 | return sbinheap_top_entry(&sem->top_m, r2dglp_heap_node_t, node)->task; |
150 | } | 150 | } |
151 | 151 | ||
152 | static void r2dglp_add_global_list(struct r2dglp_semaphore *sem, | 152 | static void r2dglp_add_global_list(struct r2dglp_semaphore *sem, |
@@ -154,33 +154,33 @@ static void r2dglp_add_global_list(struct r2dglp_semaphore *sem, | |||
154 | r2dglp_heap_node_t *node) | 154 | r2dglp_heap_node_t *node) |
155 | { | 155 | { |
156 | node->task = t; | 156 | node->task = t; |
157 | INIT_BINHEAP_NODE(&node->node); | 157 | INIT_SBINHEAP_NODE(&node->snode); |
158 | INIT_BINHEAP_NODE(&node->dnode); | ||
158 | 159 | ||
159 | if(sem->top_m_size < sem->max_in_fifos) { | 160 | if(sem->top_m.size < sem->top_m.max_size) { |
160 | TRACE_CUR("Trivially adding %s/%d to top-m global list.\n", | 161 | TRACE_CUR("Trivially adding %s/%d to top-m global list.\n", |
161 | t->comm, t->pid); | 162 | t->comm, t->pid); |
162 | binheap_add(&node->node, &sem->top_m, r2dglp_heap_node_t, node); | 163 | sbinheap_add(&node->snode, &sem->top_m, r2dglp_heap_node_t, snode); |
163 | ++(sem->top_m_size); | ||
164 | } | 164 | } |
165 | else if(litmus->__compare(t, BASE, r2dglp_mth_highest(sem), BASE)) { | 165 | else if(litmus->__compare(t, BASE, r2dglp_mth_highest(sem), BASE)) { |
166 | r2dglp_heap_node_t *evicted = | 166 | r2dglp_heap_node_t *evicted = |
167 | binheap_top_entry(&sem->top_m, r2dglp_heap_node_t, node); | 167 | sbinheap_top_entry(&sem->top_m, r2dglp_heap_node_t, snode); |
168 | 168 | ||
169 | TRACE_CUR("Adding %s/%d to top-m and evicting %s/%d.\n", | 169 | TRACE_CUR("Adding %s/%d to top-m and evicting %s/%d.\n", |
170 | t->comm, t->pid, | 170 | t->comm, t->pid, |
171 | evicted->task->comm, evicted->task->pid); | 171 | evicted->task->comm, evicted->task->pid); |
172 | 172 | ||
173 | binheap_delete_root(&sem->top_m, r2dglp_heap_node_t, node); | 173 | sbinheap_delete_root(&sem->top_m, r2dglp_heap_node_t, snode); |
174 | INIT_BINHEAP_NODE(&evicted->node); | 174 | INIT_SBINHEAP_NODE(&evicted->snode); |
175 | binheap_add(&evicted->node, &sem->not_top_m, r2dglp_heap_node_t, node); | ||
176 | 175 | ||
177 | binheap_add(&node->node, &sem->top_m, r2dglp_heap_node_t, node); | 176 | binheap_add(&evicted->dnode, &sem->not_top_m, r2dglp_heap_node_t, dnode); |
177 | sbinheap_add(&node->snode, &sem->top_m, r2dglp_heap_node_t, snode); | ||
178 | } | 178 | } |
179 | else { | 179 | else { |
180 | TRACE_CUR("Trivially adding %s/%d to not-top-m global list.\n", | 180 | TRACE_CUR("Trivially adding %s/%d to not-top-m global list.\n", |
181 | t->comm, t->pid); | 181 | t->comm, t->pid); |
182 | 182 | ||
183 | binheap_add(&node->node, &sem->not_top_m, r2dglp_heap_node_t, node); | 183 | binheap_add(&node->dnode, &sem->not_top_m, r2dglp_heap_node_t, dnode); |
184 | } | 184 | } |
185 | } | 185 | } |
186 | 186 | ||
@@ -189,36 +189,37 @@ static void r2dglp_del_global_list(struct r2dglp_semaphore *sem, | |||
189 | struct task_struct *t, | 189 | struct task_struct *t, |
190 | r2dglp_heap_node_t *node) | 190 | r2dglp_heap_node_t *node) |
191 | { | 191 | { |
192 | BUG_ON(!binheap_is_in_heap(&node->node)); | 192 | BUG_ON(!(sbinheap_is_in_heap(&node->snode) || binheap_is_in_heap(&node->dnode))); |
193 | 193 | ||
194 | TRACE_CUR("Removing %s/%d from global list.\n", t->comm, t->pid); | 194 | TRACE_CUR("Removing %s/%d from global list.\n", t->comm, t->pid); |
195 | 195 | ||
196 | if(binheap_is_in_this_heap(&node->node, &sem->top_m)) { | 196 | if(sbinheap_is_in_this_heap(&node->snode, &sem->top_m)) { |
197 | TRACE_CUR("%s/%d is in top-m\n", t->comm, t->pid); | 197 | TRACE_CUR("%s/%d is in top-m\n", t->comm, t->pid); |
198 | 198 | ||
199 | binheap_delete(&node->node, &sem->top_m); | 199 | sbinheap_delete(&node->snode, &sem->top_m); |
200 | INIT_SBINHEAP_NODE(&node->snode); | ||
200 | 201 | ||
201 | if(!binheap_empty(&sem->not_top_m)) { | 202 | if(!binheap_empty(&sem->not_top_m)) { |
202 | r2dglp_heap_node_t *promoted = | 203 | r2dglp_heap_node_t *promoted = |
203 | binheap_top_entry(&sem->not_top_m, r2dglp_heap_node_t, node); | 204 | binheap_top_entry(&sem->not_top_m, r2dglp_heap_node_t, dnode); |
204 | 205 | ||
205 | TRACE_CUR("Promoting %s/%d to top-m\n", | 206 | TRACE_CUR("Promoting %s/%d to top-m\n", |
206 | promoted->task->comm, promoted->task->pid); | 207 | promoted->task->comm, promoted->task->pid); |
207 | 208 | ||
208 | binheap_delete_root(&sem->not_top_m, r2dglp_heap_node_t, node); | 209 | binheap_delete_root(&sem->not_top_m, r2dglp_heap_node_t, dnode); |
209 | INIT_BINHEAP_NODE(&promoted->node); | 210 | INIT_BINHEAP_NODE(&promoted->dnode); |
210 | 211 | ||
211 | binheap_add(&promoted->node, &sem->top_m, r2dglp_heap_node_t, node); | 212 | sbinheap_add(&promoted->snode, &sem->top_m, r2dglp_heap_node_t, snode); |
212 | } | 213 | } |
213 | else { | 214 | else { |
214 | TRACE_CUR("No one to promote to top-m.\n"); | 215 | TRACE_CUR("No one to promote to top-m.\n"); |
215 | --(sem->top_m_size); | ||
216 | } | 216 | } |
217 | } | 217 | } |
218 | else { | 218 | else { |
219 | TRACE_CUR("%s/%d is in not-top-m\n", t->comm, t->pid); | 219 | TRACE_CUR("%s/%d is in not-top-m\n", t->comm, t->pid); |
220 | 220 | ||
221 | binheap_delete(&node->node, &sem->not_top_m); | 221 | binheap_delete(&node->dnode, &sem->not_top_m); |
222 | INIT_BINHEAP_NODE(&node->dnode); | ||
222 | } | 223 | } |
223 | } | 224 | } |
224 | 225 | ||
@@ -231,9 +232,9 @@ static void r2dglp_add_donees(struct r2dglp_semaphore *sem, | |||
231 | node->task = t; | 232 | node->task = t; |
232 | node->donor_info = NULL; | 233 | node->donor_info = NULL; |
233 | node->fq = fq; | 234 | node->fq = fq; |
234 | INIT_BINHEAP_NODE(&node->node); | 235 | INIT_SBINHEAP_NODE(&node->snode); |
235 | 236 | ||
236 | binheap_add(&node->node, &sem->donees, r2dglp_donee_heap_node_t, node); | 237 | sbinheap_add(&node->snode, &sem->donees, r2dglp_donee_heap_node_t, snode); |
237 | } | 238 | } |
238 | 239 | ||
239 | 240 | ||
@@ -273,7 +274,7 @@ static void r2dglp_refresh_owners_prio_increase(struct task_struct *t, | |||
273 | fq->nest.hp_waiter_eff_prio = effective_priority(fq->hp_waiter); | 274 | fq->nest.hp_waiter_eff_prio = effective_priority(fq->hp_waiter); |
274 | 275 | ||
275 | binheap_decrease(&fq->nest.hp_binheap_node, | 276 | binheap_decrease(&fq->nest.hp_binheap_node, |
276 | &tsk_rt(owner)->hp_blocked_tasks); | 277 | &tsk_rt(owner)->hp_blocked_tasks); |
277 | new_max_eff_prio = top_priority(&tsk_rt(owner)->hp_blocked_tasks); | 278 | new_max_eff_prio = top_priority(&tsk_rt(owner)->hp_blocked_tasks); |
278 | 279 | ||
279 | if(new_max_eff_prio != old_max_eff_prio) { | 280 | if(new_max_eff_prio != old_max_eff_prio) { |
@@ -414,15 +415,28 @@ static void r2dglp_remove_donation_from_owner(struct binheap_node *n, | |||
414 | struct task_struct *new_max_eff_prio; | 415 | struct task_struct *new_max_eff_prio; |
415 | 416 | ||
416 | BUG_ON(!owner); | 417 | BUG_ON(!owner); |
418 | BUG_ON(!binheap_is_in_heap(n)); | ||
417 | 419 | ||
418 | raw_spin_lock(&tsk_rt(owner)->hp_blocked_tasks_lock); | 420 | raw_spin_lock(&tsk_rt(owner)->hp_blocked_tasks_lock); |
419 | 421 | ||
420 | old_max_eff_prio = top_priority(&tsk_rt(owner)->hp_blocked_tasks); | 422 | old_max_eff_prio = top_priority(&tsk_rt(owner)->hp_blocked_tasks); |
421 | 423 | ||
424 | TRACE_CUR("Old effective priority: %s/%d\n", | ||
425 | (old_max_eff_prio) ? | ||
426 | old_max_eff_prio->comm : "null", | ||
427 | (old_max_eff_prio) ? | ||
428 | old_max_eff_prio->pid : 0); | ||
429 | |||
422 | binheap_delete(n, &tsk_rt(owner)->hp_blocked_tasks); | 430 | binheap_delete(n, &tsk_rt(owner)->hp_blocked_tasks); |
423 | 431 | ||
424 | new_max_eff_prio = top_priority(&tsk_rt(owner)->hp_blocked_tasks); | 432 | new_max_eff_prio = top_priority(&tsk_rt(owner)->hp_blocked_tasks); |
425 | 433 | ||
434 | TRACE_CUR("New effective priority: %s/%d\n", | ||
435 | (new_max_eff_prio) ? | ||
436 | new_max_eff_prio->comm : "null", | ||
437 | (new_max_eff_prio) ? | ||
438 | new_max_eff_prio->pid : 0); | ||
439 | |||
426 | if((old_max_eff_prio != new_max_eff_prio) && | 440 | if((old_max_eff_prio != new_max_eff_prio) && |
427 | (effective_priority(owner) == old_max_eff_prio)) | 441 | (effective_priority(owner) == old_max_eff_prio)) |
428 | { | 442 | { |
@@ -554,7 +568,8 @@ static void __r2dglp_enqueue_on_fq(struct r2dglp_semaphore *sem, | |||
554 | 568 | ||
555 | /* update global list. */ | 569 | /* update global list. */ |
556 | if(likely(global_heap_node)) { | 570 | if(likely(global_heap_node)) { |
557 | if(binheap_is_in_heap(&global_heap_node->node)) { | 571 | if(sbinheap_is_in_heap(&global_heap_node->snode) || |
572 | binheap_is_in_heap(&global_heap_node->dnode)) { | ||
558 | WARN_ON(1); | 573 | WARN_ON(1); |
559 | r2dglp_del_global_list(sem, t, global_heap_node); | 574 | r2dglp_del_global_list(sem, t, global_heap_node); |
560 | } | 575 | } |
@@ -590,8 +605,9 @@ static void r2dglp_enqueue_on_fq(struct r2dglp_semaphore *sem, | |||
590 | "and wait.\n", | 605 | "and wait.\n", |
591 | r2dglp_get_idx(sem, fq)); | 606 | r2dglp_get_idx(sem, fq)); |
592 | 607 | ||
593 | INIT_BINHEAP_NODE(&wait->global_heap_node.node); | 608 | INIT_SBINHEAP_NODE(&wait->global_heap_node.snode); |
594 | INIT_BINHEAP_NODE(&wait->donee_heap_node.node); | 609 | INIT_BINHEAP_NODE(&wait->global_heap_node.dnode); |
610 | INIT_SBINHEAP_NODE(&wait->donee_heap_node.snode); | ||
595 | 611 | ||
596 | __r2dglp_enqueue_on_fq(sem, fq, wait, | 612 | __r2dglp_enqueue_on_fq(sem, fq, wait, |
597 | &wait->global_heap_node, &wait->donee_heap_node); | 613 | &wait->global_heap_node, &wait->donee_heap_node); |
@@ -608,8 +624,8 @@ static void __r2dglp_enqueue_on_pq(struct r2dglp_semaphore *sem, | |||
608 | 624 | ||
609 | wait->pq_node.task = wait->task; /* copy over task (little redundant...) */ | 625 | wait->pq_node.task = wait->task; /* copy over task (little redundant...) */ |
610 | 626 | ||
611 | binheap_add(&wait->pq_node.node, &sem->priority_queue, | 627 | binheap_add(&wait->pq_node.dnode, &sem->priority_queue, |
612 | r2dglp_heap_node_t, node); | 628 | r2dglp_heap_node_t, dnode); |
613 | 629 | ||
614 | wait->cur_q = R2DGLP_PQ; | 630 | wait->cur_q = R2DGLP_PQ; |
615 | } | 631 | } |
@@ -617,9 +633,10 @@ static void __r2dglp_enqueue_on_pq(struct r2dglp_semaphore *sem, | |||
617 | static void r2dglp_enqueue_on_pq(struct r2dglp_semaphore *sem, | 633 | static void r2dglp_enqueue_on_pq(struct r2dglp_semaphore *sem, |
618 | r2dglp_wait_state_t *wait) | 634 | r2dglp_wait_state_t *wait) |
619 | { | 635 | { |
620 | INIT_BINHEAP_NODE(&wait->global_heap_node.node); | 636 | INIT_SBINHEAP_NODE(&wait->global_heap_node.snode); |
621 | INIT_BINHEAP_NODE(&wait->donee_heap_node.node); | 637 | INIT_BINHEAP_NODE(&wait->global_heap_node.dnode); |
622 | INIT_BINHEAP_NODE(&wait->pq_node.node); | 638 | INIT_SBINHEAP_NODE(&wait->donee_heap_node.snode); |
639 | INIT_BINHEAP_NODE(&wait->pq_node.dnode); | ||
623 | 640 | ||
624 | __r2dglp_enqueue_on_pq(sem, wait); | 641 | __r2dglp_enqueue_on_pq(sem, wait); |
625 | } | 642 | } |
@@ -636,10 +653,11 @@ static void r2dglp_enqueue_on_donor(struct r2dglp_semaphore *sem, | |||
636 | struct task_struct *new_max_eff_prio; | 653 | struct task_struct *new_max_eff_prio; |
637 | struct task_struct *new_prio = NULL; | 654 | struct task_struct *new_prio = NULL; |
638 | 655 | ||
639 | INIT_BINHEAP_NODE(&wait->global_heap_node.node); | 656 | INIT_SBINHEAP_NODE(&wait->global_heap_node.snode); |
640 | INIT_BINHEAP_NODE(&wait->donee_heap_node.node); | 657 | INIT_BINHEAP_NODE(&wait->global_heap_node.dnode); |
641 | INIT_BINHEAP_NODE(&wait->pq_node.node); | 658 | INIT_SBINHEAP_NODE(&wait->donee_heap_node.snode); |
642 | INIT_BINHEAP_NODE(&wait->node); | 659 | INIT_BINHEAP_NODE(&wait->pq_node.dnode); |
660 | INIT_SBINHEAP_NODE(&wait->snode); | ||
643 | 661 | ||
644 | /* Add donor to the global list. */ | 662 | /* Add donor to the global list. */ |
645 | r2dglp_add_global_list(sem, t, &wait->global_heap_node); | 663 | r2dglp_add_global_list(sem, t, &wait->global_heap_node); |
@@ -648,25 +666,25 @@ static void r2dglp_enqueue_on_donor(struct r2dglp_semaphore *sem, | |||
648 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 666 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
649 | donee_node = (sem->aff_obs) ? | 667 | donee_node = (sem->aff_obs) ? |
650 | sem->aff_obs->ops->advise_donee_selection(sem->aff_obs, t) : | 668 | sem->aff_obs->ops->advise_donee_selection(sem->aff_obs, t) : |
651 | binheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, node); | 669 | sbinheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, snode); |
652 | #else | 670 | #else |
653 | donee_node = binheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, node); | 671 | donee_node = sbinheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, snode); |
654 | #endif | 672 | #endif |
655 | 673 | ||
656 | donee = donee_node->task; | 674 | donee = donee_node->task; |
657 | 675 | ||
658 | TRACE_TASK(t, "Donee selected: %s/%d\n", donee->comm, donee->pid); | 676 | TRACE_TASK(t, "Donee selected: %s/%d\n", donee->comm, donee->pid); |
659 | 677 | ||
660 | TRACE_CUR("Temporarily removing %s/%d to donee list.\n", | 678 | TRACE_CUR("Temporarily removing %s/%d from donee list.\n", |
661 | donee->comm, donee->pid); | 679 | donee->comm, donee->pid); |
662 | 680 | ||
663 | /* Remove from donee list */ | 681 | /* Remove from donee list */ |
664 | binheap_delete(&donee_node->node, &sem->donees); | 682 | sbinheap_delete(&donee_node->snode, &sem->donees); |
665 | 683 | ||
666 | wait->donee_info = donee_node; | 684 | wait->donee_info = donee_node; |
667 | 685 | ||
668 | /* Add t to donor heap. */ | 686 | /* Add t to donor heap. */ |
669 | binheap_add(&wait->node, &sem->donors, r2dglp_wait_state_t, node); | 687 | sbinheap_add(&wait->snode, &sem->donors, r2dglp_wait_state_t, snode); |
670 | 688 | ||
671 | /* Now adjust the donee's priority. */ | 689 | /* Now adjust the donee's priority. */ |
672 | 690 | ||
@@ -686,7 +704,7 @@ static void r2dglp_enqueue_on_donor(struct r2dglp_semaphore *sem, | |||
686 | "Moving old donor to PQ.\n", | 704 | "Moving old donor to PQ.\n", |
687 | donee->comm, donee->pid, old_donor->comm, old_donor->pid); | 705 | donee->comm, donee->pid, old_donor->comm, old_donor->pid); |
688 | 706 | ||
689 | binheap_delete(&old_wait->node, &sem->donors); | 707 | sbinheap_delete(&old_wait->snode, &sem->donors); |
690 | 708 | ||
691 | /* Remove donation from donee's inheritance heap. */ | 709 | /* Remove donation from donee's inheritance heap. */ |
692 | binheap_delete(&old_wait->prio_donation.hp_binheap_node, | 710 | binheap_delete(&old_wait->prio_donation.hp_binheap_node, |
@@ -704,8 +722,8 @@ static void r2dglp_enqueue_on_donor(struct r2dglp_semaphore *sem, | |||
704 | TRACE_CUR("Adding %s/%d back to donee list.\n", donee->comm, donee->pid); | 722 | TRACE_CUR("Adding %s/%d back to donee list.\n", donee->comm, donee->pid); |
705 | 723 | ||
706 | donee_node->donor_info = wait; | 724 | donee_node->donor_info = wait; |
707 | INIT_BINHEAP_NODE(&donee_node->node); | 725 | INIT_SBINHEAP_NODE(&donee_node->snode); |
708 | binheap_add(&donee_node->node, &sem->donees, r2dglp_donee_heap_node_t, node); | 726 | sbinheap_add(&donee_node->snode, &sem->donees, r2dglp_donee_heap_node_t, snode); |
709 | 727 | ||
710 | /* Add an inheritance/donation to the donee's inheritance heap. */ | 728 | /* Add an inheritance/donation to the donee's inheritance heap. */ |
711 | wait->prio_donation.lock = (struct litmus_lock*)sem; | 729 | wait->prio_donation.lock = (struct litmus_lock*)sem; |
@@ -891,7 +909,7 @@ static void __drop_from_donor(struct r2dglp_semaphore *sem, | |||
891 | 909 | ||
892 | TRACE_TASK(wait->task, "is being dropped from donor heap.\n"); | 910 | TRACE_TASK(wait->task, "is being dropped from donor heap.\n"); |
893 | 911 | ||
894 | binheap_delete(&wait->node, &sem->donors); | 912 | sbinheap_delete(&wait->snode, &sem->donors); |
895 | wait->cur_q = R2DGLP_INVL; | 913 | wait->cur_q = R2DGLP_INVL; |
896 | } | 914 | } |
897 | 915 | ||
@@ -923,7 +941,7 @@ static void __drop_from_pq(struct r2dglp_semaphore *sem, | |||
923 | 941 | ||
924 | TRACE_TASK(wait->task, "is being dropped from the PQ.\n"); | 942 | TRACE_TASK(wait->task, "is being dropped from the PQ.\n"); |
925 | 943 | ||
926 | binheap_delete(&wait->pq_node.node, &sem->priority_queue); | 944 | binheap_delete(&wait->pq_node.dnode, &sem->priority_queue); |
927 | wait->cur_q = R2DGLP_INVL; | 945 | wait->cur_q = R2DGLP_INVL; |
928 | } | 946 | } |
929 | 947 | ||
@@ -1080,7 +1098,7 @@ static void r2dglp_migrate_fq_to_owner_heap_nodes(struct r2dglp_semaphore *sem, | |||
1080 | fq->global_heap_node = old_wait->global_heap_node; /* copy */ | 1098 | fq->global_heap_node = old_wait->global_heap_node; /* copy */ |
1081 | r2dglp_add_global_list(sem, t, &fq->global_heap_node); /* re-add */ | 1099 | r2dglp_add_global_list(sem, t, &fq->global_heap_node); /* re-add */ |
1082 | 1100 | ||
1083 | binheap_delete(&old_wait->donee_heap_node.node, &sem->donees); /* remove */ | 1101 | sbinheap_delete(&old_wait->donee_heap_node.snode, &sem->donees); /* remove */ |
1084 | fq->donee_heap_node = old_wait->donee_heap_node; /* copy */ | 1102 | fq->donee_heap_node = old_wait->donee_heap_node; /* copy */ |
1085 | 1103 | ||
1086 | if(fq->donee_heap_node.donor_info) { | 1104 | if(fq->donee_heap_node.donor_info) { |
@@ -1091,9 +1109,9 @@ static void r2dglp_migrate_fq_to_owner_heap_nodes(struct r2dglp_semaphore *sem, | |||
1091 | 1109 | ||
1092 | fq->donee_heap_node.donor_info->donee_info = &fq->donee_heap_node; | 1110 | fq->donee_heap_node.donor_info->donee_info = &fq->donee_heap_node; |
1093 | } | 1111 | } |
1094 | INIT_BINHEAP_NODE(&fq->donee_heap_node.node); | 1112 | INIT_SBINHEAP_NODE(&fq->donee_heap_node.snode); |
1095 | binheap_add(&fq->donee_heap_node.node, &sem->donees, | 1113 | sbinheap_add(&fq->donee_heap_node.snode, &sem->donees, |
1096 | r2dglp_donee_heap_node_t, node); /* re-add */ | 1114 | r2dglp_donee_heap_node_t, snode); /* re-add */ |
1097 | } | 1115 | } |
1098 | 1116 | ||
1099 | 1117 | ||
@@ -1256,14 +1274,14 @@ void r2dglp_move_next_to_fq(struct r2dglp_semaphore *sem, | |||
1256 | if (always_terminate_donation) | 1274 | if (always_terminate_donation) |
1257 | other_donor_info = donor_info; | 1275 | other_donor_info = donor_info; |
1258 | } | 1276 | } |
1259 | else if(!binheap_empty(&sem->donors)) { /* No donor, move any donor to FQ */ | 1277 | else if(!sbinheap_empty(&sem->donors)) { /* No donor, move any donor to FQ */ |
1260 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 1278 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
1261 | other_donor_info = (sem->aff_obs) ? | 1279 | other_donor_info = (sem->aff_obs) ? |
1262 | sem->aff_obs->ops->advise_donor_to_fq(sem->aff_obs, fq) : | 1280 | sem->aff_obs->ops->advise_donor_to_fq(sem->aff_obs, fq) : |
1263 | binheap_top_entry(&sem->donors, r2dglp_wait_state_t, node); | 1281 | sbinheap_top_entry(&sem->donors, r2dglp_wait_state_t, snode); |
1264 | #else | 1282 | #else |
1265 | other_donor_info = | 1283 | other_donor_info = |
1266 | binheap_top_entry(&sem->donors, r2dglp_wait_state_t, node); | 1284 | sbinheap_top_entry(&sem->donors, r2dglp_wait_state_t, snode); |
1267 | #endif | 1285 | #endif |
1268 | 1286 | ||
1269 | new_on_fq = other_donor_info->task; | 1287 | new_on_fq = other_donor_info->task; |
@@ -1271,7 +1289,7 @@ void r2dglp_move_next_to_fq(struct r2dglp_semaphore *sem, | |||
1271 | 1289 | ||
1272 | /* update the donee's heap position. */ | 1290 | /* update the donee's heap position. */ |
1273 | other_donor_info->donee_info->donor_info = NULL; /* clear cross-link */ | 1291 | other_donor_info->donee_info->donor_info = NULL; /* clear cross-link */ |
1274 | binheap_decrease(&other_donor_info->donee_info->node, &sem->donees); | 1292 | sbinheap_decrease(&other_donor_info->donee_info->snode, &sem->donees); |
1275 | 1293 | ||
1276 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 1294 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
1277 | if(sem->aff_obs) { | 1295 | if(sem->aff_obs) { |
@@ -1396,8 +1414,9 @@ void r2dglp_move_next_to_fq(struct r2dglp_semaphore *sem, | |||
1396 | donee->comm, donee->pid, | 1414 | donee->comm, donee->pid, |
1397 | r2dglp_get_idx(sem, other_fq)); | 1415 | r2dglp_get_idx(sem, other_fq)); |
1398 | 1416 | ||
1399 | r2dglp_remove_donation_from_owner(&other_donor_info->prio_donation.hp_binheap_node, | 1417 | r2dglp_remove_donation_from_owner( |
1400 | other_fq, sem, *flags); | 1418 | &other_donor_info->prio_donation.hp_binheap_node, |
1419 | other_fq, sem, *flags); | ||
1401 | 1420 | ||
1402 | /* there should be no contention!!!! */ | 1421 | /* there should be no contention!!!! */ |
1403 | lock_fine_irqsave(&sem->lock, *flags); | 1422 | lock_fine_irqsave(&sem->lock, *flags); |
@@ -1408,7 +1427,7 @@ void r2dglp_move_next_to_fq(struct r2dglp_semaphore *sem, | |||
1408 | r2dglp_get_idx(sem, other_fq)); | 1427 | r2dglp_get_idx(sem, other_fq)); |
1409 | 1428 | ||
1410 | r2dglp_remove_donation_from_fq_waiter(donee, | 1429 | r2dglp_remove_donation_from_fq_waiter(donee, |
1411 | &other_donor_info->prio_donation.hp_binheap_node); | 1430 | &other_donor_info->prio_donation.hp_binheap_node); |
1412 | if(donee == other_fq->hp_waiter) { | 1431 | if(donee == other_fq->hp_waiter) { |
1413 | TRACE_TASK(t, "Donee %s/%d was an hp_waiter of fq %d. " | 1432 | TRACE_TASK(t, "Donee %s/%d was an hp_waiter of fq %d. " |
1414 | "Rechecking hp_waiter.\n", | 1433 | "Rechecking hp_waiter.\n", |
@@ -1490,8 +1509,10 @@ int r2dglp_unlock(struct litmus_lock* l) | |||
1490 | TRACE_TASK(t, "Freeing replica %d.\n", r2dglp_get_idx(sem, fq)); | 1509 | TRACE_TASK(t, "Freeing replica %d.\n", r2dglp_get_idx(sem, fq)); |
1491 | 1510 | ||
1492 | /* Remove 't' from the heaps, but data in nodes will still be good. */ | 1511 | /* Remove 't' from the heaps, but data in nodes will still be good. */ |
1493 | r2dglp_del_global_list(sem, t, &fq->global_heap_node); | 1512 | if(likely(!fq->is_vunlocked)) { |
1494 | binheap_delete(&fq->donee_heap_node.node, &sem->donees); | 1513 | r2dglp_del_global_list(sem, t, &fq->global_heap_node); |
1514 | sbinheap_delete(&fq->donee_heap_node.snode, &sem->donees); | ||
1515 | } | ||
1495 | 1516 | ||
1496 | fq->owner = NULL; /* no longer owned!! */ | 1517 | fq->owner = NULL; /* no longer owned!! */ |
1497 | --(fq->count); | 1518 | --(fq->count); |
@@ -1519,12 +1540,10 @@ int r2dglp_unlock(struct litmus_lock* l) | |||
1519 | raw_spin_lock(&tsk_rt(t)->hp_blocked_tasks_lock); | 1540 | raw_spin_lock(&tsk_rt(t)->hp_blocked_tasks_lock); |
1520 | { | 1541 | { |
1521 | int count = 0; | 1542 | int count = 0; |
1522 | |||
1523 | TRACE_TASK(t, "discarding inheritance because R2DGLP is outermost\n"); | 1543 | TRACE_TASK(t, "discarding inheritance because R2DGLP is outermost\n"); |
1524 | 1544 | while (!binheap_empty(&tsk_rt(t)->hp_blocked_tasks)) { | |
1525 | while(!binheap_empty(&tsk_rt(t)->hp_blocked_tasks)) { | ||
1526 | binheap_delete_root(&tsk_rt(t)->hp_blocked_tasks, | 1545 | binheap_delete_root(&tsk_rt(t)->hp_blocked_tasks, |
1527 | struct nested_info, hp_binheap_node); | 1546 | struct nested_info, hp_binheap_node); |
1528 | ++count; | 1547 | ++count; |
1529 | } | 1548 | } |
1530 | 1549 | ||
@@ -1535,7 +1554,7 @@ int r2dglp_unlock(struct litmus_lock* l) | |||
1535 | 1554 | ||
1536 | if (likely(!fq->is_vunlocked)) { | 1555 | if (likely(!fq->is_vunlocked)) { |
1537 | /* Move the next request into the FQ and update heaps as needed. | 1556 | /* Move the next request into the FQ and update heaps as needed. |
1538 | Skip this step we already did this during the virtual unlock. */ | 1557 | Skip this step we if already did this during the virtual unlock. */ |
1539 | r2dglp_move_next_to_fq(sem, fq, t, &fq->donee_heap_node, &flags, | 1558 | r2dglp_move_next_to_fq(sem, fq, t, &fq->donee_heap_node, &flags, |
1540 | ALLOW_STEALING, !ALWAYS_TERMINATE_DONATION); | 1559 | ALLOW_STEALING, !ALWAYS_TERMINATE_DONATION); |
1541 | } | 1560 | } |
@@ -1576,14 +1595,16 @@ void r2dglp_abort_request(struct r2dglp_semaphore *sem, struct task_struct *t, | |||
1576 | switch(wait->cur_q) | 1595 | switch(wait->cur_q) |
1577 | { | 1596 | { |
1578 | case R2DGLP_PQ: | 1597 | case R2DGLP_PQ: |
1598 | TRACE_TASK(t, "Aborting request while on PQ.\n"); | ||
1579 | /* No one inherits from waiters in PQ. Just drop the request. */ | 1599 | /* No one inherits from waiters in PQ. Just drop the request. */ |
1580 | __drop_from_pq(sem, wait); | 1600 | __drop_from_pq(sem, wait); |
1581 | break; | 1601 | break; |
1582 | 1602 | ||
1583 | 1603 | ||
1584 | case R2DGLP_FQ: | 1604 | case R2DGLP_FQ: |
1605 | TRACE_TASK(t, "Aborting request while on FQ.\n"); | ||
1585 | r2dglp_del_global_list(sem, t, &wait->global_heap_node); | 1606 | r2dglp_del_global_list(sem, t, &wait->global_heap_node); |
1586 | binheap_delete(&wait->donee_heap_node.node, &sem->donees); | 1607 | sbinheap_delete(&wait->donee_heap_node.snode, &sem->donees); |
1587 | 1608 | ||
1588 | /* remove the task from the FQ */ | 1609 | /* remove the task from the FQ */ |
1589 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 1610 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
@@ -1598,12 +1619,12 @@ void r2dglp_abort_request(struct r2dglp_semaphore *sem, struct task_struct *t, | |||
1598 | int count = 0; | 1619 | int count = 0; |
1599 | TRACE_TASK(t, "discarding inheritance because R2DGLP " | 1620 | TRACE_TASK(t, "discarding inheritance because R2DGLP " |
1600 | "is outermost\n"); | 1621 | "is outermost\n"); |
1601 | 1622 | while (!binheap_empty(&tsk_rt(t)->hp_blocked_tasks)) { | |
1602 | while(!binheap_empty(&tsk_rt(t)->hp_blocked_tasks)) { | ||
1603 | binheap_delete_root(&tsk_rt(t)->hp_blocked_tasks, | 1623 | binheap_delete_root(&tsk_rt(t)->hp_blocked_tasks, |
1604 | struct nested_info, hp_binheap_node); | 1624 | struct nested_info, hp_binheap_node); |
1605 | ++count; | 1625 | ++count; |
1606 | } | 1626 | } |
1627 | |||
1607 | if (count) | 1628 | if (count) |
1608 | litmus->decrease_prio(t, NULL, 0); | 1629 | litmus->decrease_prio(t, NULL, 0); |
1609 | } | 1630 | } |
@@ -1620,13 +1641,14 @@ void r2dglp_abort_request(struct r2dglp_semaphore *sem, struct task_struct *t, | |||
1620 | 1641 | ||
1621 | 1642 | ||
1622 | case R2DGLP_DONOR: | 1643 | case R2DGLP_DONOR: |
1644 | TRACE_TASK(t, "Aborting request while donor.\n"); | ||
1623 | r2dglp_del_global_list(sem, t, &wait->global_heap_node); | 1645 | r2dglp_del_global_list(sem, t, &wait->global_heap_node); |
1624 | __drop_from_donor(sem, wait); | 1646 | __drop_from_donor(sem, wait); |
1625 | 1647 | ||
1626 | /* update donee */ | 1648 | /* update donee */ |
1627 | donee_info = wait->donee_info; | 1649 | donee_info = wait->donee_info; |
1628 | donee_info->donor_info = NULL; // clear the cross-link | 1650 | donee_info->donor_info = NULL; // clear the cross-link |
1629 | binheap_decrease(&donee_info->node, &sem->donees); | 1651 | sbinheap_decrease(&donee_info->snode, &sem->donees); |
1630 | 1652 | ||
1631 | donee = donee_info->task; | 1653 | donee = donee_info->task; |
1632 | donee_fq = donee_info->fq; | 1654 | donee_fq = donee_info->fq; |
@@ -1635,8 +1657,9 @@ void r2dglp_abort_request(struct r2dglp_semaphore *sem, struct task_struct *t, | |||
1635 | donee->comm, donee->pid, | 1657 | donee->comm, donee->pid, |
1636 | r2dglp_get_idx(sem, donee_fq)); | 1658 | r2dglp_get_idx(sem, donee_fq)); |
1637 | /* unlocks sem->lock. reacquire it. */ | 1659 | /* unlocks sem->lock. reacquire it. */ |
1638 | r2dglp_remove_donation_from_owner(&wait->prio_donation.hp_binheap_node, | 1660 | r2dglp_remove_donation_from_owner( |
1639 | donee_fq, sem, flags); | 1661 | &wait->prio_donation.hp_binheap_node, |
1662 | donee_fq, sem, flags); | ||
1640 | /* there should be no contention!!!! */ | 1663 | /* there should be no contention!!!! */ |
1641 | lock_fine_irqsave(&sem->lock, flags); | 1664 | lock_fine_irqsave(&sem->lock, flags); |
1642 | } | 1665 | } |
@@ -1646,7 +1669,8 @@ void r2dglp_abort_request(struct r2dglp_semaphore *sem, struct task_struct *t, | |||
1646 | r2dglp_get_idx(sem, donee_fq)); | 1669 | r2dglp_get_idx(sem, donee_fq)); |
1647 | 1670 | ||
1648 | r2dglp_remove_donation_from_fq_waiter(donee, | 1671 | r2dglp_remove_donation_from_fq_waiter(donee, |
1649 | &wait->prio_donation.hp_binheap_node); | 1672 | &wait->prio_donation.hp_binheap_node); |
1673 | |||
1650 | if(donee == donee_fq->hp_waiter) { | 1674 | if(donee == donee_fq->hp_waiter) { |
1651 | TRACE_TASK(t, "Donee %s/%d was an hp_waiter of fq %d. " | 1675 | TRACE_TASK(t, "Donee %s/%d was an hp_waiter of fq %d. " |
1652 | "Rechecking hp_waiter.\n", | 1676 | "Rechecking hp_waiter.\n", |
@@ -1705,6 +1729,11 @@ void r2dglp_budget_exhausted(struct litmus_lock* l, struct task_struct* t) | |||
1705 | l->ident); | 1729 | l->ident); |
1706 | 1730 | ||
1707 | wait = (r2dglp_wait_state_t*)tsk_rt(t)->blocked_lock_data; | 1731 | wait = (r2dglp_wait_state_t*)tsk_rt(t)->blocked_lock_data; |
1732 | |||
1733 | /* re-init the wait state just to be safe */ | ||
1734 | memset(wait, 0, sizeof(*wait)); | ||
1735 | wait->task = t; | ||
1736 | |||
1708 | if(sem->nr_in_fifos < sem->max_in_fifos) { | 1737 | if(sem->nr_in_fifos < sem->max_in_fifos) { |
1709 | 1738 | ||
1710 | struct fifo_queue *fq; | 1739 | struct fifo_queue *fq; |
@@ -1764,7 +1793,7 @@ void r2dglp_virtual_unlock(struct litmus_lock* l, struct task_struct* t) | |||
1764 | struct fifo_queue *fq = r2dglp_get_queue(sem, t); | 1793 | struct fifo_queue *fq = r2dglp_get_queue(sem, t); |
1765 | unsigned long flags = 0, more_flags; | 1794 | unsigned long flags = 0, more_flags; |
1766 | 1795 | ||
1767 | TRACE_TASK(t, "virtual unlock!\n"); | 1796 | TRACE_TASK(t, "performing virtual unlock\n"); |
1768 | 1797 | ||
1769 | if (!fq) | 1798 | if (!fq) |
1770 | return; | 1799 | return; |
@@ -1782,6 +1811,23 @@ void r2dglp_virtual_unlock(struct litmus_lock* l, struct task_struct* t) | |||
1782 | goto out; | 1811 | goto out; |
1783 | } | 1812 | } |
1784 | 1813 | ||
1814 | /* 't' exits priority-tracking data structures, making it | ||
1815 | "invisible" to all priority inheritance mechanisms except | ||
1816 | for FQ-based inheritance. 't' can still transitively | ||
1817 | inherit priority from a donor. */ | ||
1818 | r2dglp_del_global_list(sem, t, &fq->global_heap_node); | ||
1819 | |||
1820 | #ifdef CONFIG_SCHED_DEBUG_TRACE | ||
1821 | if(fq->donee_heap_node.donor_info && | ||
1822 | fq->donee_heap_node.donor_info->task) { | ||
1823 | TRACE_TASK(t, "has a donor while vunlock: %s/%d\n", | ||
1824 | fq->donee_heap_node.donor_info->task->comm, | ||
1825 | fq->donee_heap_node.donor_info->task->pid); | ||
1826 | } | ||
1827 | #endif | ||
1828 | |||
1829 | sbinheap_delete(&fq->donee_heap_node.snode, &sem->donees); | ||
1830 | |||
1785 | /* Move a request from donor heap or PQ to fq. don't steal from | 1831 | /* Move a request from donor heap or PQ to fq. don't steal from |
1786 | * other FQs. Also, terminate donation relationship if we move | 1832 | * other FQs. Also, terminate donation relationship if we move |
1787 | * a donor to 't' to the FQ (we'll pick inheritance back up via | 1833 | * a donor to 't' to the FQ (we'll pick inheritance back up via |
@@ -1794,6 +1840,8 @@ void r2dglp_virtual_unlock(struct litmus_lock* l, struct task_struct* t) | |||
1794 | --(sem->nr_in_fifos); | 1840 | --(sem->nr_in_fifos); |
1795 | fq->is_vunlocked = 1; | 1841 | fq->is_vunlocked = 1; |
1796 | 1842 | ||
1843 | TRACE_TASK(t, "virtual unlock completed\n"); | ||
1844 | |||
1797 | out: | 1845 | out: |
1798 | unlock_fine_irqrestore(&sem->lock, flags); | 1846 | unlock_fine_irqrestore(&sem->lock, flags); |
1799 | raw_spin_unlock_irqrestore(&sem->real_lock, more_flags); | 1847 | raw_spin_unlock_irqrestore(&sem->real_lock, more_flags); |
@@ -1831,6 +1879,9 @@ void r2dglp_free(struct litmus_lock* l) | |||
1831 | { | 1879 | { |
1832 | struct r2dglp_semaphore *sem = r2dglp_from_lock(l); | 1880 | struct r2dglp_semaphore *sem = r2dglp_from_lock(l); |
1833 | 1881 | ||
1882 | kfree(sem->donors.buf); | ||
1883 | kfree(sem->donees.buf); | ||
1884 | kfree(sem->top_m.buf); | ||
1834 | kfree(sem->fifo_queues); | 1885 | kfree(sem->fifo_queues); |
1835 | kfree(sem); | 1886 | kfree(sem); |
1836 | } | 1887 | } |
@@ -1919,12 +1970,12 @@ struct litmus_lock* r2dglp_new(unsigned int m, | |||
1919 | q->is_vunlocked = 0; | 1970 | q->is_vunlocked = 0; |
1920 | 1971 | ||
1921 | q->global_heap_node.task = NULL; | 1972 | q->global_heap_node.task = NULL; |
1922 | INIT_BINHEAP_NODE(&q->global_heap_node.node); | 1973 | INIT_BINHEAP_NODE(&q->global_heap_node.dnode); |
1923 | 1974 | ||
1924 | q->donee_heap_node.task = NULL; | 1975 | q->donee_heap_node.task = NULL; |
1925 | q->donee_heap_node.donor_info = NULL; | 1976 | q->donee_heap_node.donor_info = NULL; |
1926 | q->donee_heap_node.fq = NULL; | 1977 | q->donee_heap_node.fq = NULL; |
1927 | INIT_BINHEAP_NODE(&q->donee_heap_node.node); | 1978 | INIT_SBINHEAP_NODE(&q->donee_heap_node.snode); |
1928 | 1979 | ||
1929 | q->nest.lock = (struct litmus_lock*)sem; | 1980 | q->nest.lock = (struct litmus_lock*)sem; |
1930 | q->nest.hp_waiter_eff_prio = NULL; | 1981 | q->nest.hp_waiter_eff_prio = NULL; |
@@ -1934,15 +1985,57 @@ struct litmus_lock* r2dglp_new(unsigned int m, | |||
1934 | 1985 | ||
1935 | sem->shortest_fifo_queue = &sem->fifo_queues[0]; | 1986 | sem->shortest_fifo_queue = &sem->fifo_queues[0]; |
1936 | 1987 | ||
1937 | sem->top_m_size = 0; | ||
1938 | |||
1939 | // init heaps | 1988 | // init heaps |
1940 | INIT_BINHEAP_HANDLE(&sem->top_m, r2dglp_min_heap_base_priority_order); | 1989 | |
1990 | /* heaps of bounded sizes */ | ||
1991 | |||
1992 | /* bounded by cluster size */ | ||
1993 | sem->top_m.compare = r2dglp_min_heap_base_priority_order; | ||
1994 | sem->top_m.max_size = m; | ||
1995 | sem->top_m.buf = kmalloc(m * sizeof(struct sbinheap_node), | ||
1996 | GFP_KERNEL); | ||
1997 | if(!sem->top_m.buf) | ||
1998 | { | ||
1999 | kfree(sem->fifo_queues); | ||
2000 | kfree(sem); | ||
2001 | return NULL; | ||
2002 | } | ||
2003 | INIT_SBINHEAP(&sem->top_m); | ||
2004 | |||
2005 | /* bounded by num FQ slots */ | ||
2006 | sem->donees.compare = r2dglp_min_heap_donee_order; | ||
2007 | sem->donees.max_size = sem->max_in_fifos; | ||
2008 | sem->donees.buf = kmalloc( | ||
2009 | sem->max_in_fifos * sizeof(struct sbinheap_node), | ||
2010 | GFP_KERNEL); | ||
2011 | if(!sem->donees.buf) | ||
2012 | { | ||
2013 | kfree(sem->top_m.buf); | ||
2014 | kfree(sem->fifo_queues); | ||
2015 | kfree(sem); | ||
2016 | return NULL; | ||
2017 | } | ||
2018 | INIT_SBINHEAP(&sem->donees); | ||
2019 | |||
2020 | /* bounded by cluster size */ | ||
2021 | sem->donors.compare = r2dglp_donor_max_heap_base_priority_order; | ||
2022 | sem->donors.max_size = m; /* bounded by cluster size */ | ||
2023 | sem->donors.buf = kmalloc(m * sizeof(struct sbinheap_node), | ||
2024 | GFP_KERNEL); | ||
2025 | if(!sem->donors.buf) | ||
2026 | { | ||
2027 | kfree(sem->donees.buf); | ||
2028 | kfree(sem->top_m.buf); | ||
2029 | kfree(sem->fifo_queues); | ||
2030 | kfree(sem); | ||
2031 | return NULL; | ||
2032 | } | ||
2033 | INIT_SBINHEAP(&sem->donors); | ||
2034 | |||
2035 | /* heaps of unbounded size */ | ||
1941 | INIT_BINHEAP_HANDLE(&sem->not_top_m, r2dglp_max_heap_base_priority_order); | 2036 | INIT_BINHEAP_HANDLE(&sem->not_top_m, r2dglp_max_heap_base_priority_order); |
1942 | INIT_BINHEAP_HANDLE(&sem->donees, r2dglp_min_heap_donee_order); | ||
1943 | INIT_BINHEAP_HANDLE(&sem->priority_queue, | 2037 | INIT_BINHEAP_HANDLE(&sem->priority_queue, |
1944 | r2dglp_max_heap_base_priority_order); | 2038 | r2dglp_max_heap_base_priority_order); |
1945 | INIT_BINHEAP_HANDLE(&sem->donors, r2dglp_donor_max_heap_base_priority_order); | ||
1946 | 2039 | ||
1947 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 2040 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
1948 | sem->aff_obs = NULL; | 2041 | sem->aff_obs = NULL; |
@@ -2508,9 +2601,9 @@ r2dglp_donee_heap_node_t* gpu_r2dglp_advise_donee_selection( | |||
2508 | if(tsk_rt(donor)->last_gpu < 0) { | 2601 | if(tsk_rt(donor)->last_gpu < 0) { |
2509 | /* no affinity. just return the min prio, like standard R2DGLP */ | 2602 | /* no affinity. just return the min prio, like standard R2DGLP */ |
2510 | /* TODO: Find something closer to the head of the queue?? */ | 2603 | /* TODO: Find something closer to the head of the queue?? */ |
2511 | donee_node = binheap_top_entry(&sem->donees, | 2604 | donee_node = sbinheap_top_entry(&sem->donees, |
2512 | r2dglp_donee_heap_node_t, | 2605 | r2dglp_donee_heap_node_t, |
2513 | node); | 2606 | snode); |
2514 | goto out; | 2607 | goto out; |
2515 | } | 2608 | } |
2516 | 2609 | ||
@@ -2519,11 +2612,11 @@ r2dglp_donee_heap_node_t* gpu_r2dglp_advise_donee_selection( | |||
2519 | // prio task in the FIFO queues) to make it eligible for selection below. | 2612 | // prio task in the FIFO queues) to make it eligible for selection below. |
2520 | // | 2613 | // |
2521 | // NOTE: The original donor relation *must* be restored, even if we select | 2614 | // NOTE: The original donor relation *must* be restored, even if we select |
2522 | // the default donee throug affinity-aware selection, before returning | 2615 | // the default donee through affinity-aware selection, before returning |
2523 | // from this function so we don't screw up our heap ordering. | 2616 | // from this function so we don't screw up our heap ordering. |
2524 | // The standard R2DGLP algorithm will steal the donor relationship if needed. | 2617 | // The standard R2DGLP algorithm will steal the donor relationship if needed. |
2525 | default_donee = | 2618 | default_donee = |
2526 | binheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, node); | 2619 | sbinheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, snode); |
2527 | 2620 | ||
2528 | default_donee_donor_info = default_donee->donor_info; // back-up donor relation | 2621 | default_donee_donor_info = default_donee->donor_info; // back-up donor relation |
2529 | default_donee->donor_info = NULL; // temporarily break any donor relation. | 2622 | default_donee->donor_info = NULL; // temporarily break any donor relation. |
@@ -2609,41 +2702,39 @@ out: | |||
2609 | } | 2702 | } |
2610 | 2703 | ||
2611 | 2704 | ||
2705 | typedef struct | ||
2706 | { | ||
2707 | int gpu; | ||
2708 | r2dglp_wait_state_t* closest; | ||
2709 | int dist; | ||
2710 | } find_closest_donor_args_t; | ||
2612 | 2711 | ||
2613 | static void __find_closest_donor(int target_gpu, | 2712 | static void __find_closest_donor(sbinheap_node_t donor_node, void *_args) |
2614 | struct binheap_node* donor_node, | ||
2615 | r2dglp_wait_state_t** cur_closest, | ||
2616 | int* cur_dist) | ||
2617 | { | 2713 | { |
2714 | find_closest_donor_args_t* args = (find_closest_donor_args_t*)_args; | ||
2715 | |||
2618 | r2dglp_wait_state_t *this_donor = | 2716 | r2dglp_wait_state_t *this_donor = |
2619 | binheap_entry(donor_node, r2dglp_wait_state_t, node); | 2717 | sbinheap_entry(donor_node, r2dglp_wait_state_t, snode); |
2620 | 2718 | ||
2621 | int this_dist = | 2719 | int this_dist = |
2622 | gpu_migration_distance(target_gpu, tsk_rt(this_donor->task)->last_gpu); | 2720 | gpu_migration_distance(args->gpu, |
2721 | tsk_rt(this_donor->task)->last_gpu); | ||
2623 | 2722 | ||
2624 | if(this_dist < *cur_dist) { | 2723 | if(this_dist < args->dist) { |
2625 | // take this donor | 2724 | // take this donor |
2626 | *cur_dist = this_dist; | 2725 | args->dist = this_dist; |
2627 | *cur_closest = this_donor; | 2726 | args->closest = this_donor; |
2628 | } | 2727 | } |
2629 | else if(this_dist == *cur_dist) { | 2728 | else if(this_dist == args->dist) { |
2630 | // priority tie-break. Even though this is a pre-order traversal, | 2729 | // priority tie-break. Even though this is a pre-order traversal, |
2631 | // this is a heap, not a binary tree, so we still need to do a priority | 2730 | // this is a heap, not a binary tree, so we still need to do a priority |
2632 | // comparision. | 2731 | // comparision. |
2633 | if(!(*cur_closest) || | 2732 | if(!(args->closest) || |
2634 | litmus->compare(this_donor->task, (*cur_closest)->task)) { | 2733 | litmus->compare(this_donor->task, (args->closest)->task)) { |
2635 | *cur_dist = this_dist; | 2734 | args->dist = this_dist; |
2636 | *cur_closest = this_donor; | 2735 | args->closest = this_donor; |
2637 | } | 2736 | } |
2638 | } | 2737 | } |
2639 | |||
2640 | if(donor_node->left) | ||
2641 | __find_closest_donor(target_gpu, donor_node->left, | ||
2642 | cur_closest, cur_dist); | ||
2643 | |||
2644 | if(donor_node->right) | ||
2645 | __find_closest_donor(target_gpu, donor_node->right, | ||
2646 | cur_closest, cur_dist); | ||
2647 | } | 2738 | } |
2648 | 2739 | ||
2649 | r2dglp_wait_state_t* gpu_r2dglp_advise_donor_to_fq(struct r2dglp_affinity* aff, | 2740 | r2dglp_wait_state_t* gpu_r2dglp_advise_donor_to_fq(struct r2dglp_affinity* aff, |
@@ -2651,29 +2742,31 @@ r2dglp_wait_state_t* gpu_r2dglp_advise_donor_to_fq(struct r2dglp_affinity* aff, | |||
2651 | { | 2742 | { |
2652 | // Huristic strategy: Find donor with the closest affinity to fq. | 2743 | // Huristic strategy: Find donor with the closest affinity to fq. |
2653 | // Tie-break on priority. | 2744 | // Tie-break on priority. |
2745 | // We need to iterate over all the donors to do this. | ||
2654 | 2746 | ||
2655 | // We need to iterate over all the donors to do this. Unfortunatly, | 2747 | r2dglp_wait_state_t *donor; |
2656 | // our donors are organized in a heap. We'll visit each node with a | ||
2657 | // recurisve call. This is realitively safe since there are only sem->m | ||
2658 | // donors, at most. We won't recurse too deeply to have to worry about | ||
2659 | // our stack. (even with 128 CPUs, our nest depth is at most 7 deep). | ||
2660 | |||
2661 | struct r2dglp_semaphore *sem = r2dglp_from_lock(aff->obs.lock); | 2748 | struct r2dglp_semaphore *sem = r2dglp_from_lock(aff->obs.lock); |
2662 | r2dglp_wait_state_t *donor = NULL; | 2749 | find_closest_donor_args_t args = |
2663 | int distance = MIG_NONE; | 2750 | { |
2664 | int gpu = replica_to_gpu(aff, r2dglp_get_idx(sem, fq)); | 2751 | .gpu = replica_to_gpu(aff, r2dglp_get_idx(sem, fq)), |
2752 | .closest = NULL, | ||
2753 | .dist = MIG_NONE, | ||
2754 | }; | ||
2665 | 2755 | ||
2666 | #ifdef CONFIG_SCHED_DEBUG_TRACE | 2756 | #ifdef CONFIG_SCHED_DEBUG_TRACE |
2667 | r2dglp_wait_state_t* default_donor = | 2757 | r2dglp_wait_state_t* default_donor = |
2668 | binheap_top_entry(&sem->donors, r2dglp_wait_state_t, node); | 2758 | sbinheap_top_entry(&sem->donors, r2dglp_wait_state_t, snode); |
2669 | #endif | 2759 | #endif |
2670 | 2760 | ||
2671 | __find_closest_donor(gpu, sem->donors.root, &donor, &distance); | 2761 | sbinheap_for_each(&sem->donors, __find_closest_donor, &args); |
2762 | donor = args.closest; | ||
2763 | |||
2764 | BUG_ON(!donor); | ||
2672 | 2765 | ||
2673 | TRACE_CUR("Selected donor %s/%d (distance = %d) to move to fq %d " | 2766 | TRACE_CUR("Selected donor %s/%d (distance = %d) to move to fq %d " |
2674 | "(non-aff wanted %s/%d). differs = %d\n", | 2767 | "(non-aff wanted %s/%d). differs = %d\n", |
2675 | donor->task->comm, donor->task->pid, | 2768 | donor->task->comm, donor->task->pid, |
2676 | distance, | 2769 | args.dist, |
2677 | r2dglp_get_idx(sem, fq), | 2770 | r2dglp_get_idx(sem, fq), |
2678 | default_donor->task->comm, default_donor->task->pid, | 2771 | default_donor->task->comm, default_donor->task->pid, |
2679 | (donor->task != default_donor->task) | 2772 | (donor->task != default_donor->task) |
@@ -2936,7 +3029,7 @@ r2dglp_donee_heap_node_t* simple_gpu_r2dglp_advise_donee_selection( | |||
2936 | { | 3029 | { |
2937 | struct r2dglp_semaphore *sem = r2dglp_from_lock(aff->obs.lock); | 3030 | struct r2dglp_semaphore *sem = r2dglp_from_lock(aff->obs.lock); |
2938 | r2dglp_donee_heap_node_t *donee = | 3031 | r2dglp_donee_heap_node_t *donee = |
2939 | binheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, node); | 3032 | sbinheap_top_entry(&sem->donees, r2dglp_donee_heap_node_t, snode); |
2940 | return(donee); | 3033 | return(donee); |
2941 | } | 3034 | } |
2942 | 3035 | ||
@@ -2945,7 +3038,7 @@ r2dglp_wait_state_t* simple_gpu_r2dglp_advise_donor_to_fq( | |||
2945 | { | 3038 | { |
2946 | struct r2dglp_semaphore *sem = r2dglp_from_lock(aff->obs.lock); | 3039 | struct r2dglp_semaphore *sem = r2dglp_from_lock(aff->obs.lock); |
2947 | r2dglp_wait_state_t* donor = | 3040 | r2dglp_wait_state_t* donor = |
2948 | binheap_top_entry(&sem->donors, r2dglp_wait_state_t, node); | 3041 | sbinheap_top_entry(&sem->donors, r2dglp_wait_state_t, snode); |
2949 | return(donor); | 3042 | return(donor); |
2950 | } | 3043 | } |
2951 | 3044 | ||
@@ -3336,7 +3429,7 @@ static int r2dglp_proc_print(char *page, char **start, off_t off, int count, int | |||
3336 | } | 3429 | } |
3337 | else { | 3430 | else { |
3338 | w = scnprintf(next, size, "donors:\n"); size -= w; next += w; | 3431 | w = scnprintf(next, size, "donors:\n"); size -= w; next += w; |
3339 | binheap_for_each(&sem->donors, __r2dglp_donor_to_proc, &heap_args); | 3432 | sbinheap_for_each(&sem->donors, __r2dglp_donor_to_proc, &heap_args); |
3340 | } | 3433 | } |
3341 | 3434 | ||
3342 | raw_spin_unlock_irqrestore(&sem->real_lock, flags); | 3435 | raw_spin_unlock_irqrestore(&sem->real_lock, flags); |