diff options
| -rw-r--r-- | include/litmus/reservations/ext_reservation.h | 13 | ||||
| -rw-r--r-- | include/litmus/reservations/gedf_reservation.h | 28 | ||||
| -rw-r--r-- | include/litmus/reservations/table_driven_ext_reservation.h | 26 | ||||
| -rw-r--r-- | include/litmus/rt_param.h | 21 | ||||
| -rw-r--r-- | litmus/reservations/ext_reservation.c | 8 | ||||
| -rw-r--r-- | litmus/reservations/gedf_reservation.c | 268 | ||||
| -rw-r--r-- | litmus/sched_ext_res.c | 7 |
7 files changed, 204 insertions, 167 deletions
diff --git a/include/litmus/reservations/ext_reservation.h b/include/litmus/reservations/ext_reservation.h index 68784f71a268..40c9cd9e098e 100644 --- a/include/litmus/reservations/ext_reservation.h +++ b/include/litmus/reservations/ext_reservation.h | |||
| @@ -25,14 +25,12 @@ typedef void (*drain_budget_t) ( | |||
| 25 | 25 | ||
| 26 | typedef struct task_struct* (*dispatch_client_t) ( | 26 | typedef struct task_struct* (*dispatch_client_t) ( |
| 27 | struct reservation *reservation, | 27 | struct reservation *reservation, |
| 28 | lt_t now, | ||
| 29 | int cpu | 28 | int cpu |
| 30 | ); | 29 | ); |
| 31 | 30 | ||
| 32 | /* When reservation is scheduled. */ | 31 | /* When reservation is scheduled. */ |
| 33 | typedef void (*on_schedule_t) ( | 32 | typedef void (*on_schedule_t) ( |
| 34 | struct reservation *reservation, | 33 | struct reservation *reservation, |
| 35 | lt_t now, | ||
| 36 | int cpu | 34 | int cpu |
| 37 | ); | 35 | ); |
| 38 | 36 | ||
| @@ -59,16 +57,12 @@ struct reservation { | |||
| 59 | 57 | ||
| 60 | /* exact meaning defined by impl. */ | 58 | /* exact meaning defined by impl. */ |
| 61 | lt_t priority; | 59 | lt_t priority; |
| 62 | lt_t cur_budget; | ||
| 63 | lt_t replenishment_time; | 60 | lt_t replenishment_time; |
| 64 | 61 | ||
| 65 | /* budget stats */ | 62 | /* budget stats */ |
| 66 | lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */ | 63 | lt_t budget_consumed; /* how much budget consumed in this allocation cycle? */ |
| 67 | lt_t budget_consumed_total; | 64 | lt_t budget_consumed_total; |
| 68 | 65 | ||
| 69 | /* list of registered budget callbacks */ | ||
| 70 | struct budget_notifier_list budget_notifiers; | ||
| 71 | |||
| 72 | /* for memory reclamation purposes */ | 66 | /* for memory reclamation purposes */ |
| 73 | struct list_head all_list; | 67 | struct list_head all_list; |
| 74 | 68 | ||
| @@ -84,7 +78,10 @@ struct reservation { | |||
| 84 | struct list_head ln; | 78 | struct list_head ln; |
| 85 | }; | 79 | }; |
| 86 | 80 | ||
| 87 | void init_ext_reservation(struct reservation* res); | 81 | void init_ext_reservation( |
| 82 | struct reservation* res, | ||
| 83 | unsigned int id, | ||
| 84 | struct reservation_ops* ops); | ||
| 88 | 85 | ||
| 89 | void clean_up_ext_reservation(struct reservation* res); | 86 | void clean_up_ext_reservation(struct reservation* res); |
| 90 | 87 | ||
| @@ -96,12 +93,10 @@ typedef void (*env_update_time_t) ( | |||
| 96 | 93 | ||
| 97 | typedef struct task_struct* (*env_dispatch_t) ( | 94 | typedef struct task_struct* (*env_dispatch_t) ( |
| 98 | struct reservation_environment* env, | 95 | struct reservation_environment* env, |
| 99 | lt_t now, | ||
| 100 | int cpu); | 96 | int cpu); |
| 101 | 97 | ||
| 102 | typedef void (*env_resume_t) ( | 98 | typedef void (*env_resume_t) ( |
| 103 | struct reservation_environment* env, | 99 | struct reservation_environment* env, |
| 104 | lt_t now, | ||
| 105 | int cpu); | 100 | int cpu); |
| 106 | 101 | ||
| 107 | typedef void (*env_suspend_t) ( | 102 | typedef void (*env_suspend_t) ( |
diff --git a/include/litmus/reservations/gedf_reservation.h b/include/litmus/reservations/gedf_reservation.h index 57f2fa7f00fc..2adaaabbcaf4 100644 --- a/include/litmus/reservations/gedf_reservation.h +++ b/include/litmus/reservations/gedf_reservation.h | |||
| @@ -8,22 +8,22 @@ | |||
| 8 | #include <litmus/reservations/ext_reservation.h> | 8 | #include <litmus/reservations/ext_reservation.h> |
| 9 | 9 | ||
| 10 | /* ************************************************************************** */ | 10 | /* ************************************************************************** */ |
| 11 | struct cpu_entry { | ||
| 12 | int id; | ||
| 13 | struct hrtimer timer; | ||
| 14 | struct bheap_node* hn; | ||
| 15 | struct reservation* linked; | ||
| 16 | struct reservation* scheduled; | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct gedf_reservation { | 11 | struct gedf_reservation { |
| 20 | struct reservation res; | 12 | struct reservation res; |
| 21 | struct cpu_entry* linked_on; | 13 | struct cpu_entry* linked_on; |
| 22 | struct cpu_entry* scheduled_on; | 14 | lt_t cur_budget; |
| 23 | int will_remove; | 15 | int will_remove; |
| 24 | int blocked; | 16 | int blocked; |
| 25 | }; | 17 | }; |
| 26 | 18 | ||
| 19 | struct cpu_entry { | ||
| 20 | int id; | ||
| 21 | struct hrtimer timer; | ||
| 22 | struct bheap_node* hn; | ||
| 23 | struct gedf_reservation* linked; | ||
| 24 | struct gedf_reservation* scheduled; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct gedf_task_reservation { | 27 | struct gedf_task_reservation { |
| 28 | struct gedf_reservation gedf_res; | 28 | struct gedf_reservation gedf_res; |
| 29 | struct task_struct* task; | 29 | struct task_struct* task; |
| @@ -52,13 +52,15 @@ long alloc_gedf_task_reservation( | |||
| 52 | /* environment for scheduling reservations via gedf */ | 52 | /* environment for scheduling reservations via gedf */ |
| 53 | struct gedf_reservation_environment { | 53 | struct gedf_reservation_environment { |
| 54 | struct reservation_environment env; | 54 | struct reservation_environment env; |
| 55 | |||
| 56 | /* list of all reservations scheduled by environment */ | ||
| 55 | struct list_head all_reservations; | 57 | struct list_head all_reservations; |
| 58 | |||
| 56 | /* number of active cpus in reservation */ | 59 | /* number of active cpus in reservation */ |
| 57 | int num_cpus; | 60 | volatile int num_cpus; |
| 61 | |||
| 58 | /* array of gedf cpu entries */ | 62 | /* array of gedf cpu entries */ |
| 59 | struct cpu_entry cpu_entries[NR_CPUS]; | 63 | struct cpu_entry cpu_entries[NR_CPUS]; |
| 60 | /* smp_processor_id to environment cpu array offset mapping */ | ||
| 61 | int cpu_mapping[NR_CPUS]; | ||
| 62 | 64 | ||
| 63 | /* used to order cpus for gedf purposes */ | 65 | /* used to order cpus for gedf purposes */ |
| 64 | struct bheap cpu_heap; | 66 | struct bheap cpu_heap; |
| @@ -69,7 +71,7 @@ struct gedf_reservation_environment { | |||
| 69 | 71 | ||
| 70 | long alloc_gedf_reservation_environment( | 72 | long alloc_gedf_reservation_environment( |
| 71 | struct gedf_reservation_environment** _env, | 73 | struct gedf_reservation_environment** _env, |
| 72 | int num_cpus | 74 | int max_cpus |
| 73 | ); | 75 | ); |
| 74 | 76 | ||
| 75 | #endif | 77 | #endif |
diff --git a/include/litmus/reservations/table_driven_ext_reservation.h b/include/litmus/reservations/table_driven_ext_reservation.h index 414791ee9261..51c32eadb419 100644 --- a/include/litmus/reservations/table_driven_ext_reservation.h +++ b/include/litmus/reservations/table_driven_ext_reservation.h | |||
| @@ -12,23 +12,21 @@ struct cpu_entry { | |||
| 12 | struct reservation* scheduled; | 12 | struct reservation* scheduled; |
| 13 | }; | 13 | }; |
| 14 | 14 | ||
| 15 | struct gedf_reservation { | 15 | struct mtd_reservation { |
| 16 | struct reservation res; | 16 | struct reservation res; |
| 17 | struct cpu_entry linked_on; | 17 | lt_t major_cycle; |
| 18 | struct cpu_entry scheduled_on; | 18 | unsigned int interval_index[NR_CPUS]; |
| 19 | int will_remove; | 19 | unsigned int num_intervals[NR_CPUS]; |
| 20 | int blocked; | 20 | struct lt_interval* intervals[NR_CPUS]; |
| 21 | lt_t period; | 21 | |
| 22 | lt_t relative_deadline; | 22 | int num_cur_intervals; |
| 23 | lt_t exec_cost; | 23 | struct lt_interval cur_interval[NR_CPUS]; |
| 24 | lt_t major_cycle_start; | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | long alloc_gedf_reservation( | 27 | long alloc_mtd_reservation( |
| 27 | struct reservation** _res, | 28 | struct reservation_config* config, |
| 28 | int id, | 29 | struct reservation** _res |
| 29 | lt_t exec_cost, | ||
| 30 | lt_t period, | ||
| 31 | lt_t relative_deadline | ||
| 32 | ); | 30 | ); |
| 33 | 31 | ||
| 34 | /* environment for scheduling reservations via gedf */ | 32 | /* environment for scheduling reservations via gedf */ |
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index 9b291343714f..29bf745b4497 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
| @@ -110,6 +110,27 @@ struct reservation_config { | |||
| 110 | }; | 110 | }; |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | struct ext_reservation_config { | ||
| 114 | unsigned int id; | ||
| 115 | lt_t priority; | ||
| 116 | int cpu; | ||
| 117 | |||
| 118 | union { | ||
| 119 | struct { | ||
| 120 | lt_t period; | ||
| 121 | lt_t budget; | ||
| 122 | lt_t relative_deadline; | ||
| 123 | lt_t offset; | ||
| 124 | } polling_params; | ||
| 125 | |||
| 126 | struct { | ||
| 127 | lt_t major_cycle_length; | ||
| 128 | unsigned int num_intervals; | ||
| 129 | struct lt_interval __user *intervals; | ||
| 130 | } table_driven_params; | ||
| 131 | }; | ||
| 132 | }; | ||
| 133 | |||
| 113 | /* regular sporadic task support */ | 134 | /* regular sporadic task support */ |
| 114 | 135 | ||
| 115 | struct rt_task { | 136 | struct rt_task { |
diff --git a/litmus/reservations/ext_reservation.c b/litmus/reservations/ext_reservation.c index 9397241faf99..c39bbae08513 100644 --- a/litmus/reservations/ext_reservation.c +++ b/litmus/reservations/ext_reservation.c | |||
| @@ -6,9 +6,13 @@ | |||
| 6 | extern struct kmem_cache* bheap_node_cache; | 6 | extern struct kmem_cache* bheap_node_cache; |
| 7 | extern struct kmem_cache* release_heap_cache; | 7 | extern struct kmem_cache* release_heap_cache; |
| 8 | 8 | ||
| 9 | void init_ext_reservation(struct reservation* res) | 9 | void init_ext_reservation( |
| 10 | struct reservation* res, | ||
| 11 | unsigned int id, | ||
| 12 | struct reservation_ops* ops) | ||
| 10 | { | 13 | { |
| 11 | memset(res, 0, sizeof(struct reservation)); | 14 | res->id = id; |
| 15 | res->ops = ops; | ||
| 12 | res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC); | 16 | res->heap_node = kmem_cache_alloc(bheap_node_cache, GFP_ATOMIC); |
| 13 | res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC); | 17 | res->rel_heap = kmem_cache_alloc(release_heap_cache, GFP_ATOMIC); |
| 14 | bheap_node_init(&res->heap_node, res); | 18 | bheap_node_init(&res->heap_node, res); |
diff --git a/litmus/reservations/gedf_reservation.c b/litmus/reservations/gedf_reservation.c index 5951963e03ec..aa5eb9d4b821 100644 --- a/litmus/reservations/gedf_reservation.c +++ b/litmus/reservations/gedf_reservation.c | |||
| @@ -59,7 +59,7 @@ static int cpu_lower_prio(struct bheap_node *_a, struct bheap_node *_b) | |||
| 59 | a = _a->value; | 59 | a = _a->value; |
| 60 | b = _b->value; | 60 | b = _b->value; |
| 61 | /* use higher prio here because prio is deadline value */ | 61 | /* use higher prio here because prio is deadline value */ |
| 62 | return higher_prio(a->linked, b->linked); | 62 | return higher_prio(&a->linked->res, &b->linked->res); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap) | 65 | static void update_cpu_position(struct cpu_entry* entry, struct bheap* cpu_heap) |
| @@ -76,14 +76,16 @@ static struct cpu_entry* lowest_prio_cpu(struct bheap* cpu_heap) | |||
| 76 | return hn->value; | 76 | return hn->value; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static int edf_preemption_needed(rt_domain_t* rt, struct reservation* res) | 79 | static int edf_preemption_needed( |
| 80 | struct gedf_reservation_environment* gedf_env, | ||
| 81 | struct gedf_reservation* gedf_res) | ||
| 80 | { | 82 | { |
| 81 | /* we need the read lock for edf_ready_queue */ | 83 | /* we need the read lock for edf_ready_queue */ |
| 82 | /* no need to preempt if there is nothing pending */ | 84 | /* no need to preempt if there is nothing pending */ |
| 83 | if (bheap_empty(&rt->ready_queue)) | 85 | if (bheap_empty(&gedf_env->domain.ready_queue)) |
| 84 | return 0; | 86 | return 0; |
| 85 | /* we need to reschedule if res doesn't exist */ | 87 | /* we need to reschedule if res doesn't exist */ |
| 86 | if (!res) | 88 | if (!gedf_res) |
| 87 | return 1; | 89 | return 1; |
| 88 | 90 | ||
| 89 | /* NOTE: We cannot check for non-preemptibility since we | 91 | /* NOTE: We cannot check for non-preemptibility since we |
| @@ -91,7 +93,7 @@ static int edf_preemption_needed(rt_domain_t* rt, struct reservation* res) | |||
| 91 | */ | 93 | */ |
| 92 | 94 | ||
| 93 | /* reversed */ | 95 | /* reversed */ |
| 94 | return higher_prio(res, __next_ready_res(rt)); | 96 | return higher_prio(&gedf_res->res, __next_ready_res(&gedf_env->domain)); |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | /* ******************************************************************************** */ | 99 | /* ******************************************************************************** */ |
| @@ -107,60 +109,61 @@ static enum hrtimer_restart timer_callback(struct hrtimer* timer) | |||
| 107 | return HRTIMER_NORESTART; | 109 | return HRTIMER_NORESTART; |
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | static void requeue(rt_domain_t* domain, struct reservation* res) { | 112 | static void requeue( |
| 111 | BUG_ON(!res); | 113 | struct gedf_reservation_environment* gedf_env, |
| 112 | BUG_ON(is_queued_res(res)); | 114 | struct gedf_reservation* gedf_res) |
| 115 | { | ||
| 116 | BUG_ON(!gedf_res); | ||
| 117 | BUG_ON(is_queued_res(&gedf_res->res)); | ||
| 113 | 118 | ||
| 114 | if (lt_before_eq(res->replenishment_time, litmus_clock())) | 119 | if (lt_before_eq(gedf_res->res.replenishment_time, litmus_clock())) |
| 115 | __add_ready_res(domain, res); | 120 | __add_ready_res(&gedf_env->domain, &gedf_res->res); |
| 116 | else | 121 | else |
| 117 | __add_release_res(domain, res); | 122 | __add_release_res(&gedf_env->domain, &gedf_res->res); |
| 118 | 123 | ||
| 119 | } | 124 | } |
| 120 | 125 | ||
| 121 | static void link_task_to_cpu( | 126 | static void link_task_to_cpu( |
| 127 | struct gedf_reservation_environment* gedf_env, | ||
| 122 | struct gedf_reservation* linked, | 128 | struct gedf_reservation* linked, |
| 123 | struct cpu_entry* entry, | 129 | struct cpu_entry* entry) |
| 124 | struct gedf_reservation_environment* gedf_env) | ||
| 125 | { | 130 | { |
| 126 | struct cpu_entry* sched = NULL; | ||
| 127 | struct reservation* tmp; | ||
| 128 | 131 | ||
| 129 | if (entry->linked) | 132 | if (entry->linked) |
| 130 | ((struct gedf_reservation*)entry->linked)->linked_on = NULL; | 133 | entry->linked->linked_on = NULL; |
| 131 | 134 | ||
| 132 | if (linked) | 135 | if (linked) |
| 133 | linked->linked_on = entry; | 136 | linked->linked_on = entry; |
| 134 | 137 | ||
| 135 | entry->linked = &linked->res; | 138 | entry->linked = linked; |
| 136 | update_cpu_position(entry, &gedf_env->cpu_heap); | 139 | update_cpu_position(entry, &gedf_env->cpu_heap); |
| 137 | } | 140 | } |
| 138 | 141 | ||
| 139 | static void unlink( | 142 | static void unlink( |
| 140 | struct gedf_reservation* res, | 143 | struct gedf_reservation_environment* gedf_env, |
| 141 | struct gedf_reservation_environment* gedf_env) | 144 | struct gedf_reservation* gedf_res) |
| 142 | { | 145 | { |
| 143 | BUG_ON(!res->linked_on); | 146 | BUG_ON(!gedf_res->linked_on); |
| 144 | if (res->linked_on) { | 147 | if (gedf_res->linked_on) { |
| 145 | link_task_to_cpu(NULL, res->linked_on, gedf_env); | 148 | link_task_to_cpu(gedf_env, NULL, gedf_res->linked_on); |
| 146 | res->linked_on = NULL; | 149 | gedf_res->linked_on = NULL; |
| 147 | } else if (is_queued_res(&res->res)) { | 150 | } else if (is_queued_res(&gedf_res->res)) { |
| 148 | remove_res(&gedf_env->domain, &res->res); | 151 | remove_res(&gedf_env->domain, &gedf_res->res); |
| 149 | } | 152 | } |
| 150 | } | 153 | } |
| 151 | 154 | ||
| 152 | static void check_for_preemptions(struct gedf_reservation_environment* env) | 155 | static void check_for_preemptions(struct gedf_reservation_environment* gedf_env) |
| 153 | { | 156 | { |
| 154 | struct gedf_reservation* res; | 157 | struct gedf_reservation* gedf_res; |
| 155 | struct cpu_entry* last; | 158 | struct cpu_entry* last; |
| 156 | 159 | ||
| 157 | for (last = lowest_prio_cpu(&env->cpu_heap); | 160 | for (last = lowest_prio_cpu(&gedf_env->cpu_heap); |
| 158 | edf_preemption_needed(&env->domain, last->linked); | 161 | edf_preemption_needed(gedf_env, last->linked); |
| 159 | last = lowest_prio_cpu(&env->cpu_heap)) { | 162 | last = lowest_prio_cpu(&gedf_env->cpu_heap)) { |
| 160 | res = (struct gedf_reservation*)__take_ready_res(&env->domain); | 163 | gedf_res = (struct gedf_reservation*)__take_ready_res(&gedf_env->domain); |
| 161 | if (last->linked && last->linked->cur_budget) | 164 | if (last->linked && last->linked->cur_budget) |
| 162 | requeue(&env->domain, last->linked); | 165 | requeue(gedf_env, last->linked); |
| 163 | link_task_to_cpu(res, last, env); | 166 | link_task_to_cpu(gedf_env, gedf_res, last); |
| 164 | preempt(last); | 167 | preempt(last); |
| 165 | } | 168 | } |
| 166 | } | 169 | } |
| @@ -190,23 +193,20 @@ static void gedf_on_preempt( | |||
| 190 | 193 | ||
| 191 | static void gedf_on_schedule( | 194 | static void gedf_on_schedule( |
| 192 | struct reservation *res, | 195 | struct reservation *res, |
| 193 | lt_t now, | ||
| 194 | int cpu) | 196 | int cpu) |
| 195 | { | 197 | { |
| 196 | res->env->ops->resume(res->env, now, cpu); | 198 | res->env->ops->resume(res->env, cpu); |
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | static struct task_struct* gedf_dispatch_client( | 201 | static struct task_struct* gedf_dispatch_client( |
| 200 | struct reservation* res, | 202 | struct reservation* res, |
| 201 | lt_t now, | ||
| 202 | int cpu) | 203 | int cpu) |
| 203 | { | 204 | { |
| 204 | return res->env->ops->dispatch(res->env, now, cpu); | 205 | return res->env->ops->dispatch(res->env, cpu); |
| 205 | } | 206 | } |
| 206 | 207 | ||
| 207 | static struct task_struct* gedf_task_dispatch_client( | 208 | static struct task_struct* gedf_task_dispatch_client( |
| 208 | struct reservation* res, | 209 | struct reservation* res, |
| 209 | lt_t now, | ||
| 210 | int cpu) | 210 | int cpu) |
| 211 | { | 211 | { |
| 212 | return ((struct gedf_task_reservation*)res)->task; | 212 | return ((struct gedf_task_reservation*)res)->task; |
| @@ -219,9 +219,9 @@ static void gedf_replenish_budget( | |||
| 219 | struct gedf_container_reservation* gedf_cont_res = | 219 | struct gedf_container_reservation* gedf_cont_res = |
| 220 | (struct gedf_container_reservation*)res; | 220 | (struct gedf_container_reservation*)res; |
| 221 | res->budget_consumed = 0; | 221 | res->budget_consumed = 0; |
| 222 | res->cur_budget = gedf_cont_res->max_budget; | 222 | gedf_cont_res->gedf_res.cur_budget = gedf_cont_res->max_budget; |
| 223 | res->priority = res->replenishment_time + gedf_cont_res->relative_deadline; | ||
| 224 | res->replenishment_time += gedf_cont_res->period; | 223 | res->replenishment_time += gedf_cont_res->period; |
| 224 | res->priority = res->replenishment_time + gedf_cont_res->relative_deadline; | ||
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | static void gedf_task_replenish_budget( | 227 | static void gedf_task_replenish_budget( |
| @@ -229,6 +229,8 @@ static void gedf_task_replenish_budget( | |||
| 229 | int cpu) | 229 | int cpu) |
| 230 | { | 230 | { |
| 231 | struct task_struct* t = ((struct gedf_task_reservation*)res)->task; | 231 | struct task_struct* t = ((struct gedf_task_reservation*)res)->task; |
| 232 | struct gedf_reservation* gedf_res = container_of(res, struct gedf_reservation, res); | ||
| 233 | |||
| 232 | if (is_completed(t)) { | 234 | if (is_completed(t)) { |
| 233 | sched_trace_task_completion(t, 0); | 235 | sched_trace_task_completion(t, 0); |
| 234 | prepare_for_next_period(t); | 236 | prepare_for_next_period(t); |
| @@ -243,7 +245,7 @@ static void gedf_task_replenish_budget( | |||
| 243 | TRACE_TASK(t, "overrun budget!\n"); | 245 | TRACE_TASK(t, "overrun budget!\n"); |
| 244 | } | 246 | } |
| 245 | res->budget_consumed = 0; | 247 | res->budget_consumed = 0; |
| 246 | res->cur_budget = get_exec_cost(t); | 248 | gedf_res->cur_budget = get_exec_cost(t); |
| 247 | } | 249 | } |
| 248 | 250 | ||
| 249 | static void gedf_drain_budget( | 251 | static void gedf_drain_budget( |
| @@ -251,10 +253,12 @@ static void gedf_drain_budget( | |||
| 251 | lt_t how_much, | 253 | lt_t how_much, |
| 252 | int cpu) | 254 | int cpu) |
| 253 | { | 255 | { |
| 254 | if (how_much > res->cur_budget) | 256 | struct gedf_reservation* gedf_res = container_of(res, struct gedf_reservation, res); |
| 255 | res->cur_budget = 0; | 257 | |
| 258 | if (how_much > gedf_res->cur_budget) | ||
| 259 | gedf_res->cur_budget = 0; | ||
| 256 | else | 260 | else |
| 257 | res->cur_budget -= how_much; | 261 | gedf_res->cur_budget -= how_much; |
| 258 | res->budget_consumed += how_much; | 262 | res->budget_consumed += how_much; |
| 259 | res->budget_consumed_total += how_much; | 263 | res->budget_consumed_total += how_much; |
| 260 | 264 | ||
| @@ -267,10 +271,12 @@ static void gedf_task_drain_budget( | |||
| 267 | int cpu) | 271 | int cpu) |
| 268 | { | 272 | { |
| 269 | struct task_struct* t = ((struct gedf_task_reservation*)res)->task; | 273 | struct task_struct* t = ((struct gedf_task_reservation*)res)->task; |
| 270 | if (how_much > res->cur_budget || is_completed(t)) | 274 | struct gedf_reservation* gedf_res = container_of(res, struct gedf_reservation, res); |
| 271 | res->cur_budget = 0; | 275 | |
| 276 | if (how_much > gedf_res->cur_budget || is_completed(t)) | ||
| 277 | gedf_res->cur_budget = 0; | ||
| 272 | else | 278 | else |
| 273 | res->cur_budget -= how_much; | 279 | gedf_res->cur_budget -= how_much; |
| 274 | res->budget_consumed += how_much; | 280 | res->budget_consumed += how_much; |
| 275 | res->budget_consumed_total += how_much; | 281 | res->budget_consumed_total += how_much; |
| 276 | } | 282 | } |
| @@ -298,20 +304,12 @@ long alloc_gedf_task_reservation( | |||
| 298 | struct task_struct* task) | 304 | struct task_struct* task) |
| 299 | { | 305 | { |
| 300 | struct gedf_task_reservation* gedf_task_res; | 306 | struct gedf_task_reservation* gedf_task_res; |
| 301 | struct gedf_reservation* gedf_res; | ||
| 302 | gedf_task_res = kzalloc(sizeof(*gedf_task_res), GFP_KERNEL); | 307 | gedf_task_res = kzalloc(sizeof(*gedf_task_res), GFP_KERNEL); |
| 303 | if (!gedf_task_res) | 308 | if (!gedf_task_res) |
| 304 | return -ENOMEM; | 309 | return -ENOMEM; |
| 305 | gedf_res = &gedf_task_res->gedf_res; | ||
| 306 | 310 | ||
| 307 | init_ext_reservation(&gedf_res->res); | 311 | memset(gedf_task_res, 0, sizeof(struct gedf_task_reservation)); |
| 308 | gedf_res->res.id = task->pid; | 312 | init_ext_reservation(&gedf_task_res->gedf_res.res, task->pid, &gedf_task_ops); |
| 309 | gedf_res->res.ops = &gedf_task_ops; | ||
| 310 | |||
| 311 | gedf_res->linked_on = NULL; | ||
| 312 | gedf_res->scheduled_on = NULL; | ||
| 313 | gedf_res->will_remove = 0; | ||
| 314 | gedf_res->blocked = 0; | ||
| 315 | 313 | ||
| 316 | gedf_task_res->task = task; | 314 | gedf_task_res->task = task; |
| 317 | tsk_rt(task)->plugin_state = gedf_task_res; | 315 | tsk_rt(task)->plugin_state = gedf_task_res; |
| @@ -328,20 +326,12 @@ long alloc_gedf_container_reservation( | |||
| 328 | lt_t relative_deadline) | 326 | lt_t relative_deadline) |
| 329 | { | 327 | { |
| 330 | struct gedf_container_reservation* gedf_cont_res; | 328 | struct gedf_container_reservation* gedf_cont_res; |
| 331 | struct gedf_reservation* gedf_res; | ||
| 332 | gedf_cont_res = kzalloc(sizeof(*gedf_cont_res), GFP_KERNEL); | 329 | gedf_cont_res = kzalloc(sizeof(*gedf_cont_res), GFP_KERNEL); |
| 333 | if (!gedf_cont_res) | 330 | if (!gedf_cont_res) |
| 334 | return -ENOMEM; | 331 | return -ENOMEM; |
| 335 | gedf_res = &gedf_cont_res->gedf_res; | ||
| 336 | 332 | ||
| 337 | init_ext_reservation(&gedf_res->res); | 333 | memset(gedf_cont_res, 0, sizeof(struct gedf_container_reservation)); |
| 338 | gedf_res->res.id = id; | 334 | init_ext_reservation(&gedf_cont_res->gedf_res.res, id, &gedf_cont_ops); |
| 339 | gedf_res->res.ops = &gedf_cont_ops; | ||
| 340 | |||
| 341 | gedf_res->linked_on = NULL; | ||
| 342 | gedf_res->scheduled_on = NULL; | ||
| 343 | gedf_res->will_remove = 0; | ||
| 344 | gedf_res->blocked = 0; | ||
| 345 | 335 | ||
| 346 | gedf_cont_res->max_budget = max_budget; | 336 | gedf_cont_res->max_budget = max_budget; |
| 347 | gedf_cont_res->period = period; | 337 | gedf_cont_res->period = period; |
| @@ -361,11 +351,15 @@ static void gedf_env_shutdown( | |||
| 361 | unsigned long flags; | 351 | unsigned long flags; |
| 362 | 352 | ||
| 363 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 353 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 354 | |||
| 364 | suspend_releases(&gedf_env->domain); | 355 | suspend_releases(&gedf_env->domain); |
| 356 | |||
| 365 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 357 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 358 | /* cancel all budget tracking hrtimers */ | ||
| 366 | for_each_online_cpu(i) { | 359 | for_each_online_cpu(i) { |
| 367 | hrtimer_cancel(&gedf_env->cpu_entries[i].timer); | 360 | hrtimer_cancel(&gedf_env->cpu_entries[i].timer); |
| 368 | } | 361 | } |
| 362 | /* call shutdown on all scheduled reservations */ | ||
| 369 | while (!list_empty(&gedf_env->all_reservations)) { | 363 | while (!list_empty(&gedf_env->all_reservations)) { |
| 370 | res = list_first_entry(&gedf_env->all_reservations, | 364 | res = list_first_entry(&gedf_env->all_reservations, |
| 371 | struct reservation, all_list); | 365 | struct reservation, all_list); |
| @@ -373,6 +367,8 @@ static void gedf_env_shutdown( | |||
| 373 | res->ops->shutdown(res); | 367 | res->ops->shutdown(res); |
| 374 | } | 368 | } |
| 375 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 369 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 370 | |||
| 371 | /* free memory */ | ||
| 376 | kfree(env); | 372 | kfree(env); |
| 377 | } | 373 | } |
| 378 | 374 | ||
| @@ -389,13 +385,14 @@ static void gedf_env_remove_res( | |||
| 389 | 385 | ||
| 390 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 386 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 391 | gedf_res = container_of(res, struct gedf_reservation, res); | 387 | gedf_res = container_of(res, struct gedf_reservation, res); |
| 388 | |||
| 392 | gedf_res->will_remove = complete; | 389 | gedf_res->will_remove = complete; |
| 393 | gedf_res->blocked = !complete; | 390 | gedf_res->blocked = !complete; |
| 391 | |||
| 394 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 392 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 395 | list_del_init(&gedf_res->res.all_list); | 393 | list_del_init(&gedf_res->res.all_list); |
| 396 | unlink(gedf_res, gedf_env); | 394 | unlink(gedf_env, gedf_res); |
| 397 | if (gedf_res->scheduled_on) | 395 | check_for_preemptions(gedf_env); |
| 398 | preempt(gedf_res->scheduled_on); | ||
| 399 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 396 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 400 | /* After preempt is called, schedule will update budget tracking. | 397 | /* After preempt is called, schedule will update budget tracking. |
| 401 | * In update_time, the environment will detect that res(which is scheduled) | 398 | * In update_time, the environment will detect that res(which is scheduled) |
| @@ -414,114 +411,124 @@ static void gedf_env_add_res( | |||
| 414 | struct gedf_reservation_environment* gedf_env; | 411 | struct gedf_reservation_environment* gedf_env; |
| 415 | struct gedf_reservation* gedf_res; | 412 | struct gedf_reservation* gedf_res; |
| 416 | unsigned long flags; | 413 | unsigned long flags; |
| 414 | |||
| 417 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 415 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 418 | gedf_res = container_of(res, struct gedf_reservation, res); | 416 | gedf_res = container_of(res, struct gedf_reservation, res); |
| 417 | |||
| 419 | res->par_env = env; | 418 | res->par_env = env; |
| 420 | gedf_res->will_remove = 0; | 419 | gedf_res->will_remove = 0; |
| 421 | gedf_res->blocked = 0; | 420 | gedf_res->blocked = 0; |
| 422 | 421 | ||
| 423 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 422 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 424 | list_add(&gedf_res->res.all_list, &gedf_env->all_reservations); | 423 | list_add(&gedf_res->res.all_list, &gedf_env->all_reservations); |
| 425 | requeue(&gedf_env->domain, res); | 424 | requeue(gedf_env, gedf_res); |
| 426 | check_for_preemptions(gedf_env); | 425 | check_for_preemptions(gedf_env); |
| 427 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 426 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 428 | } | 427 | } |
| 429 | 428 | ||
| 429 | /* TODO: currently does not fully support dynamic cores count in environment | ||
| 430 | * when a core is suspended, if the release timer is on that core, it will not be | ||
| 431 | * properly suspended. Only the last core to suspend stops the release timer | ||
| 432 | */ | ||
| 430 | static void gedf_env_suspend( | 433 | static void gedf_env_suspend( |
| 431 | struct reservation_environment* env, | 434 | struct reservation_environment* env, |
| 432 | int cpu) | 435 | int cpu) |
| 433 | { | 436 | { |
| 434 | struct gedf_reservation_environment* gedf_env; | 437 | struct gedf_reservation_environment* gedf_env; |
| 435 | struct cpu_entry* entry; | 438 | struct cpu_entry* entry; |
| 436 | int env_cpu; | ||
| 437 | unsigned long flags; | 439 | unsigned long flags; |
| 438 | 440 | ||
| 439 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 441 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 440 | env_cpu = gedf_env->cpu_mapping[cpu]; | 442 | entry = &gedf_env->cpu_entries[cpu]; |
| 441 | entry = &gedf_env->cpu_entries[env_cpu]; | ||
| 442 | |||
| 443 | if (env_cpu == 0) | ||
| 444 | suspend_releases(&gedf_env->domain); | ||
| 445 | 443 | ||
| 446 | /* this essentially removes the cpu from scheduling consideration */ | ||
| 447 | /* | ||
| 448 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 444 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 445 | |||
| 446 | gedf_env->num_cpus--; | ||
| 447 | /* on env suspension, we need to preempt scheduled tasks, and unlink linked tasks */ | ||
| 449 | if (entry->linked) { | 448 | if (entry->linked) { |
| 450 | unlink(entry->linked, gedf_env); | 449 | unlink(gedf_env, entry->linked); |
| 451 | requeue(entry->linked); | 450 | requeue(gedf_env, entry->linked); |
| 452 | } | 451 | } |
| 452 | if (entry->scheduled && entry->scheduled->res.ops->on_preempt) | ||
| 453 | entry->scheduled->res.ops->on_preempt(&entry->scheduled->res, cpu); | ||
| 454 | |||
| 455 | /* this essentially removes the cpu from scheduling consideration */ | ||
| 453 | bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn); | 456 | bheap_delete(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn); |
| 457 | |||
| 454 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 458 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 455 | */ | 459 | |
| 460 | /* suspends rt_domain releases when the last core of env is preempted */ | ||
| 461 | if (!gedf_env->num_cpus) | ||
| 462 | suspend_releases(&gedf_env->domain); | ||
| 456 | 463 | ||
| 457 | hrtimer_try_to_cancel(&entry->timer); | 464 | hrtimer_try_to_cancel(&entry->timer); |
| 458 | } | 465 | } |
| 459 | 466 | ||
| 460 | static void gedf_env_resume( | 467 | static void gedf_env_resume( |
| 461 | struct reservation_environment* env, | 468 | struct reservation_environment* env, |
| 462 | lt_t now, | ||
| 463 | int cpu) | 469 | int cpu) |
| 464 | { | 470 | { |
| 465 | struct gedf_reservation_environment* gedf_env; | 471 | struct gedf_reservation_environment* gedf_env; |
| 466 | struct cpu_entry* entry; | 472 | struct cpu_entry* entry; |
| 467 | int env_cpu; | ||
| 468 | unsigned long flags; | 473 | unsigned long flags; |
| 469 | 474 | ||
| 470 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 475 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 471 | env_cpu = gedf_env->cpu_mapping[cpu]; | 476 | entry = &gedf_env->cpu_entries[cpu]; |
| 472 | entry = &gedf_env->cpu_entries[env_cpu]; | ||
| 473 | 477 | ||
| 474 | if (env_cpu == 0) | 478 | /* resumes rt_domain releases when the first core of env resumes execution */ |
| 479 | if (!gedf_env->num_cpus) | ||
| 475 | resume_releases(&gedf_env->domain); | 480 | resume_releases(&gedf_env->domain); |
| 476 | 481 | ||
| 477 | /* adds cpu back to scheduling consideration */ | ||
| 478 | /* | ||
| 479 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 482 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 480 | bheap_insert(cpu_lower_prio, cpu_heap, entry->hn); | ||
| 481 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | ||
| 482 | */ | ||
| 483 | 483 | ||
| 484 | if (entry->scheduled) | 484 | gedf_env->num_cpus++; |
| 485 | hrtimer_start( | 485 | /* adds cpu back to scheduling consideration */ |
| 486 | &entry->timer, | 486 | bheap_insert(cpu_lower_prio, &gedf_env->cpu_heap, entry->hn); |
| 487 | ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), | 487 | |
| 488 | HRTIMER_MODE_ABS_PINNED); | 488 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | static struct task_struct* gedf_env_dispatch( | 491 | static struct task_struct* gedf_env_dispatch( |
| 492 | struct reservation_environment* env, | 492 | struct reservation_environment* env, |
| 493 | lt_t now, | ||
| 494 | int cpu) | 493 | int cpu) |
| 495 | { | 494 | { |
| 496 | struct gedf_reservation_environment* gedf_env; | 495 | struct gedf_reservation_environment* gedf_env; |
| 497 | struct cpu_entry* entry; | 496 | struct cpu_entry* entry; |
| 498 | int env_cpu; | ||
| 499 | struct task_struct* next = NULL; | 497 | struct task_struct* next = NULL; |
| 500 | unsigned long flags; | 498 | unsigned long flags; |
| 501 | 499 | ||
| 502 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 500 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 503 | env_cpu = gedf_env->cpu_mapping[cpu]; | 501 | entry = &gedf_env->cpu_entries[cpu]; |
| 504 | entry = &gedf_env->cpu_entries[env_cpu]; | 502 | |
| 503 | BUG_ON(!bheap_node_in_heap(entry->hn)); | ||
| 504 | BUG_ON(entry->id != cpu); | ||
| 505 | 505 | ||
| 506 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 506 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 507 | 507 | ||
| 508 | check_for_preemptions(gedf_env); | 508 | /* update linked if linked for this cpu is empty */ |
| 509 | if (!entry->linked) | ||
| 510 | check_for_preemptions(gedf_env); | ||
| 511 | |||
| 512 | /* if linked and scheduled differ, preempt and schedule accordingly */ | ||
| 509 | if (entry->scheduled != entry->linked) { | 513 | if (entry->scheduled != entry->linked) { |
| 510 | if (entry->scheduled && entry->scheduled->ops->on_preempt) | 514 | if (entry->scheduled && entry->scheduled->res.ops->on_preempt) |
| 511 | entry->scheduled->ops->on_preempt(entry->scheduled, cpu); | 515 | entry->scheduled->res.ops->on_preempt(&entry->scheduled->res, cpu); |
| 512 | if (entry->linked && entry->linked->ops->on_schedule) | 516 | if (entry->linked && entry->linked->res.ops->on_schedule) |
| 513 | entry->linked->ops->on_schedule(entry->linked, now, cpu); | 517 | entry->linked->res.ops->on_schedule(&entry->linked->res, cpu); |
| 514 | entry->scheduled = entry->linked; | 518 | entry->scheduled = entry->linked; |
| 515 | } | 519 | } |
| 516 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 520 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 517 | 521 | ||
| 518 | //TODO: Think about possible problems with entry->scheduled being changed | 522 | //TODO: Think about possible problems with entry->scheduled being changed |
| 519 | if (entry->scheduled) { | 523 | if (entry->scheduled) { |
| 520 | next = entry->scheduled->ops->dispatch_client(entry->scheduled, now, cpu); | 524 | /* let scheduled reservation decide what runs next */ |
| 525 | next = entry->scheduled->res.ops->dispatch_client(&entry->scheduled->res, cpu); | ||
| 526 | /* set timer for budget expiration */ | ||
| 521 | hrtimer_start(&entry->timer, | 527 | hrtimer_start(&entry->timer, |
| 522 | ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), | 528 | ns_to_ktime(litmus_clock() + entry->scheduled->cur_budget), |
| 523 | HRTIMER_MODE_ABS_PINNED); | 529 | HRTIMER_MODE_ABS_PINNED); |
| 524 | } | 530 | } |
| 531 | /* cancel budget timer when no reservation is set to be scheduled */ | ||
| 525 | else | 532 | else |
| 526 | hrtimer_try_to_cancel(&entry->timer); | 533 | hrtimer_try_to_cancel(&entry->timer); |
| 527 | 534 | ||
| @@ -529,43 +536,45 @@ static struct task_struct* gedf_env_dispatch( | |||
| 529 | } | 536 | } |
| 530 | 537 | ||
| 531 | static void gedf_env_update_time( | 538 | static void gedf_env_update_time( |
| 532 | struct reservation_environment* env, lt_t how_much, int cpu) | 539 | struct reservation_environment* env, |
| 540 | lt_t how_much, | ||
| 541 | int cpu) | ||
| 533 | { | 542 | { |
| 534 | struct gedf_reservation_environment* gedf_env; | 543 | struct gedf_reservation_environment* gedf_env; |
| 535 | struct gedf_reservation* gedf_res; | ||
| 536 | struct cpu_entry* entry; | 544 | struct cpu_entry* entry; |
| 537 | int env_cpu; | ||
| 538 | unsigned long flags; | 545 | unsigned long flags; |
| 539 | 546 | ||
| 540 | gedf_env = container_of(env, struct gedf_reservation_environment, env); | 547 | gedf_env = container_of(env, struct gedf_reservation_environment, env); |
| 541 | env_cpu = gedf_env->cpu_mapping[cpu]; | 548 | entry = &gedf_env->cpu_entries[cpu]; |
| 542 | entry = &gedf_env->cpu_entries[env_cpu]; | ||
| 543 | 549 | ||
| 550 | BUG_ON(!bheap_node_in_heap(entry->hn)); | ||
| 544 | BUG_ON(entry->id != cpu); | 551 | BUG_ON(entry->id != cpu); |
| 545 | 552 | ||
| 546 | if (!entry->scheduled) | 553 | if (!entry->scheduled) |
| 547 | return; | 554 | return; |
| 548 | 555 | ||
| 549 | entry->scheduled->ops->drain_budget(entry->scheduled, how_much, cpu); | 556 | /* tells scheduled res to drain its budget */ |
| 550 | gedf_res = container_of(entry->scheduled, struct gedf_reservation, res); | 557 | entry->scheduled->res.ops->drain_budget(&entry->scheduled->res, how_much, cpu); |
| 558 | |||
| 551 | /* if flagged for removal from environment, invoke shutdown callback */ | 559 | /* if flagged for removal from environment, invoke shutdown callback */ |
| 552 | if (gedf_res->will_remove) { | 560 | if (entry->scheduled->will_remove) { |
| 553 | /* assumed to already been unlinked by whatever set will_remove */ | 561 | /* assumed to already been unlinked by whatever set will_remove */ |
| 554 | entry->scheduled->ops->shutdown(entry->scheduled); | 562 | entry->scheduled->res.ops->shutdown(&entry->scheduled->res); |
| 555 | entry->scheduled = NULL; | 563 | entry->scheduled = NULL; |
| 556 | } else if (!entry->scheduled->cur_budget) { | 564 | } else if (!entry->scheduled->cur_budget) { |
| 557 | entry->scheduled->ops->replenish_budget(entry->scheduled, cpu); | 565 | entry->scheduled->res.ops->replenish_budget(&entry->scheduled->res, cpu); |
| 558 | /* unlink and requeue if not blocked */ | 566 | /* unlink and requeue if not blocked */ |
| 559 | if (!gedf_res->blocked) { | 567 | if (!entry->scheduled->blocked) { |
| 560 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); | 568 | raw_spin_lock_irqsave(&gedf_env->domain.ready_lock, flags); |
| 561 | unlink((struct gedf_reservation*)entry->scheduled, gedf_env); | 569 | unlink(gedf_env, entry->scheduled); |
| 562 | requeue(&gedf_env->domain, entry->scheduled); | 570 | requeue(gedf_env, entry->scheduled); |
| 563 | check_for_preemptions(gedf_env); | 571 | check_for_preemptions(gedf_env); |
| 564 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); | 572 | raw_spin_unlock_irqrestore(&gedf_env->domain.ready_lock, flags); |
| 565 | } | 573 | } |
| 566 | } | 574 | } |
| 567 | } | 575 | } |
| 568 | 576 | ||
| 577 | /* callback for how the domain will release jobs */ | ||
| 569 | static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res) | 578 | static void gedf_env_release_jobs(rt_domain_t* rt, struct bheap* res) |
| 570 | { | 579 | { |
| 571 | unsigned long flags; | 580 | unsigned long flags; |
| @@ -590,7 +599,7 @@ static struct reservation_environment_ops gedf_env_ops = { | |||
| 590 | 599 | ||
| 591 | long alloc_gedf_reservation_environment( | 600 | long alloc_gedf_reservation_environment( |
| 592 | struct gedf_reservation_environment** _env, | 601 | struct gedf_reservation_environment** _env, |
| 593 | int num_cpus) | 602 | int max_cpus) |
| 594 | { | 603 | { |
| 595 | struct gedf_reservation_environment* gedf_env; | 604 | struct gedf_reservation_environment* gedf_env; |
| 596 | int i; | 605 | int i; |
| @@ -600,17 +609,26 @@ long alloc_gedf_reservation_environment( | |||
| 600 | return -ENOMEM; | 609 | return -ENOMEM; |
| 601 | 610 | ||
| 602 | memset(gedf_env, 0, sizeof(struct gedf_reservation_environment)); | 611 | memset(gedf_env, 0, sizeof(struct gedf_reservation_environment)); |
| 612 | |||
| 613 | /* set environment callback actions */ | ||
| 603 | gedf_env->env.ops = &gedf_env_ops; | 614 | gedf_env->env.ops = &gedf_env_ops; |
| 615 | |||
| 604 | INIT_LIST_HEAD(&gedf_env->all_reservations); | 616 | INIT_LIST_HEAD(&gedf_env->all_reservations); |
| 605 | gedf_env->num_cpus = 0; | 617 | gedf_env->num_cpus = 0; |
| 606 | bheap_init(&gedf_env->cpu_heap); | 618 | bheap_init(&gedf_env->cpu_heap); |
| 607 | for (i = 0; i < num_cpus; i++) { | 619 | for (i = 0; i < max_cpus; i++) { |
| 608 | gedf_env->cpu_entries[i].hn = &gedf_env->cpu_node[i]; | 620 | gedf_env->cpu_entries[i].id = i; |
| 621 | |||
| 622 | /* initialize cpu timer */ | ||
| 609 | hrtimer_init(&gedf_env->cpu_entries[i].timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); | 623 | hrtimer_init(&gedf_env->cpu_entries[i].timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); |
| 610 | gedf_env->cpu_entries[i].timer.function = timer_callback; | 624 | gedf_env->cpu_entries[i].timer.function = timer_callback; |
| 625 | |||
| 626 | /* initialize cpu heap node */ | ||
| 627 | gedf_env->cpu_entries[i].hn = &gedf_env->cpu_node[i]; | ||
| 611 | bheap_node_init(&gedf_env->cpu_entries[i].hn, &gedf_env->cpu_entries[i]); | 628 | bheap_node_init(&gedf_env->cpu_entries[i].hn, &gedf_env->cpu_entries[i]); |
| 612 | bheap_insert(cpu_lower_prio, &gedf_env->cpu_heap, gedf_env->cpu_entries[i].hn); | ||
| 613 | } | 629 | } |
| 630 | |||
| 631 | /* initialize environment domain */ | ||
| 614 | rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs); | 632 | rt_domain_init(&gedf_env->domain, edf_ready_order, NULL, gedf_env_release_jobs); |
| 615 | 633 | ||
| 616 | *_env = gedf_env; | 634 | *_env = gedf_env; |
diff --git a/litmus/sched_ext_res.c b/litmus/sched_ext_res.c index e79986a12b2c..dd2ae0f02fb3 100644 --- a/litmus/sched_ext_res.c +++ b/litmus/sched_ext_res.c | |||
| @@ -66,13 +66,12 @@ static struct task_struct* ext_res_schedule(struct task_struct * prev) | |||
| 66 | lt_t now, delta; | 66 | lt_t now, delta; |
| 67 | struct task_struct* next; | 67 | struct task_struct* next; |
| 68 | 68 | ||
| 69 | now = litmus_clock(); | 69 | delta = litmus_clock() - *this_cpu_ptr(&last_update_time); |
| 70 | delta = now - *this_cpu_ptr(&last_update_time); | ||
| 71 | 70 | ||
| 72 | //TODO: implement per cpu lt_t to track time | 71 | //TODO: implement per cpu lt_t to track time |
| 73 | 72 | ||
| 74 | gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu); | 73 | gedf_env->env.ops->update_time(&gedf_env->env, delta, cpu); |
| 75 | next = gedf_env->env.ops->dispatch(&gedf_env->env, now, cpu); | 74 | next = gedf_env->env.ops->dispatch(&gedf_env->env, cpu); |
| 76 | 75 | ||
| 77 | *this_cpu_ptr(&last_update_time) = litmus_clock(); | 76 | *this_cpu_ptr(&last_update_time) = litmus_clock(); |
| 78 | 77 | ||
| @@ -318,8 +317,8 @@ static long ext_res_activate_plugin(void) | |||
| 318 | for_each_online_cpu(cpu) { | 317 | for_each_online_cpu(cpu) { |
| 319 | TRACE("Initializing CPU%d...\n", cpu); | 318 | TRACE("Initializing CPU%d...\n", cpu); |
| 320 | *this_cpu_ptr(&last_update_time) = now; | 319 | *this_cpu_ptr(&last_update_time) = now; |
| 321 | gedf_env->cpu_mapping[cpu] = cpu; | ||
| 322 | gedf_env->cpu_entries[cpu].id = cpu; | 320 | gedf_env->cpu_entries[cpu].id = cpu; |
| 321 | gedf_env->env.ops->resume(&gedf_env->env, cpu); | ||
| 323 | } | 322 | } |
| 324 | gedf_env->num_cpus = num_cpus; | 323 | gedf_env->num_cpus = num_cpus; |
| 325 | 324 | ||
