lkml.org 
[lkml]   [2005]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[patch 19/43] Introduce ktimer_nanosleep APIs
    From
    Date
    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@linutronix.de>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

    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 = &current_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@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-12-01 01:11    [W:0.031 / U:121.068 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site