--- v6
+++ v9
@@ -1,115 +1,54 @@
-This patch augments the POSIX clock code to offer a dynamic clock
-creation method. Instead of registering a hard coded clock ID, modules
-may call create_posix_clock(), which returns a new clock ID.
+This patch adds a new mode bit into the timex structure. When set, the bit
+instructs the kernel to add the given time value to the current time.
-Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
+Signed-off-by: Richard Cochran <richard.cochran-3mrvs1K0uXizZXS1Dc/lvw@public.gmane.org>
---
- include/linux/posix-timers.h | 7 ++++++-
- include/linux/time.h | 2 ++
- kernel/posix-timers.c | 41 ++++++++++++++++++++++++++++++++++-------
- 3 files changed, 42 insertions(+), 8 deletions(-)
+ include/linux/timex.h | 3 ++-
+ kernel/time/ntp.c | 11 +++++++++++
+ 2 files changed, 13 insertions(+), 1 deletions(-)
-diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
-index abf61cc..08aa4da 100644
---- a/include/linux/posix-timers.h
-+++ b/include/linux/posix-timers.h
-@@ -68,6 +68,7 @@ struct k_itimer {
- };
+diff --git a/include/linux/timex.h b/include/linux/timex.h
+index 32d852f..800a2c8 100644
+--- a/include/linux/timex.h
++++ b/include/linux/timex.h
+@@ -73,7 +73,7 @@ struct timex {
+ long tolerance; /* clock frequency tolerance (ppm)
+ * (read only)
+ */
+- struct timeval time; /* (read only) */
++ struct timeval time; /* (read only, except for ADJ_SETOFFSET) */
+ long tick; /* (modified) usecs between clock ticks */
- struct k_clock {
-+ clockid_t id;
- int res; /* in nanoseconds */
- int (*clock_getres) (const clockid_t which_clock, struct timespec *tp);
- int (*clock_set) (const clockid_t which_clock, struct timespec * tp);
-@@ -86,7 +87,11 @@ struct k_clock {
- struct itimerspec * cur_setting);
- };
+ long ppsfreq; /* pps frequency (scaled ppm) (ro) */
+@@ -102,6 +102,7 @@ struct timex {
+ #define ADJ_STATUS 0x0010 /* clock status */
+ #define ADJ_TIMECONST 0x0020 /* pll time constant */
+ #define ADJ_TAI 0x0080 /* set TAI offset */
++#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
+ #define ADJ_MICRO 0x1000 /* select microsecond resolution */
+ #define ADJ_NANO 0x2000 /* select nanosecond resolution */
+ #define ADJ_TICK 0x4000 /* tick value */
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index d232189..0c87858 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -482,6 +482,17 @@ int do_adjtimex(struct timex *txc)
+ hrtimer_cancel(&leap_timer);
+ }
--void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
-+/* Regsiter a posix clock with a "well known" clock id. */
-+int register_posix_clock(const clockid_t id, struct k_clock *clock);
++ if (txc->modes & ADJ_SETOFFSET) {
++ struct timespec delta;
++ if ((unsigned long)txc->time.tv_usec >= NSEC_PER_SEC)
++ return -EINVAL;
++ delta.tv_sec = txc->time.tv_sec;
++ delta.tv_nsec = txc->time.tv_usec;
++ if (!(txc->modes & ADJ_NANO))
++ delta.tv_nsec *= 1000;
++ timekeeping_inject_offset(&delta);
++ }
+
-+/* Create a new posix clock with a dynamic clock id. */
-+clockid_t create_posix_clock(struct k_clock *clock);
+ getnstimeofday(&ts);
- /* error handlers for timer_create, nanosleep and settime */
- int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
-diff --git a/include/linux/time.h b/include/linux/time.h
-index 9f15ac7..914c48d 100644
---- a/include/linux/time.h
-+++ b/include/linux/time.h
-@@ -299,6 +299,8 @@ struct itimerval {
- #define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)
- #define CLOCKS_MONO CLOCK_MONOTONIC
-
-+#define CLOCK_INVALID -1
-+
- /*
- * The various flags for setting POSIX.1b interval timers:
- */
-diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
-index 446b566..67fba5c 100644
---- a/kernel/posix-timers.c
-+++ b/kernel/posix-timers.c
-@@ -132,6 +132,8 @@ static DEFINE_SPINLOCK(idr_lock);
- */
-
- static struct k_clock posix_clocks[MAX_CLOCKS];
-+static DECLARE_BITMAP(clocks_map, MAX_CLOCKS);
-+static DEFINE_MUTEX(clocks_mux); /* protects 'posix_clocks' and 'clocks_map' */
-
- /*
- * These ones are defined below.
-@@ -484,18 +486,43 @@ static struct pid *good_sigevent(sigevent_t * event)
- return task_pid(rtn);
- }
-
--void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock)
-+int register_posix_clock(const clockid_t id, struct k_clock *clock)
- {
-- if ((unsigned) clock_id >= MAX_CLOCKS) {
-- printk("POSIX clock register failed for clock_id %d\n",
-- clock_id);
-- return;
-- }
-+ struct k_clock *kc;
-+ int err = 0;
-
-- posix_clocks[clock_id] = *new_clock;
-+ mutex_lock(&clocks_mux);
-+ if (test_bit(id, clocks_map)) {
-+ pr_err("clock_id %d already registered\n", id);
-+ err = -EBUSY;
-+ goto out;
-+ }
-+ kc = &posix_clocks[id];
-+ *kc = *clock;
-+ kc->id = id;
-+ set_bit(id, clocks_map);
-+out:
-+ mutex_unlock(&clocks_mux);
-+ return err;
- }
- EXPORT_SYMBOL_GPL(register_posix_clock);
-
-+clockid_t create_posix_clock(struct k_clock *clock)
-+{
-+ clockid_t id;
-+
-+ mutex_lock(&clocks_mux);
-+ id = find_first_zero_bit(clocks_map, MAX_CLOCKS);
-+ mutex_unlock(&clocks_mux);
-+
-+ if (id < MAX_CLOCKS) {
-+ register_posix_clock(id, clock);
-+ return id;
-+ }
-+ return CLOCK_INVALID;
-+}
-+EXPORT_SYMBOL_GPL(create_posix_clock);
-+
- static struct k_itimer * alloc_posix_timer(void)
- {
- struct k_itimer *tmr;
+ write_seqlock_irq(&xtime_lock);
--
1.7.0.4