aboutsummaryrefslogtreecommitdiffstats
path: root/litmus
diff options
context:
space:
mode:
authorSven Dziadek <s9svdzia@stud.uni-saarland.de>2012-04-16 15:18:09 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2012-07-23 05:57:59 -0400
commitaced1a8244189e4016b1fdef249b3297c09f626d (patch)
tree8188dbfb0708530c2e9c2763a729e58b2f3f5113 /litmus
parent16c1fb2d4ac691e941456a084284020c63fce93a (diff)
P-FP: make PCP available to userspace
Prior to that it was only used internally for DPCP
Diffstat (limited to 'litmus')
-rw-r--r--litmus/fdso.c1
-rw-r--r--litmus/sched_pfp.c140
2 files changed, 141 insertions, 0 deletions
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
31static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) 32static 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
952struct pcp_semaphore { 952struct 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
967static 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
965struct pcp_state { 973struct 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
1214int 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
1235int 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
1252out:
1253 preempt_enable();
1254
1255 return err;
1256}
1257
1258int 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
1283int 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
1303void pfp_pcp_free(struct litmus_lock* lock)
1304{
1305 kfree(pcp_from_lock(lock));
1306}
1307
1308
1309static 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
1318static 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;