aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-02 22:53:02 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-02 22:53:02 -0400
commitae9203a19764fd434ded1e4b16ce897566aba63c (patch)
tree66802ec3ecfd985bcee370b33a42a529b6b692fb
parentd8be518053ec5b66250836f6989d1dffca5b021c (diff)
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.
-rw-r--r--include/litmus/norqlock.h26
-rw-r--r--kernel/sched.c6
-rw-r--r--litmus/Makefile2
-rw-r--r--litmus/norqlock.c56
4 files changed, 88 insertions, 2 deletions
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 @@
1#ifndef NORQLOCK_H
2#define NORQLOCK_H
3
4typedef void (*work_t)(unsigned long arg);
5
6struct no_rqlock_work {
7 int active;
8 work_t work;
9 unsigned long arg;
10 struct no_rqlock_work* next;
11};
12
13void init_no_rqlock_work(struct no_rqlock_work* w, work_t work,
14 unsigned long arg);
15
16void __do_without_rqlock(struct no_rqlock_work *work);
17
18static inline void do_without_rqlock(struct no_rqlock_work *work)
19{
20 if (!test_and_set_bit(0, (void*)&work->active))
21 __do_without_rqlock(work);
22}
23
24void tick_no_rqlock(void);
25
26#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 @@
67#include <asm/tlb.h> 67#include <asm/tlb.h>
68#include <asm/irq_regs.h> 68#include <asm/irq_regs.h>
69 69
70#include <litmus/norqlock.h>
71
70/* 72/*
71 * Scheduler clock - returns current time in nanosec units. 73 * Scheduler clock - returns current time in nanosec units.
72 * This is default implementation. 74 * This is default implementation.
@@ -1654,7 +1656,7 @@ out_running:
1654 p->state = TASK_RUNNING; 1656 p->state = TASK_RUNNING;
1655out: 1657out:
1656 task_rq_unlock(rq, &flags); 1658 task_rq_unlock(rq, &flags);
1657 1659 tick_no_rqlock();
1658 return success; 1660 return success;
1659} 1661}
1660 1662
@@ -3681,6 +3683,8 @@ need_resched_nonpreemptible:
3681 } else 3683 } else
3682 spin_unlock_irq(&rq->lock); 3684 spin_unlock_irq(&rq->lock);
3683 3685
3686 tick_no_rqlock();
3687
3684 if (unlikely(reacquire_kernel_lock(current) < 0)) { 3688 if (unlikely(reacquire_kernel_lock(current) < 0)) {
3685 cpu = smp_processor_id(); 3689 cpu = smp_processor_id();
3686 rq = cpu_rq(cpu); 3690 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 \
6 edf_common.o jobs.o\ 6 edf_common.o jobs.o\
7 sched_gsn_edf.o sched_psn_edf.o \ 7 sched_gsn_edf.o sched_psn_edf.o \
8 rt_domain.o fdso.o sync.o \ 8 rt_domain.o fdso.o sync.o \
9 fmlp.o srp.o 9 fmlp.o srp.o norqlock.o
10 10
11obj-$(CONFIG_FEATHER_TRACE) += trace.o ft_event.o 11obj-$(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 @@
1#include <linux/list.h>
2#include <linux/bitops.h>
3#include <linux/percpu.h>
4#include <linux/module.h>
5#include <linux/smp.h>
6
7#include <litmus/norqlock.h>
8
9struct worklist {
10 struct no_rqlock_work* next;
11};
12
13static DEFINE_PER_CPU(struct worklist, norq_worklist) = {NULL};
14
15void init_no_rqlock_work(struct no_rqlock_work* w, work_t work,
16 unsigned long arg)
17{
18 w->active = 0;
19 w->work = work;
20 w->arg = arg;
21 w->next = NULL;
22}
23
24void __do_without_rqlock(struct no_rqlock_work *work)
25{
26 long flags;
27 struct worklist* wl;
28
29 local_irq_save(flags);
30 wl = &__get_cpu_var(norq_worklist);
31 work->next = wl->next;
32 wl->next = work;
33 local_irq_restore(flags);
34}
35
36void tick_no_rqlock(void)
37{
38 long flags;
39 struct no_rqlock_work *todo, *next;
40
41 local_irq_save(flags);
42
43 next = __get_cpu_var(norq_worklist).next;
44 __get_cpu_var(norq_worklist).next = NULL;
45
46 while (next) {
47 todo = next;
48 next = next->next;
49 todo->next = NULL;
50 mb();
51 todo->active = 0;
52 todo->work(todo->arg);
53 }
54
55 local_irq_restore(flags);
56}