Hi Kirill, On 01/04/2015 11:51 PM, Kirill Tkhai wrote: > Hi, Luca, > > I've just notived this. [...] > I think we should do something like below. > > hrtimer_init() is already called in sched_fork(), so we shouldn't do this > twice. Also, we shouldn't reinit dl_throttled etc if timer is pending, > and we should prevent a race here. Thanks for the comments (I did not notice that hrtimer_init() was called twice) and for the patch. I'll test it in the next days. For reference, I attach the patch I am using locally (based on what I suggested in my previous mail) and seems to work fine here. Based on your comments, I suspect my patch can be further simplified by moving the call to init_dl_task_timer() in __sched_fork(). [...] > @@ -3250,16 +3251,19 @@ static void > __setparam_dl(struct task_struct *p, const struct sched_attr *attr) > { > struct sched_dl_entity *dl_se = &p->dl; > + struct hrtimer *timer = &dl_se->dl_timer; > + > + if (!hrtimer_active(timer) || hrtimer_try_to_cancel(timer) != -1) { Just for the sake of curiosity, why trying to cancel the timer ("|| hrtimer_try_to_cancel(timer)") here? If it is active, cannot we leave it active (without touching dl_throttled, dl_new and dl_yielded)? I mean: if I try to change the parameters of a task when it is throttled, I'd like it to stay throttled until the end of the reservation period... Or am I missing something? Thanks, Luca > + dl_se->dl_throttled = 0; > + dl_se->dl_new = 1; > + dl_se->dl_yielded = 0; > + } > > - init_dl_task_timer(dl_se); > dl_se->dl_runtime = attr->sched_runtime; > dl_se->dl_deadline = attr->sched_deadline; > dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline; > dl_se->flags = attr->sched_flags; > dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime); > - dl_se->dl_throttled = 0; > - dl_se->dl_new = 1; > - dl_se->dl_yielded = 0; > } > > /* > diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c > index e5db8c6..8649bd6 100644 > --- a/kernel/sched/deadline.c > +++ b/kernel/sched/deadline.c > @@ -500,7 +500,7 @@ static int start_dl_timer(struct sched_dl_entity *dl_se, bool boosted) > * updating (and the queueing back to dl_rq) will be done by the > * next call to enqueue_task_dl(). > */ > -static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) > +enum hrtimer_restart dl_task_timer(struct hrtimer *timer) > { > struct sched_dl_entity *dl_se = container_of(timer, > struct sched_dl_entity, > @@ -559,14 +559,6 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) > return HRTIMER_NORESTART; > } > > -void init_dl_task_timer(struct sched_dl_entity *dl_se) > -{ > - struct hrtimer *timer = &dl_se->dl_timer; > - > - hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); > - timer->function = dl_task_timer; > -} > - > static > int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se) > { > diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h > index 9a2a45c..ad3a2f0 100644 > --- a/kernel/sched/sched.h > +++ b/kernel/sched/sched.h > @@ -1257,7 +1257,6 @@ extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime > > extern struct dl_bandwidth def_dl_bandwidth; > extern void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime); > -extern void init_dl_task_timer(struct sched_dl_entity *dl_se); > > unsigned long to_ratio(u64 period, u64 runtime); > >