aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/ctrlpage.h6
-rw-r--r--include/litmus/locking.h5
-rw-r--r--include/litmus/reservations/gedf_reservation.h6
-rw-r--r--litmus/ctrldev.c6
-rw-r--r--litmus/locking.c27
-rw-r--r--litmus/reservations/gedf_reservation.c161
6 files changed, 186 insertions, 25 deletions
diff --git a/include/litmus/ctrlpage.h b/include/litmus/ctrlpage.h
index f7b03e1aedd6..445857d2f38b 100644
--- a/include/litmus/ctrlpage.h
+++ b/include/litmus/ctrlpage.h
@@ -74,6 +74,7 @@ typedef enum {
74 LRT_wait_for_ts_release, 74 LRT_wait_for_ts_release,
75 LRT_release_ts, 75 LRT_release_ts,
76 LRT_get_current_budget, 76 LRT_get_current_budget,
77 LRT_access_forbidden_zone_check,
77} litmus_syscall_id_t; 78} litmus_syscall_id_t;
78 79
79union litmus_syscall_args { 80union litmus_syscall_args {
@@ -98,6 +99,11 @@ union litmus_syscall_args {
98 lt_t __user *expended; 99 lt_t __user *expended;
99 lt_t __user *remaining; 100 lt_t __user *remaining;
100 } get_current_budget; 101 } get_current_budget;
102
103 struct {
104 uint32_t sem_od;
105 lt_t fz_len;
106 } access_forbidden_zone_check;
101}; 107};
102 108
103 109
diff --git a/include/litmus/locking.h b/include/litmus/locking.h
index 4d7b870cb443..0dae82711717 100644
--- a/include/litmus/locking.h
+++ b/include/litmus/locking.h
@@ -1,6 +1,8 @@
1#ifndef LITMUS_LOCKING_H 1#ifndef LITMUS_LOCKING_H
2#define LITMUS_LOCKING_H 2#define LITMUS_LOCKING_H
3 3
4#include <litmus/rt_param.h>
5
4struct litmus_lock_ops; 6struct litmus_lock_ops;
5 7
6/* Generic base struct for LITMUS^RT userspace semaphores. 8/* Generic base struct for LITMUS^RT userspace semaphores.
@@ -21,6 +23,9 @@ struct litmus_lock_ops {
21 int (*lock)(struct litmus_lock*); 23 int (*lock)(struct litmus_lock*);
22 int (*unlock)(struct litmus_lock*); 24 int (*unlock)(struct litmus_lock*);
23 25
26 /* Current tries to access protected resource (mandatory methods if supported). */
27 int (*access_forbidden_zone_check)(struct litmus_lock*, lt_t fz_len);
28
24 /* The lock is no longer being referenced (mandatory method). */ 29 /* The lock is no longer being referenced (mandatory method). */
25 void (*deallocate)(struct litmus_lock*); 30 void (*deallocate)(struct litmus_lock*);
26}; 31};
diff --git a/include/litmus/reservations/gedf_reservation.h b/include/litmus/reservations/gedf_reservation.h
index 08961e7931a2..d9694fa3ac64 100644
--- a/include/litmus/reservations/gedf_reservation.h
+++ b/include/litmus/reservations/gedf_reservation.h
@@ -66,6 +66,12 @@ struct gedf_reservation_environment {
66 struct bheap_node* cpu_node; 66 struct bheap_node* cpu_node;
67 67
68 rt_domain_t domain; 68 rt_domain_t domain;
69
70#ifdef CONFIG_LITMUS_LOCKING
71 /* reservations sleeping due to forbidden zones */
72 int num_waiter_queues;
73 wait_queue_head_t* fz_waiters;
74#endif
69}; 75};
70 76
71long alloc_gedf_reservation_environment( 77long alloc_gedf_reservation_environment(
diff --git a/litmus/ctrldev.c b/litmus/ctrldev.c
index cc74c5afa5c6..7090f9bc67ad 100644
--- a/litmus/ctrldev.c
+++ b/litmus/ctrldev.c
@@ -130,6 +130,7 @@ asmlinkage long sys_od_open(int fd, int type, int obj_id, void* __user config);
130asmlinkage long sys_od_close(int od); 130asmlinkage long sys_od_close(int od);
131asmlinkage long sys_complete_job(void); 131asmlinkage long sys_complete_job(void);
132asmlinkage long sys_litmus_lock(int lock_od); 132asmlinkage long sys_litmus_lock(int lock_od);
133asmlinkage long sys_access_forbidden_zone_check(int lock_od, lt_t fz_len);
133asmlinkage long sys_litmus_unlock(int lock_od); 134asmlinkage long sys_litmus_unlock(int lock_od);
134asmlinkage long sys_wait_for_job_release(unsigned int job); 135asmlinkage long sys_wait_for_job_release(unsigned int job);
135asmlinkage long sys_wait_for_ts_release(void); 136asmlinkage long sys_wait_for_ts_release(void);
@@ -155,6 +156,7 @@ static long litmus_ctrl_ioctl(struct file *filp,
155 case LRT_reservation_create: 156 case LRT_reservation_create:
156 case LRT_get_current_budget: 157 case LRT_get_current_budget:
157 case LRT_od_open: 158 case LRT_od_open:
159 case LRT_access_forbidden_zone_check:
158 /* multiple arguments => need to get args via pointer */ 160 /* multiple arguments => need to get args via pointer */
159 /* get syscall parameters */ 161 /* get syscall parameters */
160 if (copy_from_user(&syscall_args, (void*) arg, 162 if (copy_from_user(&syscall_args, (void*) arg,
@@ -185,6 +187,10 @@ static long litmus_ctrl_ioctl(struct file *filp,
185 syscall_args.od_open.obj_type, 187 syscall_args.od_open.obj_type,
186 syscall_args.od_open.obj_id, 188 syscall_args.od_open.obj_id,
187 syscall_args.od_open.config); 189 syscall_args.od_open.config);
190 case LRT_access_forbidden_zone_check:
191 return sys_access_forbidden_zone_check(
192 syscall_args.access_forbidden_zone_check.sem_od,
193 syscall_args.access_forbidden_zone_check.fz_len);
188 } 194 }
189 195
190 196
diff --git a/litmus/locking.c b/litmus/locking.c
index a1d0515c5613..eb228e6b01af 100644
--- a/litmus/locking.c
+++ b/litmus/locking.c
@@ -97,6 +97,28 @@ asmlinkage long sys_litmus_lock(int lock_od)
97 return err; 97 return err;
98} 98}
99 99
100asmlinkage long sys_access_forbidden_zone_check(int lock_od, lt_t fz_len)
101{
102 long err = -EINVAL;
103 struct od_table_entry* entry;
104 struct litmus_lock* l;
105
106 TS_SYSCALL_IN_START;
107
108 TS_SYSCALL_IN_END;
109
110 entry = get_entry_for_od(lock_od);
111 if (entry && is_lock(entry)) {
112 l = get_lock(entry);
113 TRACE_CUR("attempts to check forbidden zone 0x%p\n", l);
114 err = l->ops->access_forbidden_zone_check(l, fz_len);
115 }
116
117 TS_SYSCALL_OUT_START;
118
119 return err;
120}
121
100asmlinkage long sys_litmus_unlock(int lock_od) 122asmlinkage long sys_litmus_unlock(int lock_od)
101{ 123{
102 long err = -EINVAL; 124 long err = -EINVAL;
@@ -181,6 +203,11 @@ asmlinkage long sys_litmus_lock(int sem_od)
181 return -ENOSYS; 203 return -ENOSYS;
182} 204}
183 205
206asmlinkage long sys_forbidden_zone_start(int lock_od, int fz_len)
207{
208 return -ENOSYS;
209}
210
184asmlinkage long sys_litmus_unlock(int sem_od) 211asmlinkage long sys_litmus_unlock(int sem_od)
185{ 212{
186 return -ENOSYS; 213 return -ENOSYS;
diff --git a/litmus/reservations/gedf_reservation.c b/litmus/reservations/gedf_reservation.c
index 8b39518f4a1a..e5a19e6de663 100644
--- a/litmus/reservations/gedf_reservation.c
+++ b/litmus/reservations/gedf_reservation.c
@@ -13,6 +13,7 @@
13#include <litmus/debug_trace.h> 13#include <litmus/debug_trace.h>
14#include <litmus/trace.h> 14#include <litmus/trace.h>
15#include <litmus/reservations/gedf_reservation.h> 15#include <litmus/reservations/gedf_reservation.h>
16#include <litmus/reservations/table_driven_ext_reservation.h>
16 17
17// Needed to store context during cross-CPU function calls 18// Needed to store context during cross-CPU function calls
18struct csd_wrapper { 19struct csd_wrapper {
@@ -554,6 +555,10 @@ static void gedf_env_resume(
554 unsigned long flags; 555 unsigned long flags;
555 // Needs to be volatile or it may be optimized to gedf_env->num_cpus 556 // Needs to be volatile or it may be optimized to gedf_env->num_cpus
556 volatile int tmp_cpus; 557 volatile int tmp_cpus;
558 // For waking up forbidden-zone waiters
559 int i;
560 struct task_struct *next;
561 struct reservation *next_res;
557 562
558 gedf_env = container_of(env, struct gedf_reservation_environment, env); 563 gedf_env = container_of(env, struct gedf_reservation_environment, env);
559 entry = &gedf_env->cpu_entries[cpu]; 564 entry = &gedf_env->cpu_entries[cpu];
@@ -581,6 +586,22 @@ static void gedf_env_resume(
581 // Keep this outside the lock. Resuming the timer may have side-effects. 586 // Keep this outside the lock. Resuming the timer may have side-effects.
582 if (!tmp_cpus) 587 if (!tmp_cpus)
583 domain_resume_releases(&gedf_env->domain); 588 domain_resume_releases(&gedf_env->domain);
589
590#ifdef CONFIG_LITMUS_LOCKING
591 // Wake up any forbidden-zone waiters
592 for (i = 0; i < gedf_env->num_waiter_queues; i++) {
593 if (i == cpu)
594 continue;
595
596 spin_lock_irqsave(&gedf_env->fz_waiters[i].lock, flags);
597 while ( (next = __waitqueue_remove_first(&gedf_env->fz_waiters[i])) ) {
598 next_res = (struct reservation *) tsk_rt(next)->plugin_state;
599 wake_up_process(next);
600 }
601
602 spin_unlock_irqrestore(&gedf_env->fz_waiters[i].lock, flags);
603 }
604#endif
584} 605}
585 606
586static struct task_struct* gedf_env_dispatch( 607static struct task_struct* gedf_env_dispatch(
@@ -716,17 +737,17 @@ static void set_priority_inheritance(struct task_struct* t, struct task_struct*
716 struct gedf_cpu_entry* linked_on; 737 struct gedf_cpu_entry* linked_on;
717 int check_preempt = 0; 738 int check_preempt = 0;
718 739
719 struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; 740 struct reservation *t_res, *prio_inh_res;
720 struct reservation *prio_inh_res = (struct reservation *) tsk_rt(prio_inh)->plugin_state;
721
722 struct reservation_environment *env = t_res->par_env;
723
724 struct gedf_reservation_environment *gedf_env; 741 struct gedf_reservation_environment *gedf_env;
725 gedf_env = container_of(env, struct gedf_reservation_environment, env);
726
727 struct gedf_reservation *gedf_res; 742 struct gedf_reservation *gedf_res;
743
744 t_res = (struct reservation *) tsk_rt(t)->plugin_state;
728 gedf_res = container_of(t_res, struct gedf_reservation, res); 745 gedf_res = container_of(t_res, struct gedf_reservation, res);
729 746
747 prio_inh_res = (struct reservation *) tsk_rt(prio_inh)->plugin_state;
748
749 gedf_env = container_of(t_res->par_env, struct gedf_reservation_environment, env);
750
730 raw_spin_lock(&gedf_env->domain.ready_lock); 751 raw_spin_lock(&gedf_env->domain.ready_lock);
731 752
732 TRACE_TASK(t, "inherits priority from %s/%d\n", prio_inh->comm, prio_inh->pid); 753 TRACE_TASK(t, "inherits priority from %s/%d\n", prio_inh->comm, prio_inh->pid);
@@ -785,22 +806,23 @@ static void set_priority_inheritance(struct task_struct* t, struct task_struct*
785/* called with IRQs off */ 806/* called with IRQs off */
786static void clear_priority_inheritance(struct task_struct* t) 807static void clear_priority_inheritance(struct task_struct* t)
787{ 808{
788 struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; 809 struct reservation *t_res;
789 810 struct gedf_reservation *gedf_res;
790 struct reservation_environment *env = t_res->par_env; 811 struct reservation_environment *env;
791
792 struct gedf_reservation_environment *gedf_env; 812 struct gedf_reservation_environment *gedf_env;
793 gedf_env = container_of(env, struct gedf_reservation_environment, env); 813 struct gedf_cpu_entry *entry;
794 814
795 struct gedf_reservation *gedf_res; 815 t_res = (struct reservation *) tsk_rt(t)->plugin_state;
796 gedf_res = container_of(t_res, struct gedf_reservation, res); 816 gedf_res = container_of(t_res, struct gedf_reservation, res);
797 817
818 env = t_res->par_env;
819 gedf_env = container_of(env, struct gedf_reservation_environment, env);
820
798 raw_spin_lock(&gedf_env->domain.ready_lock); 821 raw_spin_lock(&gedf_env->domain.ready_lock);
799 822
800 /* A job only stops inheriting a priority when it releases a 823 /* A job only stops inheriting a priority when it releases a
801 * resource. Thus we can make the following assumption.*/ 824 * resource. Thus we can make the following assumption.*/
802 int cpu = smp_processor_id(); 825 entry = &gedf_env->cpu_entries[smp_processor_id()];
803 struct gedf_cpu_entry *entry = &gedf_env->cpu_entries[cpu];
804 BUG_ON(entry->scheduled != gedf_res); 826 BUG_ON(entry->scheduled != gedf_res);
805 827
806 TRACE_TASK(t, "priority restored\n"); 828 TRACE_TASK(t, "priority restored\n");
@@ -938,10 +960,15 @@ static struct task_struct* omlp_find_hp_waiter(struct omlp_semaphore *sem,
938 960
939int gedf_env_omlp_lock(struct litmus_lock* l) 961int gedf_env_omlp_lock(struct litmus_lock* l)
940{ 962{
963 // The task and the semaphore
941 struct task_struct* t = current; 964 struct task_struct* t = current;
942 struct omlp_semaphore *sem = omlp_from_lock(l); 965 struct omlp_semaphore *sem = omlp_from_lock(l);
943 prio_wait_queue_t wait; 966 // Various scheduler entities
967 struct reservation *t_res, *o_res;
968 struct gedf_reservation *gedf_res;
969 // Waiting
944 unsigned long flags; 970 unsigned long flags;
971 prio_wait_queue_t wait;
945 972
946 if (!is_realtime(t)) 973 if (!is_realtime(t))
947 return -EPERM; 974 return -EPERM;
@@ -951,9 +978,8 @@ int gedf_env_omlp_lock(struct litmus_lock* l)
951 if (tsk_rt(t)->num_locks_held) 978 if (tsk_rt(t)->num_locks_held)
952 return -EBUSY; 979 return -EBUSY;
953 980
954 struct reservation *t_res = (struct reservation *) tsk_rt(t)->plugin_state; 981 t_res = (struct reservation *) tsk_rt(t)->plugin_state;
955 982 gedf_res = container_of(t_res, struct gedf_reservation, res);
956 struct gedf_reservation *gedf_res = container_of(t_res, struct gedf_reservation, res);
957 983
958 spin_lock_irqsave(&sem->fifo_wait.lock, flags); 984 spin_lock_irqsave(&sem->fifo_wait.lock, flags);
959 985
@@ -971,7 +997,7 @@ int gedf_env_omlp_lock(struct litmus_lock* l)
971 if (higher_res_prio(t_res, sem->hp_waiter_res)) { 997 if (higher_res_prio(t_res, sem->hp_waiter_res)) {
972 sem->hp_waiter = t; 998 sem->hp_waiter = t;
973 sem->hp_waiter_res = t_res; 999 sem->hp_waiter_res = t_res;
974 struct reservation *o_res = (struct reservation *) tsk_rt(sem->owner)->plugin_state; 1000 o_res = (struct reservation *) tsk_rt(sem->owner)->plugin_state;
975 if (higher_res_prio(t_res, o_res)) { 1001 if (higher_res_prio(t_res, o_res)) {
976 set_priority_inheritance(sem->owner, sem->hp_waiter); 1002 set_priority_inheritance(sem->owner, sem->hp_waiter);
977 } 1003 }
@@ -1005,12 +1031,80 @@ int gedf_env_omlp_lock(struct litmus_lock* l)
1005 return 0; 1031 return 0;
1006} 1032}
1007 1033
1034static int gedf_env_omlp_access_fz_check(struct litmus_lock* l, lt_t fz_len)
1035{
1036 // The task and the semaphore
1037 struct task_struct* t = current;
1038 struct omlp_semaphore *sem = omlp_from_lock(l);
1039 // Various scheduler entities
1040 struct reservation *t_res;
1041 struct gedf_reservation_environment *gedf_env;
1042 struct gedf_reservation *gedf_res;
1043 // Forbidden zones
1044 unsigned int cpu;
1045 lt_t timeslice_end, remaining_component_budget;
1046 struct mtd_reservation *mtd_res;
1047 // Waiting
1048 unsigned long flags;
1049 wait_queue_t wait;
1050
1051 if (!is_realtime(t))
1052 return -EPERM;
1053
1054 if (sem->owner != t) { // does this need a lock around it?
1055 return -EINVAL;
1056 }
1057
1058 t_res = (struct reservation *) tsk_rt(t)->plugin_state;
1059 gedf_res = container_of(t_res, struct gedf_reservation, res);
1060
1061 /* if in a forbidden zone, wait until the next time slice */
1062 /* note that we can't use t_res->par_env->res->cur_budget
1063 * because it is only updated on a call to schedule(), and
1064 * thus might not reflect the current remaining budget
1065 * for the component */
1066 gedf_env = container_of(t_res->par_env, struct gedf_reservation_environment, env);
1067 spin_lock_irqsave(&gedf_env->fz_waiters[0].lock, flags);
1068
1069 cpu = smp_processor_id();
1070
1071 spin_unlock_irqrestore(&gedf_env->fz_waiters[0].lock, flags);
1072 spin_lock_irqsave(&gedf_env->fz_waiters[cpu].lock, flags);
1073
1074 mtd_res = (struct mtd_reservation*)t_res->par_env->res;
1075 timeslice_end = mtd_res->cur_interval[cpu].end + mtd_res->major_cycle_start[cpu];
1076 remaining_component_budget = timeslice_end - litmus_clock();
1077
1078 if (remaining_component_budget < fz_len) {
1079 /* go on a wait queue to be woken up when the parent reservation
1080 * is next scheduled */
1081 init_waitqueue_entry(&wait, t);
1082 set_task_state(t, TASK_UNINTERRUPTIBLE);
1083 __add_wait_queue_tail_exclusive(&gedf_env->fz_waiters[cpu], &wait);
1084
1085 TS_LOCK_SUSPEND;
1086
1087 spin_unlock_irqrestore(&gedf_env->fz_waiters[cpu].lock, flags);
1088
1089 BUG_ON(!gedf_res->linked_on && !bheap_node_in_heap(t_res->heap_node));
1090
1091 schedule();
1092
1093 TS_LOCK_RESUME;
1094 } else {
1095 spin_unlock_irqrestore(&gedf_env->fz_waiters[cpu].lock, flags);
1096 }
1097
1098 return 0;
1099}
1100
1008static int gedf_env_omlp_unlock(struct litmus_lock* l) 1101static int gedf_env_omlp_unlock(struct litmus_lock* l)
1009{ 1102{
1010 struct task_struct *t = current, *next; 1103 struct task_struct *t = current, *next;
1011 struct omlp_semaphore *sem = omlp_from_lock(l); 1104 struct omlp_semaphore *sem = omlp_from_lock(l);
1012 unsigned long flags; 1105 unsigned long flags;
1013 int err = 0; 1106 int err = 0;
1107 struct reservation *n_res;
1014 1108
1015 spin_lock_irqsave(&sem->fifo_wait.lock, flags); 1109 spin_lock_irqsave(&sem->fifo_wait.lock, flags);
1016 1110
@@ -1028,7 +1122,7 @@ static int gedf_env_omlp_unlock(struct litmus_lock* l)
1028 sem->owner = next; 1122 sem->owner = next;
1029 TRACE_CUR("lock ownership passed to %s/%d\n", next->comm, next->pid); 1123 TRACE_CUR("lock ownership passed to %s/%d\n", next->comm, next->pid);
1030 1124
1031 struct reservation *n_res = (struct reservation *) tsk_rt(next)->plugin_state; 1125 n_res = (struct reservation *) tsk_rt(next)->plugin_state;
1032 1126
1033 /* determine new hp_waiter if necessary */ 1127 /* determine new hp_waiter if necessary */
1034 if (next == sem->hp_waiter) { 1128 if (next == sem->hp_waiter) {
@@ -1095,10 +1189,11 @@ static void gedf_env_omlp_free(struct litmus_lock* lock)
1095} 1189}
1096 1190
1097static struct litmus_lock_ops gedf_env_omlp_lock_ops = { 1191static struct litmus_lock_ops gedf_env_omlp_lock_ops = {
1098 .close = gedf_env_omlp_close, 1192 .close = gedf_env_omlp_close,
1099 .lock = gedf_env_omlp_lock, 1193 .lock = gedf_env_omlp_lock,
1100 .unlock = gedf_env_omlp_unlock, 1194 .access_forbidden_zone_check = gedf_env_omlp_access_fz_check,
1101 .deallocate = gedf_env_omlp_free, 1195 .unlock = gedf_env_omlp_unlock,
1196 .deallocate = gedf_env_omlp_free,
1102}; 1197};
1103 1198
1104static struct litmus_lock* gedf_env_new_omlp(void) 1199static struct litmus_lock* gedf_env_new_omlp(void)
@@ -1195,6 +1290,15 @@ long alloc_gedf_reservation_environment(
1195 kfree(gedf_env); 1290 kfree(gedf_env);
1196 return -ENOMEM; 1291 return -ENOMEM;
1197 } 1292 }
1293#ifdef CONFIG_LITMUS_LOCKING
1294 gedf_env->fz_waiters = kzalloc(sizeof(wait_queue_head_t)*total_cpus, GFP_ATOMIC);
1295 if (!gedf_env->fz_waiters) {
1296 kfree(gedf_env->cpu_entries);
1297 kfree(gedf_env->cpu_node);
1298 kfree(gedf_env);
1299 return -ENOMEM;
1300 }
1301#endif
1198 1302
1199 /* set environment callback actions */ 1303 /* set environment callback actions */
1200 gedf_env->env.ops = &gedf_env_ops; 1304 gedf_env->env.ops = &gedf_env_ops;
@@ -1213,6 +1317,13 @@ long alloc_gedf_reservation_environment(
1213 /* initialize environment domain */ 1317 /* initialize environment domain */
1214 rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs); 1318 rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs);
1215 1319
1320#ifdef CONFIG_LITMUS_LOCKING
1321 gedf_env->num_waiter_queues = max_cpus;
1322 for (i = 0; i < max_cpus; i++) {
1323 init_waitqueue_head(&gedf_env->fz_waiters[i]);
1324 }
1325#endif
1326
1216 *_env = gedf_env; 1327 *_env = gedf_env;
1217 return 0; 1328 return 0;
1218} 1329}