aboutsummaryrefslogtreecommitdiffstats
path: root/litmus
diff options
context:
space:
mode:
authorTanya Amert <tamert@cs.unc.edu>2020-10-13 22:26:16 -0400
committerTanya Amert <tamert@cs.unc.edu>2020-10-13 22:26:16 -0400
commit31ed856e2e8dce5f579c97b41e136dc03c2a9319 (patch)
tree053fc0a54017150b8577769aaeb006dbb4f63b85 /litmus
parent8e23121fca5a987c1e8fbeb941cafa0fbcdc7610 (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.c143
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 */
698static 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 */
725static 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 */
819static 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
760int gedf_env_omlp_lock(struct litmus_lock* l) 855int 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
846out: 982out:
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;