diff options
Diffstat (limited to 'litmus/sched_cedf.c')
-rw-r--r-- | litmus/sched_cedf.c | 343 |
1 files changed, 0 insertions, 343 deletions
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c index 00dabbf65af7..69bba98dc664 100644 --- a/litmus/sched_cedf.c +++ b/litmus/sched_cedf.c | |||
@@ -75,10 +75,6 @@ | |||
75 | #include <litmus/litmus_softirq.h> | 75 | #include <litmus/litmus_softirq.h> |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
79 | #include <linux/interrupt.h> | ||
80 | #endif | ||
81 | |||
82 | #ifdef CONFIG_LITMUS_NVIDIA | 78 | #ifdef CONFIG_LITMUS_NVIDIA |
83 | #include <litmus/nvidia_info.h> | 79 | #include <litmus/nvidia_info.h> |
84 | #endif | 80 | #endif |
@@ -136,10 +132,6 @@ typedef struct clusterdomain { | |||
136 | 132 | ||
137 | #define cluster_lock domain.ready_lock | 133 | #define cluster_lock domain.ready_lock |
138 | 134 | ||
139 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
140 | struct tasklet_head pending_tasklets; | ||
141 | #endif | ||
142 | |||
143 | #ifdef CONFIG_LITMUS_DGL_SUPPORT | 135 | #ifdef CONFIG_LITMUS_DGL_SUPPORT |
144 | raw_spinlock_t dgl_lock; | 136 | raw_spinlock_t dgl_lock; |
145 | #endif | 137 | #endif |
@@ -1103,303 +1095,6 @@ static void cedf_tick(struct task_struct* t) | |||
1103 | } | 1095 | } |
1104 | } | 1096 | } |
1105 | 1097 | ||
1106 | |||
1107 | |||
1108 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
1109 | |||
1110 | static void __do_lit_tasklet(struct tasklet_struct* tasklet, unsigned long flushed) | ||
1111 | { | ||
1112 | if (!atomic_read(&tasklet->count)) { | ||
1113 | if(tasklet->owner) { | ||
1114 | sched_trace_tasklet_begin(tasklet->owner); | ||
1115 | } | ||
1116 | |||
1117 | if (!test_and_clear_bit(TASKLET_STATE_SCHED, &tasklet->state)) | ||
1118 | { | ||
1119 | BUG(); | ||
1120 | } | ||
1121 | TRACE("%s: Invoking tasklet with owner pid = %d (flushed = %d).\n", | ||
1122 | __FUNCTION__, | ||
1123 | (tasklet->owner) ? tasklet->owner->pid : 0, | ||
1124 | (tasklet->owner) ? 0 : 1); | ||
1125 | tasklet->func(tasklet->data); | ||
1126 | tasklet_unlock(tasklet); | ||
1127 | |||
1128 | if(tasklet->owner) { | ||
1129 | sched_trace_tasklet_end(tasklet->owner, flushed); | ||
1130 | } | ||
1131 | } | ||
1132 | else { | ||
1133 | BUG(); | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | |||
1138 | static void do_lit_tasklets(cedf_domain_t* cluster, struct task_struct* sched_task) | ||
1139 | { | ||
1140 | int work_to_do = 1; | ||
1141 | struct tasklet_struct *tasklet = NULL; | ||
1142 | unsigned long flags; | ||
1143 | |||
1144 | while(work_to_do) { | ||
1145 | |||
1146 | TS_NV_SCHED_BOTISR_START; | ||
1147 | |||
1148 | raw_readyq_lock_irqsave(&cluster->cluster_lock, flags); | ||
1149 | |||
1150 | if(cluster->pending_tasklets.head != NULL) { | ||
1151 | // remove tasklet at head. | ||
1152 | struct tasklet_struct *prev = NULL; | ||
1153 | tasklet = cluster->pending_tasklets.head; | ||
1154 | |||
1155 | // find a tasklet with prio to execute; skip ones where | ||
1156 | // sched_task has a higher priority. | ||
1157 | // We use the '!edf' test instead of swaping function arguments since | ||
1158 | // both sched_task and owner could be NULL. In this case, we want to | ||
1159 | // still execute the tasklet. | ||
1160 | while(tasklet && !edf_higher_prio(tasklet->owner, sched_task)) { | ||
1161 | prev = tasklet; | ||
1162 | tasklet = tasklet->next; | ||
1163 | } | ||
1164 | |||
1165 | if(tasklet) { // found something to execuite | ||
1166 | // remove the tasklet from the queue | ||
1167 | if(prev) { | ||
1168 | prev->next = tasklet->next; | ||
1169 | if(prev->next == NULL) { | ||
1170 | TRACE("%s: Tasklet for %d is the last element in tasklet queue.\n", __FUNCTION__, tasklet->owner->pid); | ||
1171 | cluster->pending_tasklets.tail = &(prev); | ||
1172 | } | ||
1173 | } | ||
1174 | else { | ||
1175 | cluster->pending_tasklets.head = tasklet->next; | ||
1176 | if(tasklet->next == NULL) { | ||
1177 | TRACE("%s: Tasklet for %d is the last element in tasklet queue.\n", __FUNCTION__, tasklet->owner->pid); | ||
1178 | cluster->pending_tasklets.tail = &(cluster->pending_tasklets.head); | ||
1179 | } | ||
1180 | } | ||
1181 | } | ||
1182 | else { | ||
1183 | TRACE("%s: No tasklets with eligible priority.\n", __FUNCTION__); | ||
1184 | } | ||
1185 | } | ||
1186 | else { | ||
1187 | TRACE("%s: Tasklet queue is empty.\n", __FUNCTION__); | ||
1188 | } | ||
1189 | |||
1190 | raw_readyq_unlock_irqrestore(&cluster->cluster_lock, flags); | ||
1191 | |||
1192 | if(tasklet) { | ||
1193 | __do_lit_tasklet(tasklet, 0ul); | ||
1194 | tasklet = NULL; | ||
1195 | } | ||
1196 | else { | ||
1197 | work_to_do = 0; | ||
1198 | } | ||
1199 | |||
1200 | TS_NV_SCHED_BOTISR_END; | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | static void __add_pai_tasklet(struct tasklet_struct* tasklet, cedf_domain_t* cluster) | ||
1205 | { | ||
1206 | struct tasklet_struct* step; | ||
1207 | |||
1208 | tasklet->next = NULL; // make sure there are no old values floating around | ||
1209 | |||
1210 | step = cluster->pending_tasklets.head; | ||
1211 | if(step == NULL) { | ||
1212 | TRACE("%s: tasklet queue empty. inserting tasklet for %d at head.\n", __FUNCTION__, tasklet->owner->pid); | ||
1213 | // insert at tail. | ||
1214 | *(cluster->pending_tasklets.tail) = tasklet; | ||
1215 | cluster->pending_tasklets.tail = &(tasklet->next); | ||
1216 | } | ||
1217 | else if((*(cluster->pending_tasklets.tail) != NULL) && | ||
1218 | edf_higher_prio((*(cluster->pending_tasklets.tail))->owner, tasklet->owner)) { | ||
1219 | // insert at tail. | ||
1220 | TRACE("%s: tasklet belongs at end. inserting tasklet for %d at tail.\n", __FUNCTION__, tasklet->owner->pid); | ||
1221 | |||
1222 | *(cluster->pending_tasklets.tail) = tasklet; | ||
1223 | cluster->pending_tasklets.tail = &(tasklet->next); | ||
1224 | } | ||
1225 | else { | ||
1226 | |||
1227 | // insert the tasklet somewhere in the middle. | ||
1228 | |||
1229 | TRACE("%s: tasklet belongs somewhere in the middle.\n", __FUNCTION__); | ||
1230 | |||
1231 | while(step->next && edf_higher_prio(step->next->owner, tasklet->owner)) { | ||
1232 | step = step->next; | ||
1233 | } | ||
1234 | |||
1235 | // insert tasklet right before step->next. | ||
1236 | |||
1237 | TRACE("%s: inserting tasklet for %d between %d and %d.\n", __FUNCTION__, | ||
1238 | tasklet->owner->pid, | ||
1239 | (step->owner) ? | ||
1240 | step->owner->pid : | ||
1241 | -1, | ||
1242 | (step->next) ? | ||
1243 | ((step->next->owner) ? | ||
1244 | step->next->owner->pid : | ||
1245 | -1) : | ||
1246 | -1); | ||
1247 | |||
1248 | tasklet->next = step->next; | ||
1249 | step->next = tasklet; | ||
1250 | |||
1251 | // patch up the head if needed. | ||
1252 | if(cluster->pending_tasklets.head == step) | ||
1253 | { | ||
1254 | TRACE("%s: %d is the new tasklet queue head.\n", __FUNCTION__, tasklet->owner->pid); | ||
1255 | cluster->pending_tasklets.head = tasklet; | ||
1256 | } | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | static void cedf_run_tasklets(struct task_struct* sched_task) | ||
1261 | { | ||
1262 | cedf_domain_t* cluster; | ||
1263 | |||
1264 | preempt_disable(); | ||
1265 | |||
1266 | cluster = (is_realtime(sched_task)) ? | ||
1267 | task_cpu_cluster(sched_task) : | ||
1268 | remote_cluster(smp_processor_id()); | ||
1269 | |||
1270 | if(cluster && cluster->pending_tasklets.head != NULL) { | ||
1271 | TRACE("%s: There are tasklets to process.\n", __FUNCTION__); | ||
1272 | do_lit_tasklets(cluster, sched_task); | ||
1273 | } | ||
1274 | |||
1275 | preempt_enable_no_resched(); | ||
1276 | } | ||
1277 | |||
1278 | |||
1279 | |||
1280 | static int cedf_enqueue_pai_tasklet(struct tasklet_struct* tasklet) | ||
1281 | { | ||
1282 | #if 0 | ||
1283 | cedf_domain_t *cluster = NULL; | ||
1284 | cpu_entry_t *targetCPU = NULL; | ||
1285 | int thisCPU; | ||
1286 | int runLocal = 0; | ||
1287 | int runNow = 0; | ||
1288 | unsigned long flags; | ||
1289 | |||
1290 | if(unlikely((tasklet->owner == NULL) || !is_realtime(tasklet->owner))) | ||
1291 | { | ||
1292 | TRACE("%s: No owner associated with this tasklet!\n", __FUNCTION__); | ||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | cluster = task_cpu_cluster(tasklet->owner); | ||
1297 | |||
1298 | raw_readyq_lock_irqsave(&cluster->cluster_lock, flags); | ||
1299 | |||
1300 | thisCPU = smp_processor_id(); | ||
1301 | |||
1302 | #ifdef CONFIG_SCHED_CPU_AFFINITY | ||
1303 | { | ||
1304 | cpu_entry_t* affinity = NULL; | ||
1305 | |||
1306 | // use this CPU if it is in our cluster and isn't running any RT work. | ||
1307 | if(cpu_isset(thisCPU, *cluster->cpu_map) && (__get_cpu_var(cedf_cpu_entries).linked == NULL)) { | ||
1308 | affinity = &(__get_cpu_var(cedf_cpu_entries)); | ||
1309 | } | ||
1310 | else { | ||
1311 | // this CPU is busy or shouldn't run tasklet in this cluster. | ||
1312 | // look for available near by CPUs. | ||
1313 | // NOTE: Affinity towards owner and not this CPU. Is this right? | ||
1314 | affinity = | ||
1315 | cedf_get_nearest_available_cpu(cluster, | ||
1316 | &per_cpu(cedf_cpu_entries, task_cpu(tasklet->owner))); | ||
1317 | } | ||
1318 | |||
1319 | targetCPU = affinity; | ||
1320 | } | ||
1321 | #endif | ||
1322 | |||
1323 | if (targetCPU == NULL) { | ||
1324 | targetCPU = lowest_prio_cpu(cluster); | ||
1325 | } | ||
1326 | |||
1327 | if (edf_higher_prio(tasklet->owner, targetCPU->linked)) { | ||
1328 | if (thisCPU == targetCPU->cpu) { | ||
1329 | TRACE("%s: Run tasklet locally (and now).\n", __FUNCTION__); | ||
1330 | runLocal = 1; | ||
1331 | runNow = 1; | ||
1332 | } | ||
1333 | else { | ||
1334 | TRACE("%s: Run tasklet remotely (and now).\n", __FUNCTION__); | ||
1335 | runLocal = 0; | ||
1336 | runNow = 1; | ||
1337 | } | ||
1338 | } | ||
1339 | else { | ||
1340 | runLocal = 0; | ||
1341 | runNow = 0; | ||
1342 | } | ||
1343 | |||
1344 | if(!runLocal) { | ||
1345 | // enqueue the tasklet | ||
1346 | __add_pai_tasklet(tasklet, cluster); | ||
1347 | } | ||
1348 | |||
1349 | raw_readyq_unlock_irqrestore(&cluster->cluster_lock, flags); | ||
1350 | |||
1351 | |||
1352 | if (runLocal /*&& runNow */) { // runNow == 1 is implied | ||
1353 | TRACE("%s: Running tasklet on CPU where it was received.\n", __FUNCTION__); | ||
1354 | __do_lit_tasklet(tasklet, 0ul); | ||
1355 | } | ||
1356 | else if (runNow /*&& !runLocal */) { // runLocal == 0 is implied | ||
1357 | TRACE("%s: Triggering CPU %d to run tasklet.\n", __FUNCTION__, targetCPU->cpu); | ||
1358 | preempt(targetCPU); // need to be protected by cluster_lock? | ||
1359 | } | ||
1360 | else { | ||
1361 | TRACE("%s: Scheduling of tasklet was deferred.\n", __FUNCTION__); | ||
1362 | } | ||
1363 | #else | ||
1364 | TRACE("%s: Running tasklet on CPU where it was received.\n", __FUNCTION__); | ||
1365 | __do_lit_tasklet(tasklet, 0ul); | ||
1366 | #endif | ||
1367 | return(1); // success | ||
1368 | } | ||
1369 | |||
1370 | static void cedf_change_prio_pai_tasklet(struct task_struct *old_prio, | ||
1371 | struct task_struct *new_prio) | ||
1372 | { | ||
1373 | struct tasklet_struct* step; | ||
1374 | unsigned long flags; | ||
1375 | cedf_domain_t *cluster; | ||
1376 | struct task_struct *probe; | ||
1377 | |||
1378 | // identify the cluster by the assignment of these tasks. one should | ||
1379 | // be non-NULL. | ||
1380 | probe = (old_prio) ? old_prio : new_prio; | ||
1381 | |||
1382 | if(probe) { | ||
1383 | cluster = task_cpu_cluster(probe); | ||
1384 | |||
1385 | if(cluster->pending_tasklets.head != NULL) { | ||
1386 | raw_readyq_lock_irqsave(&cluster->cluster_lock, flags); | ||
1387 | for(step = cluster->pending_tasklets.head; step != NULL; step = step->next) { | ||
1388 | if(step->owner == old_prio) { | ||
1389 | TRACE("%s: Found tasklet to change: %d\n", __FUNCTION__, step->owner->pid); | ||
1390 | step->owner = new_prio; | ||
1391 | } | ||
1392 | } | ||
1393 | raw_readyq_unlock_irqrestore(&cluster->cluster_lock, flags); | ||
1394 | } | ||
1395 | } | ||
1396 | else { | ||
1397 | TRACE("%s: Both priorities were NULL\n"); | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1401 | #endif // PAI | ||
1402 | |||
1403 | #ifdef CONFIG_LITMUS_LOCKING | 1098 | #ifdef CONFIG_LITMUS_LOCKING |
1404 | static int __increase_priority_inheritance(struct task_struct* t, struct task_struct* prio_inh); | 1099 | static int __increase_priority_inheritance(struct task_struct* t, struct task_struct* prio_inh); |
1405 | #endif | 1100 | #endif |
@@ -1791,10 +1486,6 @@ static void cedf_task_exit(struct task_struct * t) | |||
1791 | unsigned long flags; | 1486 | unsigned long flags; |
1792 | cedf_domain_t *cluster = task_cpu_cluster(t); | 1487 | cedf_domain_t *cluster = task_cpu_cluster(t); |
1793 | 1488 | ||
1794 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
1795 | cedf_change_prio_pai_tasklet(t, NULL); | ||
1796 | #endif | ||
1797 | |||
1798 | /* unlink if necessary */ | 1489 | /* unlink if necessary */ |
1799 | raw_readyq_lock_irqsave(&cluster->cluster_lock, flags); | 1490 | raw_readyq_lock_irqsave(&cluster->cluster_lock, flags); |
1800 | 1491 | ||
@@ -2120,17 +1811,6 @@ static void increase_priority_inheritance(struct task_struct* t, struct task_str | |||
2120 | __increase_priority_inheritance(t, prio_inh); | 1811 | __increase_priority_inheritance(t, prio_inh); |
2121 | 1812 | ||
2122 | raw_readyq_unlock(&cluster->cluster_lock); | 1813 | raw_readyq_unlock(&cluster->cluster_lock); |
2123 | |||
2124 | #if defined(CONFIG_LITMUS_PAI_SOFTIRQD) && defined(CONFIG_LITMUS_NVIDIA) | ||
2125 | if(tsk_rt(t)->held_gpus) { | ||
2126 | int i; | ||
2127 | for(i = find_first_bit(&tsk_rt(t)->held_gpus, BITS_PER_BYTE*sizeof(tsk_rt(t)->held_gpus)); | ||
2128 | i < NV_DEVICE_NUM; | ||
2129 | i = find_next_bit(&tsk_rt(t)->held_gpus, BITS_PER_BYTE*sizeof(tsk_rt(t)->held_gpus), i+1)) { | ||
2130 | pai_check_priority_increase(t, i); | ||
2131 | } | ||
2132 | } | ||
2133 | #endif | ||
2134 | } | 1814 | } |
2135 | 1815 | ||
2136 | /* called with IRQs off */ | 1816 | /* called with IRQs off */ |
@@ -2294,17 +1974,6 @@ static void decrease_priority_inheritance(struct task_struct* t, | |||
2294 | __decrease_priority_inheritance(t, prio_inh, budget_tiggered); | 1974 | __decrease_priority_inheritance(t, prio_inh, budget_tiggered); |
2295 | 1975 | ||
2296 | raw_readyq_unlock(&cluster->cluster_lock); | 1976 | raw_readyq_unlock(&cluster->cluster_lock); |
2297 | |||
2298 | #if defined(CONFIG_LITMUS_PAI_SOFTIRQD) && defined(CONFIG_LITMUS_NVIDIA) | ||
2299 | if(tsk_rt(t)->held_gpus) { | ||
2300 | int i; | ||
2301 | for(i = find_first_bit(&tsk_rt(t)->held_gpus, BITS_PER_BYTE*sizeof(tsk_rt(t)->held_gpus)); | ||
2302 | i < NV_DEVICE_NUM; | ||
2303 | i = find_next_bit(&tsk_rt(t)->held_gpus, BITS_PER_BYTE*sizeof(tsk_rt(t)->held_gpus), i+1)) { | ||
2304 | pai_check_priority_decrease(t, i); | ||
2305 | } | ||
2306 | } | ||
2307 | #endif | ||
2308 | } | 1977 | } |
2309 | 1978 | ||
2310 | 1979 | ||
@@ -2740,13 +2409,6 @@ static long cedf_activate_plugin(void) | |||
2740 | INIT_BINHEAP_HANDLE(&(cedf[i].cpu_heap), cpu_lower_prio); | 2409 | INIT_BINHEAP_HANDLE(&(cedf[i].cpu_heap), cpu_lower_prio); |
2741 | edf_domain_init(&(cedf[i].domain), NULL, cedf_release_jobs); | 2410 | edf_domain_init(&(cedf[i].domain), NULL, cedf_release_jobs); |
2742 | 2411 | ||
2743 | |||
2744 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
2745 | cedf[i].pending_tasklets.head = NULL; | ||
2746 | cedf[i].pending_tasklets.tail = &(cedf[i].pending_tasklets.head); | ||
2747 | #endif | ||
2748 | |||
2749 | |||
2750 | if(!zalloc_cpumask_var(&cedf[i].cpu_map, GFP_ATOMIC)) | 2412 | if(!zalloc_cpumask_var(&cedf[i].cpu_map, GFP_ATOMIC)) |
2751 | return -ENOMEM; | 2413 | return -ENOMEM; |
2752 | #ifdef CONFIG_RELEASE_MASTER | 2414 | #ifdef CONFIG_RELEASE_MASTER |
@@ -2864,11 +2526,6 @@ static struct sched_plugin cedf_plugin __cacheline_aligned_in_smp = { | |||
2864 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 2526 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
2865 | .allocate_aff_obs = cedf_allocate_affinity_observer, | 2527 | .allocate_aff_obs = cedf_allocate_affinity_observer, |
2866 | #endif | 2528 | #endif |
2867 | #ifdef CONFIG_LITMUS_PAI_SOFTIRQD | ||
2868 | .enqueue_pai_tasklet = cedf_enqueue_pai_tasklet, | ||
2869 | .change_prio_pai_tasklet = cedf_change_prio_pai_tasklet, | ||
2870 | .run_tasklets = cedf_run_tasklets, | ||
2871 | #endif | ||
2872 | #if defined(CONFIG_LITMUS_NVIDIA) && defined(CONFIG_LITMUS_SOFTIRQD) | 2529 | #if defined(CONFIG_LITMUS_NVIDIA) && defined(CONFIG_LITMUS_SOFTIRQD) |
2873 | .map_gpu_to_cpu = cedf_map_gpu_to_cpu, | 2530 | .map_gpu_to_cpu = cedf_map_gpu_to_cpu, |
2874 | #endif | 2531 | #endif |