From f08db18a7b4195691010c7343b998f455c0c9038 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Tue, 4 Mar 2008 15:59:07 -0500 Subject: update SRP impl This is the first step in cleaning up the SRP implementation. --- include/litmus/litmus.h | 2 +- include/litmus/rt_param.h | 6 ---- litmus/litmus.c | 4 +-- litmus/litmus_sem.c | 79 ++++++++++++++++++++++++----------------------- 4 files changed, 43 insertions(+), 48 deletions(-) diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h index 7a27c987b6..512efef341 100644 --- a/include/litmus/litmus.h +++ b/include/litmus/litmus.h @@ -153,7 +153,7 @@ inline static int budget_exhausted(struct task_struct* t) return get_exec_time(t) >= get_exec_cost(t); } -#define is_subject_to_srp(t) ((t)->rt_param.subject_to_srp) + #define is_hrt(t) \ ((t)->rt_param.task_params.class == RT_CLASS_HARD) #define is_srt(t) \ diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index 8ffbf300b0..118e8590fd 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h @@ -73,12 +73,6 @@ struct rt_param { /* is the task sleeping? */ unsigned int flags:8; - /* Did this task register any SRP controlled resource accesses? - * This, of course, should only ever be true under partitioning. - * However, this limitation is not currently enforced. - */ - unsigned int subject_to_srp:1; - /* user controlled parameters */ struct rt_task task_params; diff --git a/litmus/litmus.c b/litmus/litmus.c index 8ab96452e6..2909d5c04e 100644 --- a/litmus/litmus.c +++ b/litmus/litmus.c @@ -153,7 +153,7 @@ asmlinkage long sys_complete_job(void) * appropriate queue and call schedule */ retval = litmus->complete_job(); - if (!retval && is_subject_to_srp(current)) + if (!retval) srp_ceiling_block(); out: return retval; @@ -207,7 +207,7 @@ asmlinkage long sys_wait_for_job_release(unsigned int job) /* We still have to honor the SRP after the actual release. */ - if (!retval && is_subject_to_srp(current)) + if (!retval) srp_ceiling_block(); out: return retval; diff --git a/litmus/litmus_sem.c b/litmus/litmus_sem.c index f52941c5ca..f7047058d1 100644 --- a/litmus/litmus_sem.c +++ b/litmus/litmus_sem.c @@ -313,6 +313,8 @@ struct srp { }; +atomic_t srp_objects_in_use = ATOMIC_INIT(0); + DEFINE_PER_CPU(struct srp, srp); #define system_ceiling(srp) list2prio(srp->ceiling.next) @@ -343,6 +345,9 @@ static void srp_add_prio(struct srp* srp, struct srp_priority* prio) list_add_tail(&prio->list, &srp->ceiling); } +#define UNDEF_SEM -2 + + /* struct for uniprocessor SRP "semaphore" */ struct srp_semaphore { struct srp_priority ceiling; @@ -366,18 +371,47 @@ static void* create_srp_semaphore(void) INIT_LIST_HEAD(&sem->ceiling.list); sem->ceiling.period = 0; sem->claimed = 0; - sem->cpu = get_partition(current); + sem->cpu = UNDEF_SEM; + atomic_inc(&srp_objects_in_use); return sem; } +static noinline int open_srp_semaphore(struct od_table_entry* entry, void* __user arg) +{ + struct srp_semaphore* sem = (struct srp_semaphore*) entry->obj->obj; + int ret = 0; + struct task_struct* t = current; + struct srp_priority t_prio; + + TRACE("opening SRP semaphore %p, cpu=%d\n", sem, sem->cpu); + + if (sem->cpu == UNDEF_SEM) + sem->cpu = get_partition(t); + else if (sem->cpu != get_partition(t)) + ret = -EPERM; + + if (ret == 0) { + t_prio.period = get_rt_period(t); + t_prio.pid = t->pid; + if (srp_higher_prio(&t_prio, &sem->ceiling)) { + sem->ceiling.period = t_prio.period; + sem->ceiling.pid = t_prio.pid; + } + } + + return ret; +} + static void destroy_srp_semaphore(void* sem) { /* XXX invariants */ + atomic_dec(&srp_objects_in_use); kfree(sem); } struct fdso_ops srp_sem_ops = { .create = create_srp_semaphore, + .open = open_srp_semaphore, .destroy = destroy_srp_semaphore }; @@ -470,46 +504,9 @@ asmlinkage long sys_srp_up(int sem_od) return ret; } -/* Indicate that task will use a resource associated with a given - * semaphore. Should be done *a priori* before RT task system is - * executed, so this does *not* update the system priority - * ceiling! (The ceiling would be meaningless anyway, as the SRP - * breaks without this a priori knowledge.) - */ asmlinkage long sys_reg_task_srp_sem(int sem_od) { - /* - * FIXME: This whole concept is rather brittle! - * There must be a better solution. Maybe register on - * first reference? - */ - - struct task_struct *t = current; - struct srp_priority t_prio; - struct srp_semaphore* sem; - - sem = lookup_srp_sem(sem_od); - - if (!sem) - return -EINVAL; - - if (!is_realtime(t)) - return -EPERM; - - if (sem->cpu != get_partition(t)) - return -EINVAL; - - preempt_disable(); - t->rt_param.subject_to_srp = 1; - t_prio.period = get_rt_period(t); - t_prio.pid = t->pid; - if (srp_higher_prio(&t_prio, &sem->ceiling)) { - sem->ceiling.period = t_prio.period; - sem->ceiling.pid = t_prio.pid; - } - - preempt_enable(); - + /* unused */ return 0; } @@ -539,6 +536,10 @@ void srp_ceiling_block(void) .task_list = {NULL, NULL} }; + /* bail out early if there aren't any SRP resources around */ + if (!atomic_read(&srp_objects_in_use)) + return; + preempt_disable(); if (!srp_exceeds_ceiling(tsk, &__get_cpu_var(srp))) { tsk->state = TASK_UNINTERRUPTIBLE; -- cgit v1.2.2