[patch 19/43] Introduce ktimer_nanosleep APIs
From: Thomas Gleixner
Date: Wed Nov 30 2005 - 19:07:22 EST
plain text document attachment (ktimer-nanosleep-interface.patch)
- introduce the ktimer_nanosleep() and ktimer_nanosleep_real() APIs.
Not yet used by any code.
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
include/linux/ktimer.h | 6 +
kernel/ktimer.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+)
Index: linux-2.6.15-rc2-rework/include/linux/ktimer.h
===================================================================
--- linux-2.6.15-rc2-rework.orig/include/linux/ktimer.h
+++ linux-2.6.15-rc2-rework/include/linux/ktimer.h
@@ -155,6 +155,12 @@ extern ktime_t ktimer_round_timeval(cons
extern ktime_t ktimer_round_timespec(const struct ktimer *timer,
const struct timespec *ts);
+/* Precise sleep: */
+extern long ktimer_nanosleep(struct timespec *rqtp,
+ struct timespec __user *rmtp, const int mode);
+extern long ktimer_nanosleep_real(struct timespec *rqtp,
+ struct timespec __user *rmtp, const int mode);
+
#ifdef CONFIG_SMP
extern void wait_for_ktimer(const struct ktimer *timer);
#else
Index: linux-2.6.15-rc2-rework/kernel/ktimer.c
===================================================================
--- linux-2.6.15-rc2-rework.orig/kernel/ktimer.c
+++ linux-2.6.15-rc2-rework/kernel/ktimer.c
@@ -806,6 +806,170 @@ void ktimer_run_queues(void)
}
/*
+ * Sleep related functions:
+ */
+
+/*
+ * Process-wakeup callback:
+ */
+static void ktimer_wake_up(void *data)
+{
+ wake_up_process(data);
+}
+
+/**
+ * schedule_ktimer - sleep until timeout
+ *
+ * @timer: ktimer variable initialized with the correct clock base
+ * @t: timeout value
+ * @mode: timeout value is abs/rel
+ *
+ * Make the current task sleep until @timeout is
+ * elapsed.
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout is guaranteed to
+ * pass before the routine returns. The routine will return 0
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task. In this case the remaining time
+ * will be returned
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ */
+static ktime_t __sched
+schedule_ktimer(struct ktimer *timer, ktime_t *t, const int mode)
+{
+ timer->data = current;
+ timer->function = ktimer_wake_up;
+
+ if (unlikely(ktimer_start(timer, t, mode) < 0)) {
+ __set_current_state(TASK_RUNNING);
+ } else {
+ if (current->state != TASK_RUNNING)
+ schedule();
+ ktimer_cancel(timer);
+ }
+
+ /* Store the absolute expiry time */
+ *t = timer->expires;
+
+ /* Return the remaining time */
+ return ktime_sub(timer->expires, timer->expired);
+}
+
+static ktime_t __sched
+schedule_ktimer_interruptible(struct ktimer *timer, ktime_t *t, const int mode)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ return schedule_ktimer(timer, t, mode);
+}
+
+static long __sched
+nanosleep_restart(struct ktimer *timer, struct restart_block *restart)
+{
+ void *rfn_save = restart->fn;
+ struct timespec __user *rmtp;
+ struct timespec tu;
+ ktime_t t, rem;
+
+ restart->fn = do_no_restart_syscall;
+
+ t = ktime_set_low_high(restart->arg0, restart->arg1);
+
+ rem = schedule_ktimer_interruptible(timer, &t, KTIMER_ABS);
+
+ if (rem.tv64 <= 0)
+ return 0;
+
+ rmtp = (struct timespec __user *) restart->arg2;
+ tu = ktime_to_timespec(rem);
+ if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
+ return -EFAULT;
+
+ restart->fn = rfn_save;
+
+ /* The other values in restart are already filled in */
+ return -ERESTART_RESTARTBLOCK;
+}
+
+static long __sched nanosleep_restart_mono(struct restart_block *restart)
+{
+ struct ktimer timer;
+
+ ktimer_init(&timer);
+
+ return nanosleep_restart(&timer, restart);
+}
+
+static long __sched nanosleep_restart_real(struct restart_block *restart)
+{
+ struct ktimer timer;
+
+ ktimer_init_clock(&timer, CLOCK_REALTIME);
+
+ return nanosleep_restart(&timer, restart);
+}
+
+static long __ktimer_nanosleep(struct ktimer *timer, struct timespec *rqtp,
+ struct timespec __user *rmtp, const int mode,
+ long (*rfn)(struct restart_block *))
+{
+ struct timespec tu;
+ ktime_t rem, t;
+ struct restart_block *restart;
+
+ t = timespec_to_ktime(*rqtp);
+
+ /* t is updated to absolute expiry time ! */
+ rem = schedule_ktimer_interruptible(timer, &t, mode | KTIMER_ROUND);
+
+ if (rem.tv64 <= 0)
+ return 0;
+
+ /* Absolute timers do not update the rmtp value */
+ if (mode == KTIMER_ABS)
+ return -ERESTARTNOHAND;
+
+ tu = ktime_to_timespec(rem);
+
+ if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
+ return -EFAULT;
+
+ restart = ¤t_thread_info()->restart_block;
+ restart->fn = rfn;
+ restart->arg0 = ktime_get_low(t);
+ restart->arg1 = ktime_get_high(t);
+ restart->arg2 = (unsigned long) rmtp;
+
+ return -ERESTART_RESTARTBLOCK;
+}
+
+long ktimer_nanosleep(struct timespec *rqtp,
+ struct timespec __user *rmtp, const int mode)
+{
+ struct ktimer timer;
+
+ ktimer_init(&timer);
+
+ return __ktimer_nanosleep(&timer, rqtp, rmtp, mode,
+ nanosleep_restart_mono);
+}
+
+long ktimer_nanosleep_real(struct timespec *rqtp,
+ struct timespec __user *rmtp, const int mode)
+{
+ struct ktimer timer;
+
+ ktimer_init_clock(&timer, CLOCK_REALTIME);
+ return __ktimer_nanosleep(&timer, rqtp, rmtp, mode,
+ nanosleep_restart_real);
+}
+
+/*
* Functions related to boot-time initialization:
*/
static void __devinit init_ktimers_cpu(int cpu)
--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/