X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fposix-timers.c;h=fed2ad64fcb4fca34ddbb9a344ff9ca5f204b462;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=e081fef3624e6343a869334b4b35f1848b9494b3;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index e081fef36..fed2ad64f 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -145,7 +144,7 @@ static int common_timer_set(struct k_itimer *, int, struct itimerspec *, struct itimerspec *); static int common_timer_del(struct k_itimer *timer); -static int posix_timer_fn(struct hrtimer *data); +static int posix_timer_fn(void *data); static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags); @@ -251,18 +250,15 @@ __initcall(init_posix_timers); static void schedule_next_timer(struct k_itimer *timr) { - struct hrtimer *timer = &timr->it.real.timer; - if (timr->it.real.interval.tv64 == 0) return; - timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(), + timr->it_overrun += hrtimer_forward(&timr->it.real.timer, timr->it.real.interval); - timr->it_overrun_last = timr->it_overrun; timr->it_overrun = -1; ++timr->it_requeue_pending; - hrtimer_restart(timer); + hrtimer_restart(&timr->it.real.timer); } /* @@ -334,14 +330,13 @@ EXPORT_SYMBOL_GPL(posix_timer_event); * This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers. */ -static int posix_timer_fn(struct hrtimer *timer) +static int posix_timer_fn(void *data) { - struct k_itimer *timr; + struct k_itimer *timr = data; unsigned long flags; int si_private = 0; int ret = HRTIMER_NORESTART; - timr = container_of(timer, struct k_itimer, it.real.timer); spin_lock_irqsave(&timr->it_lock, flags); if (timr->it.real.interval.tv64 != 0) @@ -355,8 +350,7 @@ static int posix_timer_fn(struct hrtimer *timer) */ if (timr->it.real.interval.tv64 != 0) { timr->it_overrun += - hrtimer_forward(timer, - timer->base->softirq_time, + hrtimer_forward(&timr->it.real.timer, timr->it.real.interval); ret = HRTIMER_RESTART; ++timr->it_requeue_pending; @@ -608,41 +602,38 @@ static struct k_itimer * lock_timer(timer_t timer_id, unsigned long *flags) static void common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) { - ktime_t now, remaining, iv; + ktime_t remaining; struct hrtimer *timer = &timr->it.real.timer; memset(cur_setting, 0, sizeof(struct itimerspec)); + remaining = hrtimer_get_remaining(timer); - iv = timr->it.real.interval; - + /* Time left ? or timer pending */ + if (remaining.tv64 > 0 || hrtimer_active(timer)) + goto calci; /* interval timer ? */ - if (iv.tv64) - cur_setting->it_interval = ktime_to_timespec(iv); - else if (!hrtimer_active(timer) && - (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) + if (timr->it.real.interval.tv64 == 0) return; - - now = timer->base->get_time(); - /* - * When a requeue is pending or this is a SIGEV_NONE - * timer move the expiry time forward by intervals, so - * expiry is > now. + * When a requeue is pending or this is a SIGEV_NONE timer + * move the expiry time forward by intervals, so expiry is > + * now. */ - if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || - (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) - timr->it_overrun += hrtimer_forward(timer, now, iv); - - remaining = ktime_sub(timer->expires, now); + if (timr->it_requeue_pending & REQUEUE_PENDING || + (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) { + timr->it_overrun += + hrtimer_forward(timer, timr->it.real.interval); + remaining = hrtimer_get_remaining(timer); + } + calci: + /* interval timer ? */ + if (timr->it.real.interval.tv64 != 0) + cur_setting->it_interval = + ktime_to_timespec(timr->it.real.interval); /* Return 0 only, when the timer is expired and not pending */ - if (remaining.tv64 <= 0) { - /* - * A single shot SIGEV_NONE timer must return 0, when - * it is expired ! - */ - if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) - cur_setting->it_value.tv_nsec = 1; - } else + if (remaining.tv64 <= 0) + cur_setting->it_value.tv_nsec = 1; + else cur_setting->it_value = ktime_to_timespec(remaining); } @@ -725,6 +716,7 @@ common_timer_set(struct k_itimer *timr, int flags, mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL; hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); + timr->it.real.timer.data = timr; timr->it.real.timer.function = posix_timer_fn; timer->expires = timespec_to_ktime(new_setting->it_value);