* [patch 0/2] hrtimer: generic sleeper infrastructure
@ 2006-03-25 12:46 Thomas Gleixner
2006-03-25 12:46 ` [patch 1/2] hrtimer Thomas Gleixner
2006-03-25 12:46 ` [patch 2/2] hrtimer Thomas Gleixner
0 siblings, 2 replies; 8+ messages in thread
From: Thomas Gleixner @ 2006-03-25 12:46 UTC (permalink / raw)
To: Andrew Morton; +Cc: LKML, Ingo Molnar
Andrew,
the removal of the data field in the hrtimer structure introduced a
private sleeper implementation for nanosleep. wakeup is the most common
callback case for timers and we should use a generic implementation
instead of forcing users to reimplement it all over the place.
tglx
--
^ permalink raw reply [flat|nested] 8+ messages in thread* [patch 1/2] hrtimer 2006-03-25 12:46 [patch 0/2] hrtimer: generic sleeper infrastructure Thomas Gleixner @ 2006-03-25 12:46 ` Thomas Gleixner 2006-03-25 12:46 ` [patch 2/2] hrtimer Thomas Gleixner 1 sibling, 0 replies; 8+ messages in thread From: Thomas Gleixner @ 2006-03-25 12:46 UTC (permalink / raw) To: Andrew Morton; +Cc: LKML, Ingo Molnar [-- Attachment #1: hrtimer-create-generic-sleeper.patch --] [-- Type: text/plain, Size: 2334 bytes --] The removal of the data field in the hrtimer structure enforces the embedding of the timer into another data structure. nanosleep now uses a private implementation of the most common used timer callback function (simple task wakeup). In order to avoid the reimplentation of such functionality all over the place a generic hrtimer_sleeper functionality is created. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> include/linux/hrtimer.h | 16 ++++++++++++++++ kernel/hrtimer.c | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) Index: linux-2.6.16/include/linux/hrtimer.h =================================================================== --- linux-2.6.16.orig/include/linux/hrtimer.h +++ linux-2.6.16/include/linux/hrtimer.h @@ -58,6 +58,19 @@ struct hrtimer { }; /** + * struct hrtimer_sleeper - simple sleeper structure + * + * @timer: embedded timer structure + * @task: task to wake up + * + * task is set to NULL, when the timer expires. + */ +struct hrtimer_sleeper { + struct hrtimer timer; + struct task_struct *task; +}; + +/** * struct hrtimer_base - the timer base for a specific clock * * @index: clock type index for per_cpu support when moving a timer @@ -127,6 +140,9 @@ extern long hrtimer_nanosleep(struct tim const enum hrtimer_mode mode, const clockid_t clockid); +extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, + struct task_struct *tsk); + /* Soft interrupt function to run the hrtimer queues: */ extern void hrtimer_run_queues(void); Index: linux-2.6.16/kernel/hrtimer.c =================================================================== --- linux-2.6.16.orig/kernel/hrtimer.c +++ linux-2.6.16/kernel/hrtimer.c @@ -656,6 +656,25 @@ void hrtimer_run_queues(void) * Sleep related functions: */ +static int hrtimer_wakeup(struct hrtimer *timer) +{ + struct hrtimer_sleeper *t = + container_of(timer, struct hrtimer_sleeper, timer); + struct task_struct *task = t->task; + + t->task = NULL; + if (task) + wake_up_process(task); + + return HRTIMER_NORESTART; +} + +void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, task_t *task) +{ + sl->timer.function = hrtimer_wakeup; + sl->task = task; +} + struct sleep_hrtimer { struct hrtimer timer; struct task_struct *task; -- ^ permalink raw reply [flat|nested] 8+ messages in thread
* [patch 2/2] hrtimer 2006-03-25 12:46 [patch 0/2] hrtimer: generic sleeper infrastructure Thomas Gleixner 2006-03-25 12:46 ` [patch 1/2] hrtimer Thomas Gleixner @ 2006-03-25 12:46 ` Thomas Gleixner 2006-03-26 2:32 ` Andrew Morton 1 sibling, 1 reply; 8+ messages in thread From: Thomas Gleixner @ 2006-03-25 12:46 UTC (permalink / raw) To: Andrew Morton; +Cc: LKML, Ingo Molnar [-- Attachment #1: hrtimer-nanosleep-use-generic-sleeper.patch --] [-- Type: text/plain, Size: 2197 bytes --] Replace the nanosleep private sleeper functionality by the generic hrtimer sleeper. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> kernel/hrtimer.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) Index: linux-2.6.16/kernel/hrtimer.c =================================================================== --- linux-2.6.16.orig/kernel/hrtimer.c +++ linux-2.6.16/kernel/hrtimer.c @@ -655,7 +655,6 @@ void hrtimer_run_queues(void) /* * Sleep related functions: */ - static int hrtimer_wakeup(struct hrtimer *timer) { struct hrtimer_sleeper *t = @@ -675,28 +674,9 @@ void hrtimer_init_sleeper(struct hrtimer sl->task = task; } -struct sleep_hrtimer { - struct hrtimer timer; - struct task_struct *task; - int expired; -}; - -static int nanosleep_wakeup(struct hrtimer *timer) -{ - struct sleep_hrtimer *t = - container_of(timer, struct sleep_hrtimer, timer); - - t->expired = 1; - wake_up_process(t->task); - - return HRTIMER_NORESTART; -} - -static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode) +static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) { - t->timer.function = nanosleep_wakeup; - t->task = current; - t->expired = 0; + hrtimer_init_sleeper(t, current); do { set_current_state(TASK_INTERRUPTIBLE); @@ -704,18 +684,18 @@ static int __sched do_nanosleep(struct s schedule(); - if (unlikely(!t->expired)) { + if (unlikely(t->task)) { hrtimer_cancel(&t->timer); mode = HRTIMER_ABS; } - } while (!t->expired && !signal_pending(current)); + } while (t->task && !signal_pending(current)); - return t->expired; + return t->task == NULL; } static long __sched nanosleep_restart(struct restart_block *restart) { - struct sleep_hrtimer t; + struct hrtimer_sleeper t; struct timespec __user *rmtp; struct timespec tu; ktime_t time; @@ -748,7 +728,7 @@ long hrtimer_nanosleep(struct timespec * const enum hrtimer_mode mode, const clockid_t clockid) { struct restart_block *restart; - struct sleep_hrtimer t; + struct hrtimer_sleeper t; struct timespec tu; ktime_t rem; -- ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] hrtimer 2006-03-25 12:46 ` [patch 2/2] hrtimer Thomas Gleixner @ 2006-03-26 2:32 ` Andrew Morton 2006-03-26 22:10 ` Thomas Gleixner 0 siblings, 1 reply; 8+ messages in thread From: Andrew Morton @ 2006-03-26 2:32 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel, mingo Thomas Gleixner <tglx@linutronix.de> wrote: > > > Replace the nanosleep private sleeper functionality by the generic > hrtimer sleeper. > > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > Signed-off-by: Ingo Molnar <mingo@elte.hu> > > > kernel/hrtimer.c | 34 +++++++--------------------------- > 1 file changed, 7 insertions(+), 27 deletions(-) > > Index: linux-2.6.16/kernel/hrtimer.c > =================================================================== > --- linux-2.6.16.orig/kernel/hrtimer.c > +++ linux-2.6.16/kernel/hrtimer.c > @@ -655,7 +655,6 @@ void hrtimer_run_queues(void) > /* > * Sleep related functions: > */ > - > static int hrtimer_wakeup(struct hrtimer *timer) > { > struct hrtimer_sleeper *t = > @@ -675,28 +674,9 @@ void hrtimer_init_sleeper(struct hrtimer > sl->task = task; > } > > -struct sleep_hrtimer { > - struct hrtimer timer; > - struct task_struct *task; > - int expired; > -}; > - > -static int nanosleep_wakeup(struct hrtimer *timer) > -{ > - struct sleep_hrtimer *t = > - container_of(timer, struct sleep_hrtimer, timer); > - > - t->expired = 1; > - wake_up_process(t->task); > - > - return HRTIMER_NORESTART; > -} > - > -static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode) > +static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) > { > - t->timer.function = nanosleep_wakeup; > - t->task = current; > - t->expired = 0; > + hrtimer_init_sleeper(t, current); > > do { > set_current_state(TASK_INTERRUPTIBLE); > @@ -704,18 +684,18 @@ static int __sched do_nanosleep(struct s > > schedule(); > > - if (unlikely(!t->expired)) { > + if (unlikely(t->task)) { > hrtimer_cancel(&t->timer); > mode = HRTIMER_ABS; > } > - } while (!t->expired && !signal_pending(current)); > + } while (t->task && !signal_pending(current)); > > - return t->expired; > + return t->task == NULL; > } This all looks vaguely racy. hrtimer_wakeup() will set t->task to NULL without barriers, locks or anything. And the waiter here can break out of schedule() due to signal delivery while a wakeup is in progress. So the value of t->task here is fairly meaningless. Ot just depends on how far the waker has got through hrtimer_wakeup(). Maybe that doesn't matter, because hrtimer_cancel() will spin until hrtimer_wakeup() has completed anyway, but could you please recheck and confirm that this is all solid? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] hrtimer 2006-03-26 2:32 ` Andrew Morton @ 2006-03-26 22:10 ` Thomas Gleixner 2006-03-27 23:55 ` Oleg Nesterov 0 siblings, 1 reply; 8+ messages in thread From: Thomas Gleixner @ 2006-03-26 22:10 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, mingo, Oleg Nesterov On Sat, 2006-03-25 at 18:32 -0800, Andrew Morton wrote: > This all looks vaguely racy. hrtimer_wakeup() will set t->task to NULL > without barriers, locks or anything. And the waiter here can break out of > schedule() due to signal delivery while a wakeup is in progress. We set task = NULL before wake_up_process() which acts as a barrier. > So the value of t->task here is fairly meaningless. Ot just depends on how > far the waker has got through hrtimer_wakeup(). > > Maybe that doesn't matter, because hrtimer_cancel() will spin until > hrtimer_wakeup() has completed anyway, but could you please recheck and > confirm that this is all solid? Right, either it waits for the running timer or in case the wakeup happens between if (unlikely(t->task)) { and hrtimer_cancel(&t->timer); then hrtimer_cancel will see that the timer is inactive and we drop out of the loop because the while(t->task) condition is not longer true. tglx ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] hrtimer 2006-03-26 22:10 ` Thomas Gleixner @ 2006-03-27 23:55 ` Oleg Nesterov 2006-03-28 0:03 ` Roman Zippel 2006-03-28 8:29 ` Thomas Gleixner 0 siblings, 2 replies; 8+ messages in thread From: Oleg Nesterov @ 2006-03-27 23:55 UTC (permalink / raw) To: Thomas Gleixner; +Cc: Andrew Morton, linux-kernel, mingo I also think this is racy. CPU_0 CPU_1 hrtimer_wakeup: task = t->task; t->task = NULL; <--- INTERRUPT ---> task is woken by signal, do_nanosleep() sees t->task == NULL, returns without hrtimer_cancel(), and __exits__. <--- RESUME ---> wake_up_process(task); Instead of exit(), 'task' can go to TASK_STOPPED or TASK_UNINTERRUPTIBLE after return from do_nanosleep(), it will be awakened by hrtimer_wakeup() unexpectedly. Oleg. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] hrtimer 2006-03-27 23:55 ` Oleg Nesterov @ 2006-03-28 0:03 ` Roman Zippel 2006-03-28 8:29 ` Thomas Gleixner 1 sibling, 0 replies; 8+ messages in thread From: Roman Zippel @ 2006-03-28 0:03 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Thomas Gleixner, Andrew Morton, linux-kernel, mingo Hi, On Tue, 28 Mar 2006, Oleg Nesterov wrote: > I also think this is racy. > > CPU_0 CPU_1 > > hrtimer_wakeup: > > task = t->task; > t->task = NULL; > > <--- INTERRUPT ---> > > task is woken by signal, > do_nanosleep() sees t->task == NULL, > returns without hrtimer_cancel(), > and __exits__. > > <--- RESUME ---> > > wake_up_process(task); > > Instead of exit(), 'task' can go to TASK_STOPPED or TASK_UNINTERRUPTIBLE > after return from do_nanosleep(), it will be awakened by hrtimer_wakeup() > unexpectedly. Indeed and my original patch did call hrtimer_cancel() unconditionally to synchronize with a possibly running timer. Thomas, could you please document it a bit better, when you modify my patches? bye, Roman ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] hrtimer 2006-03-27 23:55 ` Oleg Nesterov 2006-03-28 0:03 ` Roman Zippel @ 2006-03-28 8:29 ` Thomas Gleixner 1 sibling, 0 replies; 8+ messages in thread From: Thomas Gleixner @ 2006-03-28 8:29 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Andrew Morton, linux-kernel, mingo On Tue, 2006-03-28 at 03:55 +0400, Oleg Nesterov wrote: > Instead of exit(), 'task' can go to TASK_STOPPED or TASK_UNINTERRUPTIBLE > after return from do_nanosleep(), it will be awakened by hrtimer_wakeup() > unexpectedly. Yep, you are right. Index: linux-2.6.16/kernel/hrtimer.c =================================================================== --- linux-2.6.16.orig/kernel/hrtimer.c +++ linux-2.6.16/kernel/hrtimer.c @@ -684,10 +684,9 @@ static int __sched do_nanosleep(struct h schedule(); - if (unlikely(t->task)) { - hrtimer_cancel(&t->timer); - mode = HRTIMER_ABS; - } + hrtimer_cancel(&t->timer); + mode = HRTIMER_ABS; + } while (t->task && !signal_pending(current)); return t->task == NULL; ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-03-28 8:28 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-03-25 12:46 [patch 0/2] hrtimer: generic sleeper infrastructure Thomas Gleixner 2006-03-25 12:46 ` [patch 1/2] hrtimer Thomas Gleixner 2006-03-25 12:46 ` [patch 2/2] hrtimer Thomas Gleixner 2006-03-26 2:32 ` Andrew Morton 2006-03-26 22:10 ` Thomas Gleixner 2006-03-27 23:55 ` Oleg Nesterov 2006-03-28 0:03 ` Roman Zippel 2006-03-28 8:29 ` Thomas Gleixner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox