aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-02 22:54:44 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-02 22:54:44 -0400
commit89908c1b2f22b19641f5cbc19805be7aed664a8e (patch)
tree933625bbb2454e3341cfbf6c172bb43425f5a1c7
parentae9203a19764fd434ded1e4b16ce897566aba63c (diff)
LITMUS: use no_rqlock_work to avoid ksoftirqd deadlock
We can't use tasklets from within the scheduler. User no_rqlock_work instead.
-rw-r--r--include/litmus/litmus.h5
-rw-r--r--include/litmus/rt_domain.h4
-rw-r--r--include/litmus/rt_param.h14
-rw-r--r--litmus/rt_domain.c15
4 files changed, 26 insertions, 12 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index 8fc9f630c8..a4c49111aa 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -173,7 +173,10 @@ static inline lt_t litmus_clock(void)
173#define ns_to_ktime(t) ktime_add_ns(ktime_set(0, 0), t) 173#define ns_to_ktime(t) ktime_add_ns(ktime_set(0, 0), t)
174 174
175/* The high-resolution release timer for a task. */ 175/* The high-resolution release timer for a task. */
176#define release_timer(t) ((t)->rt_param.job_params.release_timer) 176#define release_timer(t) ((t)->rt_param.release_timer)
177
178/* The high-resolution release timer for a task. */
179#define get_domain(t) ((t)->rt_param.domain)
177 180
178/* Honor the flag in the preempt_count variable that is set 181/* Honor the flag in the preempt_count variable that is set
179 * when scheduling is in progress. 182 * when scheduling is in progress.
diff --git a/include/litmus/rt_domain.h b/include/litmus/rt_domain.h
index 7b2a11c0f2..6489b0c0fd 100644
--- a/include/litmus/rt_domain.h
+++ b/include/litmus/rt_domain.h
@@ -5,7 +5,7 @@
5#ifndef __UNC_RT_DOMAIN_H__ 5#ifndef __UNC_RT_DOMAIN_H__
6#define __UNC_RT_DOMAIN_H__ 6#define __UNC_RT_DOMAIN_H__
7 7
8#include <linux/interrupt.h> 8#include <litmus/norqlock.h>
9 9
10struct _rt_domain; 10struct _rt_domain;
11 11
@@ -13,7 +13,7 @@ typedef int (*check_resched_needed_t)(struct _rt_domain *rt);
13typedef void (*release_job_t)(struct task_struct *t, struct _rt_domain *rt); 13typedef void (*release_job_t)(struct task_struct *t, struct _rt_domain *rt);
14 14
15typedef struct _rt_domain { 15typedef struct _rt_domain {
16 struct tasklet_struct release_tasklet; 16 struct no_rqlock_work arm_timers;
17 17
18 /* runnable rt tasks are in here */ 18 /* runnable rt tasks are in here */
19 spinlock_t ready_lock; 19 spinlock_t ready_lock;
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index 933c1961cb..76be2fe4be 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -38,17 +38,15 @@ struct rt_task {
38/* don't export internal data structures to user space (liblitmus) */ 38/* don't export internal data structures to user space (liblitmus) */
39#ifdef __KERNEL__ 39#ifdef __KERNEL__
40 40
41struct _rt_domain;
42
41struct rt_job { 43struct rt_job {
42 /* Time instant the the job was or will be released. */ 44 /* Time instant the the job was or will be released. */
43 lt_t release; 45 lt_t release;
44 /* What is the current deadline? */ 46 /* What is the current deadline? */
45 lt_t deadline; 47 lt_t deadline;
46 48
47 /* The high-resolution timer used to control its release. */ 49 /* How much service has this job received so far? */
48 struct hrtimer release_timer;
49
50 /* How much service has this job received so far?
51 */
52 lt_t exec_time; 50 lt_t exec_time;
53 51
54 /* Which job is this. This is used to let user space 52 /* Which job is this. This is used to let user space
@@ -125,6 +123,12 @@ struct rt_param {
125 */ 123 */
126 int old_policy; 124 int old_policy;
127 int old_prio; 125 int old_prio;
126
127 /* The high-resolution timer used to control its release. */
128 struct hrtimer release_timer;
129
130 /* ready queue for this task */
131 struct _rt_domain* domain;
128}; 132};
129 133
130/* Possible RT flags */ 134/* Possible RT flags */
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c
index cbedbac1dc..47027b49bb 100644
--- a/litmus/rt_domain.c
+++ b/litmus/rt_domain.c
@@ -35,7 +35,13 @@ static void default_release_job(struct task_struct* t, rt_domain_t* rt)
35 35
36static enum hrtimer_restart release_job_timer(struct hrtimer *timer) 36static enum hrtimer_restart release_job_timer(struct hrtimer *timer)
37{ 37{
38 /* call the current plugin */ 38 struct task_struct *t;
39
40 t = container_of(timer, struct task_struct,
41 rt_param.release_timer);
42
43 get_domain(t)->release_job(t, get_domain(t));
44
39 return HRTIMER_NORESTART; 45 return HRTIMER_NORESTART;
40} 46}
41 47
@@ -44,7 +50,7 @@ static void setup_job_release_timer(struct task_struct *task)
44 hrtimer_init(&release_timer(task), CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 50 hrtimer_init(&release_timer(task), CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
45 release_timer(task).function = release_job_timer; 51 release_timer(task).function = release_job_timer;
46#ifdef CONFIG_HIGH_RES_TIMERS 52#ifdef CONFIG_HIGH_RES_TIMERS
47 release_timer(task).cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; 53 release_timer(task).cb_mode = HRTIMER_CB_IRQSAFE_NO_RESTART;
48#endif 54#endif
49 /* Expiration time of timer is release time of task. */ 55 /* Expiration time of timer is release time of task. */
50 release_timer(task).expires = ns_to_ktime(get_release(task)); 56 release_timer(task).expires = ns_to_ktime(get_release(task));
@@ -95,7 +101,7 @@ void rt_domain_init(rt_domain_t *rt,
95 rt->check_resched = check; 101 rt->check_resched = check;
96 rt->release_job = release; 102 rt->release_job = release;
97 rt->order = order; 103 rt->order = order;
98 tasklet_init(&rt->release_tasklet, arm_release_timers, (unsigned long) rt); 104 init_no_rqlock_work(&rt->arm_timers, arm_release_timers, (unsigned long) rt);
99} 105}
100 106
101/* add_ready - add a real-time task to the rt ready queue. It must be runnable. 107/* add_ready - add a real-time task to the rt ready queue. It must be runnable.
@@ -135,6 +141,7 @@ struct task_struct* __peek_ready(rt_domain_t* rt)
135void __add_release(rt_domain_t* rt, struct task_struct *task) 141void __add_release(rt_domain_t* rt, struct task_struct *task)
136{ 142{
137 list_add(&task->rt_list, &rt->release_queue); 143 list_add(&task->rt_list, &rt->release_queue);
138 tasklet_hi_schedule(&rt->release_tasklet); 144 task->rt_param.domain = rt;
145 do_without_rqlock(&rt->arm_timers);
139} 146}
140 147