diff options
author | Tanya Amert <tamert@cs.unc.edu> | 2020-10-13 22:26:16 -0400 |
---|---|---|
committer | Tanya Amert <tamert@cs.unc.edu> | 2020-10-13 22:26:16 -0400 |
commit | 31ed856e2e8dce5f579c97b41e136dc03c2a9319 (patch) | |
tree | 053fc0a54017150b8577769aaeb006dbb4f63b85 /litmus | |
parent | 8e23121fca5a987c1e8fbeb941cafa0fbcdc7610 (diff) |
Added (unused) inh_res field to extended reservations, to be used for priority inheritance.
Diffstat (limited to 'litmus')
-rw-r--r-- | litmus/reservations/gedf_reservation.c | 143 |
1 files changed, 140 insertions, 3 deletions
diff --git a/litmus/reservations/gedf_reservation.c b/litmus/reservations/gedf_reservation.c index 6d713d95131b..e16be7de4902 100644 --- a/litmus/reservations/gedf_reservation.c +++ b/litmus/reservations/gedf_reservation.c | |||
@@ -694,6 +694,63 @@ static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res) | |||
694 | #include <litmus/fdso.h> | 694 | #include <litmus/fdso.h> |
695 | #include <litmus/wait.h> | 695 | #include <litmus/wait.h> |
696 | 696 | ||
697 | /* called with IRQs off */ | ||
698 | static void set_priority_inheritance(struct task_struct* t, struct task_struct* prio_inh) | ||
699 | { | ||
700 | struct gedf_cpu_entry* linked_on; | ||
701 | int check_preempt = 0; | ||
702 | |||
703 | struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; | ||
704 | struct reservation *prio_inh_res = (struct reservation *) tsk_rt(prio_inh)->plugin_state; | ||
705 | |||
706 | struct reservation_environment *env = t_res->par_env; | ||
707 | |||
708 | struct gedf_reservation_environment *gedf_env; | ||
709 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | ||
710 | |||
711 | raw_spin_lock(&gedf_env->domain.ready_lock); | ||
712 | |||
713 | printk("Task %d had inherited prio=%llu, now will be prio=%llu\n", | ||
714 | t->pid, t_res->inh_res ? t_res->inh_res->priority : 0, | ||
715 | prio_inh_res->priority); | ||
716 | TRACE_TASK(t, "inherits priority from %s/%d\n", prio_inh->comm, prio_inh->pid); | ||
717 | t_res->inh_res = prio_inh_res; | ||
718 | |||
719 | // TODO tamert: actually try and handle the change to the priority | ||
720 | |||
721 | raw_spin_unlock(&gedf_env->domain.ready_lock); | ||
722 | } | ||
723 | |||
724 | /* called with IRQs off */ | ||
725 | static void clear_priority_inheritance(struct task_struct* t) | ||
726 | { | ||
727 | struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; | ||
728 | |||
729 | struct reservation_environment *env = t_res->par_env; | ||
730 | |||
731 | struct gedf_reservation_environment *gedf_env; | ||
732 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | ||
733 | |||
734 | struct gedf_reservation *gedf_res; | ||
735 | gedf_res = container_of(t_res, struct gedf_reservation, res); | ||
736 | |||
737 | raw_spin_lock(&gedf_env->domain.ready_lock); | ||
738 | |||
739 | /* A job only stops inheriting a priority when it releases a | ||
740 | * resource. Thus we can make the following assumption.*/ | ||
741 | int cpu = smp_processor_id(); | ||
742 | struct gedf_cpu_entry *entry = &gedf_env->cpu_entries[cpu]; | ||
743 | BUG_ON(entry->scheduled != gedf_res); | ||
744 | |||
745 | TRACE_TASK(t, "priority restored\n"); | ||
746 | t_res->inh_res = NULL; | ||
747 | |||
748 | // TODO tamert: reschedule if necessary | ||
749 | // (the priority was effectively lowered) | ||
750 | |||
751 | raw_spin_unlock(&gedf_env->domain.ready_lock); | ||
752 | } | ||
753 | |||
697 | /* ******************** OMLP support ********************** */ | 754 | /* ******************** OMLP support ********************** */ |
698 | 755 | ||
699 | /* struct for semaphore with priority inheritance */ | 756 | /* struct for semaphore with priority inheritance */ |
@@ -705,6 +762,7 @@ struct omlp_semaphore { | |||
705 | 762 | ||
706 | /* highest-priority waiter */ | 763 | /* highest-priority waiter */ |
707 | struct task_struct *hp_waiter; | 764 | struct task_struct *hp_waiter; |
765 | struct reservation *hp_waiter_res; | ||
708 | 766 | ||
709 | /* FIFO queue of waiting tasks */ | 767 | /* FIFO queue of waiting tasks */ |
710 | wait_queue_head_t fifo_wait; | 768 | wait_queue_head_t fifo_wait; |
@@ -757,6 +815,43 @@ static struct task_struct* omlp_dequeue(struct omlp_semaphore *sem) | |||
757 | return first; | 815 | return first; |
758 | } | 816 | } |
759 | 817 | ||
818 | /* caller is responsible for locking */ | ||
819 | static struct task_struct* omlp_find_hp_waiter(struct omlp_semaphore *sem, | ||
820 | struct task_struct* skip) | ||
821 | { | ||
822 | struct list_head *pos; | ||
823 | struct task_struct *queued, *found = NULL; | ||
824 | struct reservation *q_res, *f_res = NULL; | ||
825 | |||
826 | /* check FIFO queue first */ | ||
827 | list_for_each(pos, &sem->fifo_wait.task_list) { | ||
828 | queued = (struct task_struct*) list_entry(pos, wait_queue_t, | ||
829 | task_list)->private; | ||
830 | |||
831 | /* Compare task prios, find high prio task. */ | ||
832 | q_res = (struct reservation *) tsk_rt(queued)->plugin_state; | ||
833 | if (queued != skip && (!f_res || higher_res_prio(f_res, q_res))) { | ||
834 | f_res = q_res; | ||
835 | found = queued; | ||
836 | } | ||
837 | } | ||
838 | |||
839 | /* check priority queue next */ | ||
840 | if (waitqueue_active(&sem->prio_wait)) { | ||
841 | /* first has highest priority */ | ||
842 | pos = sem->prio_wait.task_list.next; | ||
843 | queued = (struct task_struct*) list_entry(pos, wait_queue_t, | ||
844 | task_list)->private; | ||
845 | q_res = (struct reservation *) tsk_rt(queued)->plugin_state; | ||
846 | if (!f_res || (higher_res_prio(f_res, q_res))) { | ||
847 | f_res = q_res; | ||
848 | found = queued; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | return found; | ||
853 | } | ||
854 | |||
760 | int gedf_env_omlp_lock(struct litmus_lock* l) | 855 | int gedf_env_omlp_lock(struct litmus_lock* l) |
761 | { | 856 | { |
762 | struct task_struct* t = current; | 857 | struct task_struct* t = current; |
@@ -774,6 +869,9 @@ int gedf_env_omlp_lock(struct litmus_lock* l) | |||
774 | 869 | ||
775 | struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; | 870 | struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; |
776 | 871 | ||
872 | struct gedf_reservation *gedf_res = container_of(t_res, struct gedf_reservation, res); | ||
873 | BUG_ON(!gedf_res->linked_on && !bheap_node_in_heap(t_res->heap_node)); | ||
874 | |||
777 | spin_lock_irqsave(&sem->fifo_wait.lock, flags); | 875 | spin_lock_irqsave(&sem->fifo_wait.lock, flags); |
778 | 876 | ||
779 | if (sem->owner) { | 877 | if (sem->owner) { |
@@ -785,14 +883,25 @@ int gedf_env_omlp_lock(struct litmus_lock* l) | |||
785 | 883 | ||
786 | omlp_enqueue(sem, &wait); | 884 | omlp_enqueue(sem, &wait); |
787 | 885 | ||
788 | // TODO tamert: add priority inheritance | 886 | /* check if we need to activate priority inheritance */ |
887 | if (!sem->hp_waiter_res || higher_res_prio(sem->hp_waiter_res, t_res)) { | ||
888 | sem->hp_waiter = t; | ||
889 | sem->hp_waiter_res = t_res; | ||
890 | struct reservation *o_res = (struct reservation *) tsk_rt(sem->owner)->plugin_state; | ||
891 | if (higher_res_prio(o_res, t_res)) { | ||
892 | set_priority_inheritance(sem->owner, sem->hp_waiter); | ||
893 | } | ||
894 | } | ||
789 | 895 | ||
790 | TS_LOCK_SUSPEND; | 896 | TS_LOCK_SUSPEND; |
791 | 897 | ||
792 | /* release lock before sleeping */ | 898 | /* release lock before sleeping */ |
793 | spin_unlock_irqrestore(&sem->fifo_wait.lock, flags); | 899 | spin_unlock_irqrestore(&sem->fifo_wait.lock, flags); |
794 | 900 | ||
795 | schedule(); | 901 | BUG_ON(!gedf_res->linked_on && !bheap_node_in_heap(t_res->heap_node)); |
902 | |||
903 | schedule(); // will have issues if the reservation | ||
904 | // is not linked or on the ready queue (wtf?!) | ||
796 | 905 | ||
797 | TS_LOCK_RESUME; | 906 | TS_LOCK_RESUME; |
798 | 907 | ||
@@ -835,7 +944,30 @@ static int gedf_env_omlp_unlock(struct litmus_lock* l) | |||
835 | sem->owner = next; | 944 | sem->owner = next; |
836 | TRACE_CUR("lock ownership passed to %s/%d\n", next->comm, next->pid); | 945 | TRACE_CUR("lock ownership passed to %s/%d\n", next->comm, next->pid); |
837 | 946 | ||
838 | // TODO tamert: add priority inheritance | 947 | struct reservation *n_res = (struct reservation *) tsk_rt(next)->plugin_state; |
948 | |||
949 | /* determine new hp_waiter if necessary */ | ||
950 | if (next == sem->hp_waiter) { | ||
951 | TRACE_TASK(next, "was highest-prio waiter\n"); | ||
952 | /* next has the highest priority --- it doesn't need to | ||
953 | * inherit. However, we need to make sure that the | ||
954 | * next-highest priority in the queue is reflected in | ||
955 | * hp_waiter. */ | ||
956 | sem->hp_waiter = omlp_find_hp_waiter(sem, next); | ||
957 | if (sem->hp_waiter) { | ||
958 | TRACE_TASK(sem->hp_waiter, "is new highest-prio waiter\n"); | ||
959 | sem->hp_waiter_res = (struct reservation *) tsk_rt(sem->hp_waiter)->plugin_state; | ||
960 | } | ||
961 | else { | ||
962 | TRACE("no further waiters\n"); | ||
963 | sem->hp_waiter_res = NULL; | ||
964 | } | ||
965 | } else { | ||
966 | /* Well, if next is not the highest-priority waiter, | ||
967 | * then it ought to inherit the highest-priority | ||
968 | * waiter's priority. */ | ||
969 | set_priority_inheritance(next, sem->hp_waiter); | ||
970 | } | ||
839 | 971 | ||
840 | /* wake up next */ | 972 | /* wake up next */ |
841 | wake_up_process(next); | 973 | wake_up_process(next); |
@@ -843,6 +975,10 @@ static int gedf_env_omlp_unlock(struct litmus_lock* l) | |||
843 | /* becomes available */ | 975 | /* becomes available */ |
844 | sem->owner = NULL; | 976 | sem->owner = NULL; |
845 | 977 | ||
978 | /* we lose the benefit of priority inheritance (if any) */ | ||
979 | if (((struct reservation *)tsk_rt(t)->plugin_state)->inh_res) | ||
980 | clear_priority_inheritance(t); | ||
981 | |||
846 | out: | 982 | out: |
847 | spin_unlock_irqrestore(&sem->fifo_wait.lock, flags); | 983 | spin_unlock_irqrestore(&sem->fifo_wait.lock, flags); |
848 | 984 | ||
@@ -891,6 +1027,7 @@ static struct litmus_lock* gedf_env_new_omlp(void) | |||
891 | 1027 | ||
892 | sem->owner = NULL; | 1028 | sem->owner = NULL; |
893 | sem->hp_waiter = NULL; | 1029 | sem->hp_waiter = NULL; |
1030 | sem->hp_waiter_res = NULL; | ||
894 | init_waitqueue_head(&sem->fifo_wait); | 1031 | init_waitqueue_head(&sem->fifo_wait); |
895 | init_waitqueue_head(&sem->prio_wait); | 1032 | init_waitqueue_head(&sem->prio_wait); |
896 | sem->litmus_lock.ops = &gedf_env_omlp_lock_ops; | 1033 | sem->litmus_lock.ops = &gedf_env_omlp_lock_ops; |