aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/r2dglp_lock.h22
-rw-r--r--litmus/r2dglp_lock.c349
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;
13typedef struct r2dglp_heap_node 14typedef 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
19struct fifo_queue; 22struct 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
34typedef enum r2dglp_states 37typedef 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
31int r2dglp_min_heap_base_priority_order(const struct binheap_node *a, 31int 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
40int r2dglp_donor_max_heap_base_priority_order(const struct binheap_node *a, 40int 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
50int r2dglp_min_heap_donee_order(const struct binheap_node *a, 50int 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
147static inline struct task_struct* r2dglp_mth_highest(struct r2dglp_semaphore *sem) 147static 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
152static void r2dglp_add_global_list(struct r2dglp_semaphore *sem, 152static 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,
617static void r2dglp_enqueue_on_pq(struct r2dglp_semaphore *sem, 633static 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
1797out: 1845out:
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
2705typedef struct
2706{
2707 int gpu;
2708 r2dglp_wait_state_t* closest;
2709 int dist;
2710} find_closest_donor_args_t;
2612 2711
2613static void __find_closest_donor(int target_gpu, 2712static 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
2649r2dglp_wait_state_t* gpu_r2dglp_advise_donor_to_fq(struct r2dglp_affinity* aff, 2740r2dglp_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);