Commit 7fe672b1 authored by George Anzinger's avatar George Anzinger Committed by Linus Torvalds

[PATCH] Bugfix for CLOCK_REALTIME absolute timer

As required by the standard, this patch adds to POSIX ABSOLUTE timers the
functionality of adjusting the timer when the clock is set so that it still
expires at the specified time (provided that time has not passed, in which
case the timer expires immeadiatly).

The standard is, IMNSOHO, a bit vague on just how repeating timers are to
be handled so I made some choices:

1) If an absolute timer is to expire every N intervals, we assume that
   the expiries should happen at those specified times after clock setting.
    I.e.  we adjust the repeat timer as well as the initial timer.  (The
   other option would be to treat the repeating timers as relative and not
   to adjust them.)

2) If a clock set moves the the clock prior to the initial expiry time
   AND that time has already passed and been signaled, the current repeat
   timer is adjusted, i.e.  we DO NOT go back to the initial time and
   repeat that.  (The other option is to treat this case as a new request
   with the initial timer parameters (which by this time we have lost).)

3) If time is advanced such that it appears that several expiries have
   been missed, the overrun count will reflect the misses.  (The other
   option is to not reflect this in the overrun.) At the same time, nothing
   is done to acknowledge, to the user, that we are repeating expiries when
   the clock is retarded.
Signed-off-by: default avatarGeorge Anzinger <george@mvista.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 84db6603
#ifndef _linux_POSIX_TIMERS_H
#define _linux_POSIX_TIMERS_H
#include <linux/spinlock.h>
#include <linux/list.h>
struct k_clock_abs {
struct list_head list;
spinlock_t lock;
};
struct k_clock {
int res; /* in nano seconds */
struct k_clock_abs *abs_struct;
int (*clock_set) (struct timespec * tp);
int (*clock_get) (struct timespec * tp);
int (*nsleep) (int flags,
......@@ -23,8 +31,14 @@ struct now_struct {
#define posix_time_before(timer, now) \
time_before((timer)->expires, (now)->jiffies)
#define posix_bump_timer(timr) do { \
(timr)->it_timer.expires += (timr)->it_incr; \
(timr)->it_overrun++; \
#define posix_bump_timer(timr, now) \
do { \
long delta, orun; \
delta = now.jiffies - (timr)->it_timer.expires; \
if (delta >= 0) { \
orun = 1 + (delta / (timr)->it_incr); \
(timr)->it_timer.expires += orun * (timr)->it_incr; \
(timr)->it_overrun += orun; \
} \
}while (0)
#endif
......@@ -343,6 +343,8 @@ struct k_itimer {
struct task_struct *it_process; /* process to send signal to */
struct timer_list it_timer;
struct sigqueue *sigq; /* signal queue entry. */
struct list_head abs_timer_entry; /* clock abs_timer_list */
struct timespec wall_to_prev; /* wall_to_monotonic used when set */
};
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment