From ae9203a19764fd434ded1e4b16ce897566aba63c Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Fri, 2 May 2008 22:53:02 -0400 Subject: LITMUS: add framework for carrying out jobs after dropping rq locks Many things can't be done from within the scheduler. This framework should make it easer to defer them. --- include/litmus/norqlock.h | 26 ++++++++++++++++++++++ kernel/sched.c | 6 ++++- litmus/Makefile | 2 +- litmus/norqlock.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 include/litmus/norqlock.h create mode 100644 litmus/norqlock.c diff --git a/include/litmus/norqlock.h b/include/litmus/norqlock.h new file mode 100644 index 0000000000..e4c1d06f51 --- /dev/null +++ b/include/litmus/norqlock.h @@ -0,0 +1,26 @@ +#ifndef NORQLOCK_H +#define NORQLOCK_H + +typedef void (*work_t)(unsigned long arg); + +struct no_rqlock_work { + int active; + work_t work; + unsigned long arg; + struct no_rqlock_work* next; +}; + +void init_no_rqlock_work(struct no_rqlock_work* w, work_t work, + unsigned long arg); + +void __do_without_rqlock(struct no_rqlock_work *work); + +static inline void do_without_rqlock(struct no_rqlock_work *work) +{ + if (!test_and_set_bit(0, (void*)&work->active)) + __do_without_rqlock(work); +} + +void tick_no_rqlock(void); + +#endif diff --git a/kernel/sched.c b/kernel/sched.c index c52f1b3000..441996e08c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -67,6 +67,8 @@ #include #include +#include + /* * Scheduler clock - returns current time in nanosec units. * This is default implementation. @@ -1654,7 +1656,7 @@ out_running: p->state = TASK_RUNNING; out: task_rq_unlock(rq, &flags); - + tick_no_rqlock(); return success; } @@ -3681,6 +3683,8 @@ need_resched_nonpreemptible: } else spin_unlock_irq(&rq->lock); + tick_no_rqlock(); + if (unlikely(reacquire_kernel_lock(current) < 0)) { cpu = smp_processor_id(); rq = cpu_rq(cpu); diff --git a/litmus/Makefile b/litmus/Makefile index ec088a071b..0e3bedd165 100644 --- a/litmus/Makefile +++ b/litmus/Makefile @@ -6,6 +6,6 @@ obj-y = sched_plugin.o litmus.o sched_trace.o \ edf_common.o jobs.o\ sched_gsn_edf.o sched_psn_edf.o \ rt_domain.o fdso.o sync.o \ - fmlp.o srp.o + fmlp.o srp.o norqlock.o obj-$(CONFIG_FEATHER_TRACE) += trace.o ft_event.o diff --git a/litmus/norqlock.c b/litmus/norqlock.c new file mode 100644 index 0000000000..d0cbe1388e --- /dev/null +++ b/litmus/norqlock.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +#include + +struct worklist { + struct no_rqlock_work* next; +}; + +static DEFINE_PER_CPU(struct worklist, norq_worklist) = {NULL}; + +void init_no_rqlock_work(struct no_rqlock_work* w, work_t work, + unsigned long arg) +{ + w->active = 0; + w->work = work; + w->arg = arg; + w->next = NULL; +} + +void __do_without_rqlock(struct no_rqlock_work *work) +{ + long flags; + struct worklist* wl; + + local_irq_save(flags); + wl = &__get_cpu_var(norq_worklist); + work->next = wl->next; + wl->next = work; + local_irq_restore(flags); +} + +void tick_no_rqlock(void) +{ + long flags; + struct no_rqlock_work *todo, *next; + + local_irq_save(flags); + + next = __get_cpu_var(norq_worklist).next; + __get_cpu_var(norq_worklist).next = NULL; + + while (next) { + todo = next; + next = next->next; + todo->next = NULL; + mb(); + todo->active = 0; + todo->work(todo->arg); + } + + local_irq_restore(flags); +} -- cgit v1.2.2