From a43d7785d4b385e670c9871e370acbb573704a9c Mon Sep 17 00:00:00 2001 From: Nicola Manica Date: Wed, 1 Jul 2009 12:11:05 +0200 Subject: [PATCH] Seems to work BUGS: 1. the last timer fires when the task is already dead 2. The task works for more than its period --- kernel/sched.c | 2 + kernel/sched_cbs.c | 149 ++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 121 insertions(+), 30 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 9a91621e..ba73d1e0 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6349,7 +6349,9 @@ recheck: p->cbs_se.period = timespec_to_ns(&(param->sched_ss_repl_period)); p->cbs_se.max_budget = timespec_to_ns(¶m->sched_ss_init_budget); p->cbs_se.budget = 0; + //now=cbs_rq_of(task_cbs_rq(p))->clock; p->cbs_se.deadline = 0; + init_cbs_timer(&p->cbs_se); } #endif diff --git a/kernel/sched_cbs.c b/kernel/sched_cbs.c index 08bfa819..e643b835 100644 --- a/kernel/sched_cbs.c +++ b/kernel/sched_cbs.c @@ -72,24 +72,31 @@ static inline void deadline_postpone(struct sched_cbs_entity *cbs_se); static void __enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se); +static void enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se); + +static void enqueue_task_cbs(struct rq *rq, struct task_struct *p, int wakeup); + static void cbs_deadline(struct sched_cbs_entity *se) { struct cbs_rq *cbs_rq=cbs_cbs_rq_of(se); - printk("cbs_deadline!\n"); + //printk("cbs_deadline! %p %p\n",cbs_rq, se); deadline_postpone(se); - if (se != cbs_rq->curr) - __enqueue_cbs_entity(cbs_rq, se); - + if (se != cbs_rq->curr){ + enqueue_task_cbs(cbs_rq_of(cbs_rq), cbs_task_of(se),0); + resched_task(cbs_task_of(se)); + } + //printk("cbs_deadline! %p %p\n",cbs_rq, se); }; static enum hrtimer_restart cbs_end_deadline(struct hrtimer *timer) { struct sched_cbs_entity *se = container_of(timer, struct sched_cbs_entity, cbs_deadline_timer); - printk("timer has fired at deadline\n"); + struct rq *rq = cbs_rq_of(cbs_cbs_rq_of(se)); + printk("timer has fired at deadline (%p)\n",se); //WARN_ON_ONCE(cpu_of(rq) != smp_processor_id()); - //spin_lock(&rq->lock); - //update_rq_clock(rq); + spin_lock(&rq->lock); + update_rq_clock(rq); /** Qua va inserita una funzione che inserisce il task nel rbtree e ricarica il budget (postpone_deadline + enqueue_task) @@ -97,8 +104,10 @@ static enum hrtimer_restart cbs_end_deadline(struct hrtimer *timer) rq->curr punta al task cbs che contiene il timer espirato? **/ cbs_deadline(se); + //rq->curr->sched_class->end_(rq, rq->curr, 1); - //spin_unlock(&rq->lock); + spin_unlock(&rq->lock); + //printk("timer has fired at deadline end(%p)\n",se); return HRTIMER_NORESTART; } @@ -107,14 +116,18 @@ static enum hrtimer_restart cbs_end_deadline(struct hrtimer *timer) static void init_cbs_timer(struct sched_cbs_entity *cbs_se){ + //printk("init_cbs_timer %p\n",cbs_se); hrtimer_init(&cbs_se->cbs_deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); cbs_se->cbs_deadline_timer.function = cbs_end_deadline; cbs_se->cbs_deadline_timer.irqsafe = 1; + //printk("init_cbs_timer end %p\n",cbs_se); + } static void start_cbs_timer(struct sched_cbs_entity *cbs_se) { + //printk("start_cbs_timer %p\n",cbs_se); u64 now; struct cbs_rq *cbs_rq = cbs_cbs_rq_of(cbs_se); //ktime_t now; @@ -122,12 +135,15 @@ static void start_cbs_timer(struct sched_cbs_entity *cbs_se) /* if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF) return; */ + now = cbs_rq_of(cbs_rq)->clock; + if (now > cbs_se->deadline) + hrtimer_cancel(&cbs_se->cbs_deadline_timer); + + if (hrtimer_active(&cbs_se->cbs_deadline_timer)) return; - printk("DEAD setted to set=%llu\n",(unsigned long long)cbs_se->deadline); - printk("PERIOD %llu",(unsigned long long)cbs_se->period); - spin_lock(&cbs_se->cbs_sleeptime_lock); + spin_lock(&cbs_se->cbs_sleeptime_lock); for (;;) { ktime_t hard; @@ -136,29 +152,38 @@ static void start_cbs_timer(struct sched_cbs_entity *cbs_se) now = cbs_rq_of(cbs_rq)->clock; //now = hrtimer_cb_get_time(&cbs_se->cbs_deadline_timer); - if (cbs_se->deadline==0) - cbs_se->deadline=now+cbs_se->period; - + //if (cbs_se->deadline==0) + // cbs_se->deadline=now+cbs_se->period; + //printk("DEAD setted to set=%llu",(unsigned long long)cbs_se->deadline); + //printk(" PERIOD %llu\n",(unsigned long long)cbs_se->period); + //printk("Dati: %llu %llu %p\n",now,cbs_se->period, cbs_se); + printk("Timer settato a %llu\n",cbs_se->deadline-cbs_se->period); // hrtimer_forward(&cbs_se->cbs_deadline_timer, now, ns_to_ktime(cbs_se->period)); //soft = hrtimer_get_softexpires(&cbs_se->cbs_deadline_timer); //hard = hrtimer_get_expires(&cbs_se->cbs_deadline_timer); //delta = ktime_to_ns(ktime_sub(hard, soft)); - hard=ns_to_ktime(cbs_se->deadline); + hard=ns_to_ktime(cbs_se->deadline-cbs_se->period); //__hrtimer_start_range_ns(&cbs_se->cbs_deadline_timer, soft, delta, HRTIMER_MODE_ABS, 0); hrtimer_start(&cbs_se->cbs_deadline_timer, hard, HRTIMER_MODE_ABS); } spin_unlock(&cbs_se->cbs_sleeptime_lock); + //printk("start_cbs_timer end%p\n",cbs_se); + } static inline void deadline_postpone(struct sched_cbs_entity *cbs_se) { - while (cbs_se->budget < 0) { + //printk("deadline_postpone %p\n",cbs_se); + while (cbs_se->budget <= 0) { cbs_se->deadline += cbs_se->period; cbs_se->budget += cbs_se->max_budget; } + //printk("deadline_postpone end %p\n",cbs_se); + + } static inline s64 entity_deadline(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) @@ -171,6 +196,8 @@ static inline s64 entity_deadline(struct cbs_rq *cbs_rq, struct sched_cbs_entity */ static void __enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) { + //printk("__enqueue_cbs_entity %p %p\n",cbs_rq,se); + struct rb_node **link = &cbs_rq->tasks_timeline.rb_node; struct rb_node *parent = NULL; struct sched_cbs_entity *entry; @@ -194,7 +221,6 @@ static void __enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity leftmost = 0; } } - /* * Maintain a cache of leftmost tree entries (it is frequently * used): @@ -208,13 +234,17 @@ static void __enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity cbs_rq->min_deadline = max_dl(cbs_rq->min_deadline, se->deadline); } - + rb_link_node(&se->run_node, parent, link); rb_insert_color(&se->run_node, &cbs_rq->tasks_timeline); + //printk("__enqueue_cbs_entity end %p %p\n",cbs_rq,se); + } static void __dequeue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) { + //printk("__dequeue_cbs_entity %p\n",se); + if (cbs_rq->rb_leftmost == &se->run_node) { struct rb_node *next_node; struct sched_cbs_entity *next; @@ -232,6 +262,7 @@ static void __dequeue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity } rb_erase(&se->run_node, &cbs_rq->tasks_timeline); +// printk("__dequeue_cbs_entity end%p\n",se); } static inline struct rb_node *earliest_deadline(struct cbs_rq *cbs_rq) @@ -252,6 +283,8 @@ static inline void __update_curr_cbs(struct cbs_rq *cbs_rq, struct sched_cbs_entity *curr, unsigned long delta_exec) { + //printk("__update_curr_cbs %p %p\n",cbs_rq,curr); + //schedstat_set(curr->exec_max, max((u64)delta_exec, curr->exec_max)); // curr->sum_exec_runtime += delta_exec; @@ -260,19 +293,27 @@ __update_curr_cbs(struct cbs_rq *cbs_rq, struct sched_cbs_entity *curr, /**Soft CBS: If budget < 0 recharge buffer and postpone deadline**/ /**Hard CBS: If budget < 0 start a timer until the deadline**/ -#ifndef CBS_SOFT +#ifdef CBS_SOFT + BUG_ON(cbs_rq->curr<=0); +#endif if (curr->budget <= 0) { - curr->budget=0; - start_cbs_timer(curr); - } -#else - deadline_postpone(curr); + //printk("budget terminato per il task %p\n",curr); + deadline_postpone(curr); +#ifndef CBS_SOFT + start_cbs_timer(curr); #endif + + //resched_task(cbs_task_of(curr)); + } + //printk("__update_curr_cbs end %p %p\n",cbs_rq,curr); + } static void update_curr_cbs(struct cbs_rq *cbs_rq) { + //printk("update_curr_cbs %p\n",cbs_rq); + //printk("cbs_rq %p\n",cbs_rq); struct sched_cbs_entity *curr = cbs_rq->curr; u64 now = cbs_rq_of(cbs_rq)->clock; @@ -297,6 +338,8 @@ static void update_curr_cbs(struct cbs_rq *cbs_rq) cpuacct_charge(curtask, delta_exec); } #endif + //printk("update_curr_cbs end%p\n",cbs_rq); + } /* @@ -318,23 +361,30 @@ update_stats_curr_start_cbs(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) static void account_cbs_entity_enqueue(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) { + //printk("account_cbs_entity_enqueue %p %p\n",cbs_rq,se); + cbs_rq->nr_running++; se->on_rq = 1; + //printk("account_cbs_entity_enqueue end %p %p\n",cbs_rq,se); + } static void account_cbs_entity_dequeue(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) { + //printk("account_cbs_entity_dequeue %p %p\n",cbs_rq,se); BUG_ON(se->on_rq == 0); BUG_ON(cbs_rq->nr_running == 0); cbs_rq->nr_running--; se->on_rq = 0; + //printk("account_cbs_entity_dequeue end%p %p\n",cbs_rq,se); } static void enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) { u64 vt, now = cbs_rq_of(cbs_rq)->clock; + //printk("enqueue_cbs_entity %p %p\n",cbs_rq,se); /* * Update run-time statistics of the 'current'. @@ -344,21 +394,24 @@ enqueue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) vt = se->period * se->budget; do_div(vt, se->max_budget); - printk("dead %llu and budget %lld\n",(unsigned long long)se->deadline,(long long)se->budget); +// printk("dead %llu and budget %lld\n",(unsigned long long)se->deadline,(long long)se->budget); if (vt + now > se->deadline) { se->budget = se->max_budget; se->deadline = se->period + now; } - printk("dead %llu and budget %lld\n",(unsigned long long)se->deadline,(long long)se->budget); +// printk("dead %llu and budget %lld\n",(unsigned long long)se->deadline,(long long)se->budget); /**HARD: If budget < 0 does not enqueue the current task**/ /**SOFT: Enqueue the task beacuse budget can not be <= 0**/ + //printk("Budget %lld\n",se->budget); #ifdef CBS_SOFT if (se != cbs_rq->curr) #else if ((se != cbs_rq->curr)&&(se->budget > 0)) #endif __enqueue_cbs_entity(cbs_rq, se); + //printk("enqueue_cbs_entity end%p %p\n",cbs_rq,se); + } static void @@ -367,11 +420,14 @@ dequeue_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *se) /* * Update run-time statistics of the 'current'. */ + //printk("dequeue_cbs_entity %p\n",se); update_curr_cbs(cbs_rq); if (se != cbs_rq->curr) __dequeue_cbs_entity(cbs_rq, se); account_cbs_entity_dequeue(cbs_rq, se); + //printk("dequeue_cbs_entity end %p\n",se); + } static void @@ -396,18 +452,23 @@ wakeup_preempt_cbs_entity(struct sched_cbs_entity *curr, struct sched_cbs_entity static struct sched_cbs_entity *pick_next_cbs_entity(struct cbs_rq *cbs_rq) { + struct sched_cbs_entity *se = NULL; + //printk("pick_next_cbs_entity\n"); if (earliest_deadline(cbs_rq)) { se = __pick_next_cbs_entity(cbs_rq); set_next_cbs_entity(cbs_rq, se); } + //printk("pick_next_cbs_entity end\n"); return se; } static void put_prev_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity *prev) { + //printk("put_prev_cbs_entity %p\n",prev); + /* * If still on the runqueue then deactivate_task() * was not called and update_curr() has to be done: @@ -420,6 +481,8 @@ static void put_prev_cbs_entity(struct cbs_rq *cbs_rq, struct sched_cbs_entity * __enqueue_cbs_entity(cbs_rq, prev); } cbs_rq->curr = NULL; + //printk("put_prev_cbs_entity end %p\n",prev); + } static void @@ -443,17 +506,28 @@ cbs_entity_tick(struct cbs_rq *cbs_rq, struct sched_cbs_entity *curr, int queued static void hrtick_start_cbs(struct rq *rq, struct task_struct *p) { // int requeue = rq->curr == p; + //printk("hrtick_start_cbs %p\n",p); struct sched_cbs_entity *se = &p->cbs_se; s64 delta; WARN_ON(task_rq(p) != rq); + /*if (se->budget <= 0) + { + printk("budget terminato per il task %p\n",se); + //se->budget=0; + deadline_postpone(se); + start_cbs_timer(se); + resched_task(p); + }*/ /* * Don't schedule timeouts shorter than 10000ns, that just * doesn't make sense. */ delta = max(10000LL, se->budget); hrtick_start(rq, delta); + //printk("hrtick_start_cbs end%p\n",p); + } #else static inline void @@ -469,8 +543,10 @@ hrtick_start_cbs(struct rq *rq, struct task_struct *p, s64 time) */ static void enqueue_task_cbs(struct rq *rq, struct task_struct *p, int wakeup) { + struct cbs_rq *cbs_rq; struct sched_cbs_entity *se = &p->cbs_se; + //printk("enqueue_task_cbs %p\n",se); for_each_cbs_sched_entity(se) { if (se->on_rq) @@ -480,6 +556,7 @@ static void enqueue_task_cbs(struct rq *rq, struct task_struct *p, int wakeup) } hrtick_start_cbs(rq, rq->curr); + //printk("enqueue_task_cbs end%p\n",se); } /* @@ -489,9 +566,12 @@ static void enqueue_task_cbs(struct rq *rq, struct task_struct *p, int wakeup) */ static void dequeue_task_cbs(struct rq *rq, struct task_struct *p, int sleep) { + struct cbs_rq *cbs_rq; struct sched_cbs_entity *se = &p->cbs_se; + //printk("dequeue_task_cbs %p\n",se); + for_each_cbs_sched_entity(se) { cbs_rq = cbs_cbs_rq_of(se); dequeue_cbs_entity(cbs_rq, se); @@ -499,6 +579,8 @@ static void dequeue_task_cbs(struct rq *rq, struct task_struct *p, int sleep) } hrtick_start_cbs(rq, rq->curr); + //printk("dequeue_task_cbs end%p\n",se); + } /* @@ -532,6 +614,8 @@ static void check_preempt_wakeup_cbs(struct rq *rq, struct task_struct *p,int sy #if 0 int se_depth, pse_depth; #endif + //printk("check_preempt_wakeup_cbs %p %p\n",cbs_rq,se); + if (unlikely(rt_prio(p->prio))) { update_rq_clock(rq); update_curr_cbs(cbs_rq); @@ -576,10 +660,11 @@ static void check_preempt_wakeup_cbs(struct rq *rq, struct task_struct *p,int sy static struct task_struct *pick_next_task_cbs(struct rq *rq) { + struct task_struct *p; struct cbs_rq *cbs_rq = &rq->cbs; struct sched_cbs_entity *se; - + //printk("pick_next_task_cbs %p\n",se); if (unlikely(!cbs_rq->nr_running)) return NULL; @@ -589,8 +674,9 @@ static struct task_struct *pick_next_task_cbs(struct rq *rq) } while (cbs_rq); p = cbs_task_of(se); + //if (likely(se!=NULL)) hrtick_start_cbs(rq, p); - + //printk("pick_next_task_cbs end%p\n",se); return p; } @@ -601,11 +687,14 @@ static void put_prev_task_cbs(struct rq *rq, struct task_struct *prev) { struct sched_cbs_entity *se = &prev->cbs_se; struct cbs_rq *cbs_rq; + //printk("put_prev_task_cbs\n"); for_each_cbs_sched_entity(se) { cbs_rq = cbs_cbs_rq_of(se); put_prev_cbs_entity(cbs_rq, se); } + //printk("put_prev_task_cbs end\n"); + } /* @@ -629,7 +718,7 @@ static void task_new_cbs(struct rq *rq, struct task_struct *p) { //#warning Task New CBS is W R O N G ! ! ! struct cbs_rq *cbs_rq = task_cbs_rq(p); - printk("task_new_cbs has been called!\n"); + //printk("task_new_cbs has been called!\n"); sched_info_queued(p); update_curr_cbs(cbs_rq); @@ -648,7 +737,7 @@ static void prio_changed_cbs(struct rq *rq, struct task_struct *p, int oldprio, int running) { //#warning Check prio_changed_cbs() implementation, thanks! - printk("prio_changed_cbs has been called!\n"); + //printk("prio_changed_cbs has been called!\n"); check_preempt_curr(rq, p,running); } -- 2.11.4.GIT