diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-04-15 18:06:04 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-04-15 18:06:04 -0400 |
commit | f4aef3b7d845324eb79a226d87f232dcd8867f3b (patch) | |
tree | 685ca7ad02944ee055dbe43f2eab48fccfab2717 /litmus/sched_gsn_edf.c | |
parent | 786d383a58108ad3437a38d0e2583859cb94a4ee (diff) |
Update PAI to support multiGPUs (todo: klitirqd)
Diffstat (limited to 'litmus/sched_gsn_edf.c')
-rw-r--r-- | litmus/sched_gsn_edf.c | 203 |
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 | |||
471 | static 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 | |||
491 | static void do_lit_tasklets(struct task_struct* sched_task) | 462 | static 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 | |||
548 | static 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 | ||
561 | static void __add_pai_tasklet(struct tasklet_struct* tasklet) | 574 | static 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 | ||
607 | static int enqueue_pai_tasklet(struct tasklet_struct* tasklet) | 620 | static 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 | |||
632 | static 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 | ||
720 | static 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 */ |
1073 | static void increase_priority_inheritance(struct task_struct* t, struct task_struct* prio_inh) | 1115 | static 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, | |||
1147 | static void decrease_priority_inheritance(struct task_struct* t, | 1199 | static 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 | ||