aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2014-03-14 16:45:44 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2014-03-14 16:45:44 -0400
commitc93d29a1d7e65a32bfa9111c93badb26b3622f13 (patch)
treed0f46adbc05ffb3e6606a1316bf6ead37c816252
parentd03c848f2b2b18e6d9a2d408c2fc2a6433dc4f91 (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.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);