From 89908c1b2f22b19641f5cbc19805be7aed664a8e Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Fri, 2 May 2008 22:54:44 -0400 Subject: LITMUS: use no_rqlock_work to avoid ksoftirqd deadlock We can't use tasklets from within the scheduler. User no_rqlock_work instead. --- include/litmus/litmus.h | 5 ++++- include/litmus/rt_domain.h | 4 ++-- include/litmus/rt_param.h | 14 +++++++++----- litmus/rt_domain.c | 15 +++++++++++---- 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) #define ns_to_ktime(t) ktime_add_ns(ktime_set(0, 0), t) /* The high-resolution release timer for a task. */ -#define release_timer(t) ((t)->rt_param.job_params.release_timer) +#define release_timer(t) ((t)->rt_param.release_timer) + +/* The high-resolution release timer for a task. */ +#define get_domain(t) ((t)->rt_param.domain) /* Honor the flag in the preempt_count variable that is set * 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 @@ #ifndef __UNC_RT_DOMAIN_H__ #define __UNC_RT_DOMAIN_H__ -#include +#include struct _rt_domain; @@ -13,7 +13,7 @@ typedef int (*check_resched_needed_t)(struct _rt_domain *rt); typedef void (*release_job_t)(struct task_struct *t, struct _rt_domain *rt); typedef struct _rt_domain { - struct tasklet_struct release_tasklet; + struct no_rqlock_work arm_timers; /* runnable rt tasks are in here */ 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 { /* don't export internal data structures to user space (liblitmus) */ #ifdef __KERNEL__ +struct _rt_domain; + struct rt_job { /* Time instant the the job was or will be released. */ lt_t release; /* What is the current deadline? */ lt_t deadline; - /* The high-resolution timer used to control its release. */ - struct hrtimer release_timer; - - /* How much service has this job received so far? - */ + /* How much service has this job received so far? */ lt_t exec_time; /* Which job is this. This is used to let user space @@ -125,6 +123,12 @@ struct rt_param { */ int old_policy; int old_prio; + + /* The high-resolution timer used to control its release. */ + struct hrtimer release_timer; + + /* ready queue for this task */ + struct _rt_domain* domain; }; /* 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) static enum hrtimer_restart release_job_timer(struct hrtimer *timer) { - /* call the current plugin */ + struct task_struct *t; + + t = container_of(timer, struct task_struct, + rt_param.release_timer); + + get_domain(t)->release_job(t, get_domain(t)); + return HRTIMER_NORESTART; } @@ -44,7 +50,7 @@ static void setup_job_release_timer(struct task_struct *task) hrtimer_init(&release_timer(task), CLOCK_MONOTONIC, HRTIMER_MODE_ABS); release_timer(task).function = release_job_timer; #ifdef CONFIG_HIGH_RES_TIMERS - release_timer(task).cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; + release_timer(task).cb_mode = HRTIMER_CB_IRQSAFE_NO_RESTART; #endif /* Expiration time of timer is release time of task. */ release_timer(task).expires = ns_to_ktime(get_release(task)); @@ -95,7 +101,7 @@ void rt_domain_init(rt_domain_t *rt, rt->check_resched = check; rt->release_job = release; rt->order = order; - tasklet_init(&rt->release_tasklet, arm_release_timers, (unsigned long) rt); + init_no_rqlock_work(&rt->arm_timers, arm_release_timers, (unsigned long) rt); } /* 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) void __add_release(rt_domain_t* rt, struct task_struct *task) { list_add(&task->rt_list, &rt->release_queue); - tasklet_hi_schedule(&rt->release_tasklet); + task->rt_param.domain = rt; + do_without_rqlock(&rt->arm_timers); } -- cgit v1.2.2