aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/sched_gsn_edf.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-04-15 18:06:04 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2012-04-15 18:06:04 -0400
commitf4aef3b7d845324eb79a226d87f232dcd8867f3b (patch)
tree685ca7ad02944ee055dbe43f2eab48fccfab2717 /litmus/sched_gsn_edf.c
parent786d383a58108ad3437a38d0e2583859cb94a4ee (diff)
Update PAI to support multiGPUs (todo: klitirqd)
Diffstat (limited to 'litmus/sched_gsn_edf.c')
-rw-r--r--litmus/sched_gsn_edf.c203
1 files changed, 133 insertions, 70 deletions
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index e009b7f34aca..37f7821dca50 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -436,14 +436,6 @@ static void gsnedf_tick(struct task_struct* t)
436 436
437 437
438 438
439
440
441
442
443
444
445
446
447#ifdef CONFIG_LITMUS_PAI_SOFTIRQD 439#ifdef CONFIG_LITMUS_PAI_SOFTIRQD
448 440
449 441
@@ -467,96 +459,117 @@ static void __do_lit_tasklet(struct tasklet_struct* tasklet, unsigned long flush
467 } 459 }
468} 460}
469 461
470
471static void flush_tasklets(struct task_struct* task)
472{
473 // lazy flushing.
474 // just change ownership to NULL and let idel processor
475 // take care of it. :P
476
477 struct tasklet_struct* step;
478 unsigned long flags;
479
480 raw_spin_lock_irqsave(&gsnedf_lock, flags);
481 for(step = gsnedf_pending_tasklets.head; step != NULL; step = step->next) {
482 if(step->owner == task) {
483 TRACE("%s: Found tasklet to flush: %d\n", __FUNCTION__, step->owner->pid);
484 step->owner = NULL;
485 }
486 }
487 raw_spin_unlock_irqrestore(&gsnedf_lock, flags);
488}
489
490
491static void do_lit_tasklets(struct task_struct* sched_task) 462static void do_lit_tasklets(struct task_struct* sched_task)
492{ 463{
493 int work_to_do = 1; 464 int work_to_do = 1;
494 struct tasklet_struct *tasklet = NULL; 465 struct tasklet_struct *tasklet = NULL;
495 //struct tasklet_struct *step;
496 unsigned long flags; 466 unsigned long flags;
497 467
498 while(work_to_do) { 468 while(work_to_do) {
499 469
500 TS_NV_SCHED_BOTISR_START; 470 TS_NV_SCHED_BOTISR_START;
501 471
502 // remove tasklet at head of list if it has higher priority. 472 // execute one tasklet that has higher priority
503 raw_spin_lock_irqsave(&gsnedf_lock, flags); 473 raw_spin_lock_irqsave(&gsnedf_lock, flags);
504 474
505 if(gsnedf_pending_tasklets.head != NULL) { 475 if(gsnedf_pending_tasklets.head != NULL) {
506 // remove tasklet at head. 476 struct tasklet_struct *prev = NULL;
507 tasklet = gsnedf_pending_tasklets.head; 477 tasklet = gsnedf_pending_tasklets.head;
478
479 while(tasklet && edf_higher_prio(sched_task, tasklet->owner)) {
480 prev = tasklet;
481 tasklet = tasklet->next;
482 }
508 483
509 if(edf_higher_prio(tasklet->owner, sched_task)) { 484 // remove the tasklet from the queue
510 485 if(prev) {
511 if(NULL == tasklet->next) { 486 prev->next = tasklet->next;
512 // tasklet is at the head, list only has one element 487 if(prev->next == NULL) {
513 TRACE("%s: Tasklet for %d is the last element in tasklet queue.\n", __FUNCTION__, tasklet->owner->pid); 488 TRACE("%s: Tasklet for %d is the last element in tasklet queue.\n", __FUNCTION__, tasklet->owner->pid);
514 gsnedf_pending_tasklets.tail = &(gsnedf_pending_tasklets.head); 489 gsnedf_pending_tasklets.tail = &(prev);
515 } 490 }
516
517 // remove the tasklet from the queue
518 gsnedf_pending_tasklets.head = tasklet->next;
519
520 TRACE("%s: Removed tasklet for %d from tasklet queue.\n", __FUNCTION__, tasklet->owner->pid);
521 } 491 }
522 else { 492 else {
523 TRACE("%s: Pending tasklet (%d) does not have priority to run on this CPU (%d).\n", __FUNCTION__, tasklet->owner->pid, smp_processor_id()); 493 gsnedf_pending_tasklets.head = tasklet->next;
524 tasklet = NULL; 494 if(tasklet->next == NULL) {
495 TRACE("%s: Tasklet for %d is the last element in tasklet queue.\n", __FUNCTION__, tasklet->owner->pid);
496 gsnedf_pending_tasklets.tail = &(gsnedf_pending_tasklets.head);
497 }
525 } 498 }
526 } 499 }
527 else { 500 else {
528 TRACE("%s: Tasklet queue is empty.\n", __FUNCTION__); 501 TRACE("%s: Tasklet queue is empty.\n", __FUNCTION__);
529 } 502 }
530 503
531 raw_spin_unlock_irqrestore(&gsnedf_lock, flags); 504 raw_spin_unlock_irqrestore(&gsnedf_lock, flags);
532 505
533 TS_NV_SCHED_BOTISR_END;
534
535 if(tasklet) { 506 if(tasklet) {
536 __do_lit_tasklet(tasklet, 0ul); 507 __do_lit_tasklet(tasklet, 0ul);
537 tasklet = NULL; 508 tasklet = NULL;
538 } 509 }
539 else { 510 else {
540 work_to_do = 0; 511 work_to_do = 0;
541 } 512 }
513
514 TS_NV_SCHED_BOTISR_END;
542 } 515 }
543
544 //TRACE("%s: exited.\n", __FUNCTION__);
545}
546
547
548static void run_tasklets(struct task_struct* sched_task)
549{
550 preempt_disable();
551
552 if(gsnedf_pending_tasklets.head != NULL) {
553 TRACE("%s: There are tasklets to process.\n", __FUNCTION__);
554 do_lit_tasklets(sched_task);
555 }
556
557 preempt_enable_no_resched();
558} 516}
559 517
518//static void do_lit_tasklets(struct task_struct* sched_task)
519//{
520// int work_to_do = 1;
521// struct tasklet_struct *tasklet = NULL;
522// //struct tasklet_struct *step;
523// unsigned long flags;
524//
525// while(work_to_do) {
526//
527// TS_NV_SCHED_BOTISR_START;
528//
529// // remove tasklet at head of list if it has higher priority.
530// raw_spin_lock_irqsave(&gsnedf_lock, flags);
531//
532// if(gsnedf_pending_tasklets.head != NULL) {
533// // remove tasklet at head.
534// tasklet = gsnedf_pending_tasklets.head;
535//
536// if(edf_higher_prio(tasklet->owner, sched_task)) {
537//
538// if(NULL == tasklet->next) {
539// // tasklet is at the head, list only has one element
540// TRACE("%s: Tasklet for %d is the last element in tasklet queue.\n", __FUNCTION__, tasklet->owner->pid);
541// gsnedf_pending_tasklets.tail = &(gsnedf_pending_tasklets.head);
542// }
543//
544// // remove the tasklet from the queue
545// gsnedf_pending_tasklets.head = tasklet->next;
546//
547// TRACE("%s: Removed tasklet for %d from tasklet queue.\n", __FUNCTION__, tasklet->owner->pid);
548// }
549// else {
550// TRACE("%s: Pending tasklet (%d) does not have priority to run on this CPU (%d).\n", __FUNCTION__, tasklet->owner->pid, smp_processor_id());
551// tasklet = NULL;
552// }
553// }
554// else {
555// TRACE("%s: Tasklet queue is empty.\n", __FUNCTION__);
556// }
557//
558// raw_spin_unlock_irqrestore(&gsnedf_lock, flags);
559//
560// TS_NV_SCHED_BOTISR_END;
561//
562// if(tasklet) {
563// __do_lit_tasklet(tasklet, 0ul);
564// tasklet = NULL;
565// }
566// else {
567// work_to_do = 0;
568// }
569// }
570//
571// //TRACE("%s: exited.\n", __FUNCTION__);
572//}
560 573
561static void __add_pai_tasklet(struct tasklet_struct* tasklet) 574static void __add_pai_tasklet(struct tasklet_struct* tasklet)
562{ 575{
@@ -604,7 +617,19 @@ static void __add_pai_tasklet(struct tasklet_struct* tasklet)
604 } 617 }
605} 618}
606 619
607static int enqueue_pai_tasklet(struct tasklet_struct* tasklet) 620static void gsnedf_run_tasklets(struct task_struct* sched_task)
621{
622 preempt_disable();
623
624 if(gsnedf_pending_tasklets.head != NULL) {
625 TRACE("%s: There are tasklets to process.\n", __FUNCTION__);
626 do_lit_tasklets(sched_task);
627 }
628
629 preempt_enable_no_resched();
630}
631
632static int gsnedf_enqueue_pai_tasklet(struct tasklet_struct* tasklet)
608{ 633{
609 cpu_entry_t *targetCPU = NULL; 634 cpu_entry_t *targetCPU = NULL;
610 int thisCPU; 635 int thisCPU;
@@ -692,6 +717,23 @@ static int enqueue_pai_tasklet(struct tasklet_struct* tasklet)
692 return(1); // success 717 return(1); // success
693} 718}
694 719
720static void gsnedf_change_prio_pai_tasklet(struct task_struct *old_prio,
721 struct task_struct *new_prio)
722{
723 struct tasklet_struct* step;
724 unsigned long flags;
725
726 raw_spin_lock_irqsave(&gsnedf_lock, flags);
727
728 for(step = gsnedf_pending_tasklets.head; step != NULL; step = step->next) {
729 if(step->owner == old_prio) {
730 TRACE("%s: Found tasklet to flush: %d\n", __FUNCTION__, step->owner->pid);
731 step->owner = new_prio;
732 }
733 }
734 raw_spin_unlock_irqrestore(&gsnedf_lock, flags);
735}
736
695#endif // end PAI 737#endif // end PAI
696 738
697 739
@@ -954,7 +996,7 @@ static void gsnedf_task_exit(struct task_struct * t)
954 unsigned long flags; 996 unsigned long flags;
955 997
956#ifdef CONFIG_LITMUS_PAI_SOFTIRQD 998#ifdef CONFIG_LITMUS_PAI_SOFTIRQD
957 flush_tasklets(t); 999 gsnedf_change_prio_pai_tasklet(t, NULL);
958#endif 1000#endif
959 1001
960 /* unlink if necessary */ 1002 /* unlink if necessary */
@@ -1072,6 +1114,8 @@ static void __increase_priority_inheritance(struct task_struct* t,
1072/* called with IRQs off */ 1114/* called with IRQs off */
1073static void increase_priority_inheritance(struct task_struct* t, struct task_struct* prio_inh) 1115static void increase_priority_inheritance(struct task_struct* t, struct task_struct* prio_inh)
1074{ 1116{
1117 int i = 0;
1118
1075 raw_spin_lock(&gsnedf_lock); 1119 raw_spin_lock(&gsnedf_lock);
1076 1120
1077 __increase_priority_inheritance(t, prio_inh); 1121 __increase_priority_inheritance(t, prio_inh);
@@ -1087,6 +1131,14 @@ static void increase_priority_inheritance(struct task_struct* t, struct task_str
1087#endif 1131#endif
1088 1132
1089 raw_spin_unlock(&gsnedf_lock); 1133 raw_spin_unlock(&gsnedf_lock);
1134
1135#if defined(CONFIG_LITMUS_PAI_SOFTIRQD) && defined(CONFIG_LITMUS_NVIDIA)
1136 for(i = find_first_bit(&tsk_rt(t)->held_gpus, sizeof(tsk_rt(t)->held_gpus));
1137 i < NV_DEVICE_NUM;
1138 i = find_next_bit(&tsk_rt(t)->held_gpus, sizeof(tsk_rt(t)->held_gpus), i)) {
1139 pai_check_priority_increase(t, i);
1140 }
1141#endif
1090} 1142}
1091 1143
1092 1144
@@ -1147,6 +1199,8 @@ static void __decrease_priority_inheritance(struct task_struct* t,
1147static void decrease_priority_inheritance(struct task_struct* t, 1199static void decrease_priority_inheritance(struct task_struct* t,
1148 struct task_struct* prio_inh) 1200 struct task_struct* prio_inh)
1149{ 1201{
1202 int i;
1203
1150 raw_spin_lock(&gsnedf_lock); 1204 raw_spin_lock(&gsnedf_lock);
1151 __decrease_priority_inheritance(t, prio_inh); 1205 __decrease_priority_inheritance(t, prio_inh);
1152 1206
@@ -1160,7 +1214,15 @@ static void decrease_priority_inheritance(struct task_struct* t,
1160 } 1214 }
1161#endif 1215#endif
1162 1216
1163 raw_spin_unlock(&gsnedf_lock); 1217 raw_spin_unlock(&gsnedf_lock);
1218
1219#if defined(CONFIG_LITMUS_PAI_SOFTIRQD) && defined(CONFIG_LITMUS_NVIDIA)
1220 for(i = find_first_bit(&tsk_rt(t)->held_gpus, sizeof(tsk_rt(t)->held_gpus));
1221 i < NV_DEVICE_NUM;
1222 i = find_next_bit(&tsk_rt(t)->held_gpus, sizeof(tsk_rt(t)->held_gpus), i)) {
1223 pai_check_priority_decrease(t, i);
1224 }
1225#endif
1164} 1226}
1165 1227
1166 1228
@@ -1687,8 +1749,9 @@ static struct sched_plugin gsn_edf_plugin __cacheline_aligned_in_smp = {
1687 .decrease_prio_klitirqd = decrease_priority_inheritance_klitirqd, 1749 .decrease_prio_klitirqd = decrease_priority_inheritance_klitirqd,
1688#endif 1750#endif
1689#ifdef CONFIG_LITMUS_PAI_SOFTIRQD 1751#ifdef CONFIG_LITMUS_PAI_SOFTIRQD
1690 .enqueue_pai_tasklet = enqueue_pai_tasklet, 1752 .enqueue_pai_tasklet = gsnedf_enqueue_pai_tasklet,
1691 .run_tasklets = run_tasklets, 1753 .change_prio_pai_tasklet = gsnedf_change_prio_pai_tasklet,
1754 .run_tasklets = gsnedf_run_tasklets,
1692#endif 1755#endif
1693}; 1756};
1694 1757