diff options
author | Sven Dziadek <s9svdzia@stud.uni-saarland.de> | 2012-04-16 15:18:09 -0400 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-07-23 05:57:59 -0400 |
commit | aced1a8244189e4016b1fdef249b3297c09f626d (patch) | |
tree | 8188dbfb0708530c2e9c2763a729e58b2f3f5113 | |
parent | 16c1fb2d4ac691e941456a084284020c63fce93a (diff) |
P-FP: make PCP available to userspace
Prior to that it was only used internally for DPCP
-rw-r--r-- | include/litmus/fdso.h | 4 | ||||
-rw-r--r-- | litmus/fdso.c | 1 | ||||
-rw-r--r-- | litmus/sched_pfp.c | 140 |
3 files changed, 144 insertions, 1 deletions
diff --git a/include/litmus/fdso.h b/include/litmus/fdso.h index 2b0537ce7260..f2115b83f1e4 100644 --- a/include/litmus/fdso.h +++ b/include/litmus/fdso.h | |||
@@ -24,7 +24,9 @@ typedef enum { | |||
24 | MPCP_VS_SEM = 3, | 24 | MPCP_VS_SEM = 3, |
25 | DPCP_SEM = 4, | 25 | DPCP_SEM = 4, |
26 | 26 | ||
27 | MAX_OBJ_TYPE = 4 | 27 | PCP_SEM = 5, |
28 | |||
29 | MAX_OBJ_TYPE = 5 | ||
28 | } obj_type_t; | 30 | } obj_type_t; |
29 | 31 | ||
30 | struct inode_obj_id { | 32 | struct inode_obj_id { |
diff --git a/litmus/fdso.c b/litmus/fdso.c index 04c0b55e41d3..cd85b9cd9a0a 100644 --- a/litmus/fdso.c +++ b/litmus/fdso.c | |||
@@ -26,6 +26,7 @@ static const struct fdso_ops* fdso_ops[] = { | |||
26 | &generic_lock_ops, /* MPCP_SEM */ | 26 | &generic_lock_ops, /* MPCP_SEM */ |
27 | &generic_lock_ops, /* MPCP_VS_SEM */ | 27 | &generic_lock_ops, /* MPCP_VS_SEM */ |
28 | &generic_lock_ops, /* DPCP_SEM */ | 28 | &generic_lock_ops, /* DPCP_SEM */ |
29 | &generic_lock_ops, /* PCP_SEM */ | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) | 32 | static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) |
diff --git a/litmus/sched_pfp.c b/litmus/sched_pfp.c index d5dd78d941c6..42d17b0c08fd 100644 --- a/litmus/sched_pfp.c +++ b/litmus/sched_pfp.c | |||
@@ -950,6 +950,8 @@ static struct litmus_lock* pfp_new_mpcp(int vspin) | |||
950 | 950 | ||
951 | 951 | ||
952 | struct pcp_semaphore { | 952 | struct pcp_semaphore { |
953 | struct litmus_lock litmus_lock; | ||
954 | |||
953 | struct list_head ceiling; | 955 | struct list_head ceiling; |
954 | 956 | ||
955 | /* current resource holder */ | 957 | /* current resource holder */ |
@@ -962,6 +964,12 @@ struct pcp_semaphore { | |||
962 | int on_cpu; | 964 | int on_cpu; |
963 | }; | 965 | }; |
964 | 966 | ||
967 | static inline struct pcp_semaphore* pcp_from_lock(struct litmus_lock* lock) | ||
968 | { | ||
969 | return container_of(lock, struct pcp_semaphore, litmus_lock); | ||
970 | } | ||
971 | |||
972 | |||
965 | struct pcp_state { | 973 | struct pcp_state { |
966 | struct list_head system_ceiling; | 974 | struct list_head system_ceiling; |
967 | 975 | ||
@@ -1203,6 +1211,123 @@ static void pcp_init_semaphore(struct pcp_semaphore* sem, int cpu) | |||
1203 | sem->on_cpu = cpu; | 1211 | sem->on_cpu = cpu; |
1204 | } | 1212 | } |
1205 | 1213 | ||
1214 | int pfp_pcp_lock(struct litmus_lock* l) | ||
1215 | { | ||
1216 | struct task_struct* t = current; | ||
1217 | struct pcp_semaphore *sem = pcp_from_lock(l); | ||
1218 | |||
1219 | int eprio = effective_agent_priority(get_priority(t)); | ||
1220 | int from = get_partition(t); | ||
1221 | int to = sem->on_cpu; | ||
1222 | |||
1223 | if (!is_realtime(t) || from != to) | ||
1224 | return -EPERM; | ||
1225 | |||
1226 | preempt_disable(); | ||
1227 | |||
1228 | pcp_raise_ceiling(sem, eprio); | ||
1229 | |||
1230 | preempt_enable(); | ||
1231 | |||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1235 | int pfp_pcp_unlock(struct litmus_lock* l) | ||
1236 | { | ||
1237 | struct task_struct *t = current; | ||
1238 | struct pcp_semaphore *sem = pcp_from_lock(l); | ||
1239 | |||
1240 | int err = 0; | ||
1241 | |||
1242 | preempt_disable(); | ||
1243 | |||
1244 | if (sem->on_cpu != smp_processor_id() || sem->owner != t) { | ||
1245 | err = -EINVAL; | ||
1246 | goto out; | ||
1247 | } | ||
1248 | |||
1249 | /* give it back */ | ||
1250 | pcp_lower_ceiling(sem); | ||
1251 | |||
1252 | out: | ||
1253 | preempt_enable(); | ||
1254 | |||
1255 | return err; | ||
1256 | } | ||
1257 | |||
1258 | int pfp_pcp_open(struct litmus_lock* l, void* __user config) | ||
1259 | { | ||
1260 | struct task_struct *t = current; | ||
1261 | struct pcp_semaphore *sem = pcp_from_lock(l); | ||
1262 | |||
1263 | int cpu, eprio; | ||
1264 | |||
1265 | if (!is_realtime(t)) | ||
1266 | /* we need to know the real-time priority */ | ||
1267 | return -EPERM; | ||
1268 | |||
1269 | if (get_user(cpu, (int*) config)) | ||
1270 | return -EFAULT; | ||
1271 | |||
1272 | /* make sure the resource location matches */ | ||
1273 | if (cpu != sem->on_cpu) | ||
1274 | return -EINVAL; | ||
1275 | |||
1276 | eprio = effective_agent_priority(get_priority(t)); | ||
1277 | |||
1278 | pcp_update_prio_ceiling(sem, eprio); | ||
1279 | |||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | int pfp_pcp_close(struct litmus_lock* l) | ||
1284 | { | ||
1285 | struct task_struct *t = current; | ||
1286 | struct pcp_semaphore *sem = pcp_from_lock(l); | ||
1287 | |||
1288 | int owner = 0; | ||
1289 | |||
1290 | preempt_disable(); | ||
1291 | |||
1292 | if (sem->on_cpu == smp_processor_id()) | ||
1293 | owner = sem->owner == t; | ||
1294 | |||
1295 | preempt_enable(); | ||
1296 | |||
1297 | if (owner) | ||
1298 | pfp_pcp_unlock(l); | ||
1299 | |||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | void pfp_pcp_free(struct litmus_lock* lock) | ||
1304 | { | ||
1305 | kfree(pcp_from_lock(lock)); | ||
1306 | } | ||
1307 | |||
1308 | |||
1309 | static struct litmus_lock_ops pfp_pcp_lock_ops = { | ||
1310 | .close = pfp_pcp_close, | ||
1311 | .lock = pfp_pcp_lock, | ||
1312 | .open = pfp_pcp_open, | ||
1313 | .unlock = pfp_pcp_unlock, | ||
1314 | .deallocate = pfp_pcp_free, | ||
1315 | }; | ||
1316 | |||
1317 | |||
1318 | static struct litmus_lock* pfp_new_pcp(int on_cpu) | ||
1319 | { | ||
1320 | struct pcp_semaphore* sem; | ||
1321 | |||
1322 | sem = kmalloc(sizeof(*sem), GFP_KERNEL); | ||
1323 | if (!sem) | ||
1324 | return NULL; | ||
1325 | |||
1326 | sem->litmus_lock.ops = &pfp_pcp_lock_ops; | ||
1327 | pcp_init_semaphore(sem, on_cpu); | ||
1328 | |||
1329 | return &sem->litmus_lock; | ||
1330 | } | ||
1206 | 1331 | ||
1207 | /* ******************** DPCP support ********************** */ | 1332 | /* ******************** DPCP support ********************** */ |
1208 | 1333 | ||
@@ -1459,6 +1584,21 @@ static long pfp_allocate_lock(struct litmus_lock **lock, int type, | |||
1459 | } else | 1584 | } else |
1460 | err = -ENOMEM; | 1585 | err = -ENOMEM; |
1461 | break; | 1586 | break; |
1587 | |||
1588 | case PCP_SEM: | ||
1589 | /* Priority Ceiling Protocol */ | ||
1590 | if (get_user(cpu, (int*) config)) | ||
1591 | return -EFAULT; | ||
1592 | |||
1593 | if (!cpu_online(cpu)) | ||
1594 | return -EINVAL; | ||
1595 | |||
1596 | *lock = pfp_new_pcp(cpu); | ||
1597 | if (*lock) | ||
1598 | err = 0; | ||
1599 | else | ||
1600 | err = -ENOMEM; | ||
1601 | break; | ||
1462 | }; | 1602 | }; |
1463 | 1603 | ||
1464 | return err; | 1604 | return err; |