hrtimers: Provide schedule_hrtimeout for CLOCK_REALTIME
The current version of schedule_hrtimeout() always uses the monotonic clock. Some system calls such as mq_timedsend() and mq_timedreceive(), however, require the use of the wall clock due to the definition of the system call. This patch provides the infrastructure to use schedule_hrtimeout() with a CLOCK_REALTIME timer. Signed-off-by: Carsten Emde <C.Emde@osadl.org> Tested-by: Pradyumna Sampath <pradysam@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arjan van de Veen <arjan@infradead.org> LKML-Reference: <20100402204331.167439615@osadl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
3bbb9ec946
commit
351b3f7a21
@ -422,6 +422,8 @@ extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
|
|||||||
|
|
||||||
extern int schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
|
extern int schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
|
||||||
const enum hrtimer_mode mode);
|
const enum hrtimer_mode mode);
|
||||||
|
extern int schedule_hrtimeout_range_clock(ktime_t *expires,
|
||||||
|
unsigned long delta, const enum hrtimer_mode mode, int clock);
|
||||||
extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode);
|
extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode);
|
||||||
|
|
||||||
/* Soft interrupt function to run the hrtimer queues: */
|
/* Soft interrupt function to run the hrtimer queues: */
|
||||||
|
@ -1748,6 +1748,57 @@ void __init hrtimers_init(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* schedule_hrtimeout_range_clock - sleep until timeout
|
||||||
|
* @expires: timeout value (ktime_t)
|
||||||
|
* @delta: slack in expires timeout (ktime_t)
|
||||||
|
* @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
|
||||||
|
* @clock: timer clock, CLOCK_MONOTONIC or CLOCK_REALTIME
|
||||||
|
*/
|
||||||
|
int __sched
|
||||||
|
schedule_hrtimeout_range_clock(ktime_t *expires, unsigned long delta,
|
||||||
|
const enum hrtimer_mode mode, int clock)
|
||||||
|
{
|
||||||
|
struct hrtimer_sleeper t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optimize when a zero timeout value is given. It does not
|
||||||
|
* matter whether this is an absolute or a relative time.
|
||||||
|
*/
|
||||||
|
if (expires && !expires->tv64) {
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A NULL parameter means "inifinte"
|
||||||
|
*/
|
||||||
|
if (!expires) {
|
||||||
|
schedule();
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hrtimer_init_on_stack(&t.timer, clock, mode);
|
||||||
|
hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
|
||||||
|
|
||||||
|
hrtimer_init_sleeper(&t, current);
|
||||||
|
|
||||||
|
hrtimer_start_expires(&t.timer, mode);
|
||||||
|
if (!hrtimer_active(&t.timer))
|
||||||
|
t.task = NULL;
|
||||||
|
|
||||||
|
if (likely(t.task))
|
||||||
|
schedule();
|
||||||
|
|
||||||
|
hrtimer_cancel(&t.timer);
|
||||||
|
destroy_hrtimer_on_stack(&t.timer);
|
||||||
|
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
|
return !t.task ? 0 : -EINTR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* schedule_hrtimeout_range - sleep until timeout
|
* schedule_hrtimeout_range - sleep until timeout
|
||||||
* @expires: timeout value (ktime_t)
|
* @expires: timeout value (ktime_t)
|
||||||
@ -1777,46 +1828,10 @@ void __init hrtimers_init(void)
|
|||||||
* Returns 0 when the timer has expired otherwise -EINTR
|
* Returns 0 when the timer has expired otherwise -EINTR
|
||||||
*/
|
*/
|
||||||
int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
|
int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
|
||||||
const enum hrtimer_mode mode)
|
const enum hrtimer_mode mode)
|
||||||
{
|
{
|
||||||
struct hrtimer_sleeper t;
|
return schedule_hrtimeout_range_clock(expires, delta, mode,
|
||||||
|
CLOCK_MONOTONIC);
|
||||||
/*
|
|
||||||
* Optimize when a zero timeout value is given. It does not
|
|
||||||
* matter whether this is an absolute or a relative time.
|
|
||||||
*/
|
|
||||||
if (expires && !expires->tv64) {
|
|
||||||
__set_current_state(TASK_RUNNING);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A NULL parameter means "inifinte"
|
|
||||||
*/
|
|
||||||
if (!expires) {
|
|
||||||
schedule();
|
|
||||||
__set_current_state(TASK_RUNNING);
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, mode);
|
|
||||||
hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
|
|
||||||
|
|
||||||
hrtimer_init_sleeper(&t, current);
|
|
||||||
|
|
||||||
hrtimer_start_expires(&t.timer, mode);
|
|
||||||
if (!hrtimer_active(&t.timer))
|
|
||||||
t.task = NULL;
|
|
||||||
|
|
||||||
if (likely(t.task))
|
|
||||||
schedule();
|
|
||||||
|
|
||||||
hrtimer_cancel(&t.timer);
|
|
||||||
destroy_hrtimer_on_stack(&t.timer);
|
|
||||||
|
|
||||||
__set_current_state(TASK_RUNNING);
|
|
||||||
|
|
||||||
return !t.task ? 0 : -EINTR;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
|
EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user