Merge master.kernel.org:/pub/scm/linux/kernel/git/tglx/hrtimer-2.6
This commit is contained in:
@@ -49,8 +49,6 @@ struct hrtimer_base;
|
|||||||
* struct hrtimer - the basic hrtimer structure
|
* struct hrtimer - the basic hrtimer structure
|
||||||
*
|
*
|
||||||
* @node: red black tree node for time ordered insertion
|
* @node: red black tree node for time ordered insertion
|
||||||
* @list: list head for easier access to the time ordered list,
|
|
||||||
* without walking the red black tree.
|
|
||||||
* @expires: the absolute expiry time in the hrtimers internal
|
* @expires: the absolute expiry time in the hrtimers internal
|
||||||
* representation. The time is related to the clock on
|
* representation. The time is related to the clock on
|
||||||
* which the timer is based.
|
* which the timer is based.
|
||||||
@@ -63,7 +61,6 @@ struct hrtimer_base;
|
|||||||
*/
|
*/
|
||||||
struct hrtimer {
|
struct hrtimer {
|
||||||
struct rb_node node;
|
struct rb_node node;
|
||||||
struct list_head list;
|
|
||||||
ktime_t expires;
|
ktime_t expires;
|
||||||
enum hrtimer_state state;
|
enum hrtimer_state state;
|
||||||
int (*function)(void *);
|
int (*function)(void *);
|
||||||
@@ -78,7 +75,7 @@ struct hrtimer {
|
|||||||
* to a base on another cpu.
|
* to a base on another cpu.
|
||||||
* @lock: lock protecting the base and associated timers
|
* @lock: lock protecting the base and associated timers
|
||||||
* @active: red black tree root node for the active timers
|
* @active: red black tree root node for the active timers
|
||||||
* @pending: list of pending timers for simple time ordered access
|
* @first: pointer to the timer node which expires first
|
||||||
* @resolution: the resolution of the clock, in nanoseconds
|
* @resolution: the resolution of the clock, in nanoseconds
|
||||||
* @get_time: function to retrieve the current time of the clock
|
* @get_time: function to retrieve the current time of the clock
|
||||||
* @curr_timer: the timer which is executing a callback right now
|
* @curr_timer: the timer which is executing a callback right now
|
||||||
@@ -87,8 +84,8 @@ struct hrtimer_base {
|
|||||||
clockid_t index;
|
clockid_t index;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
struct rb_root active;
|
struct rb_root active;
|
||||||
struct list_head pending;
|
struct rb_node *first;
|
||||||
unsigned long resolution;
|
ktime_t resolution;
|
||||||
ktime_t (*get_time)(void);
|
ktime_t (*get_time)(void);
|
||||||
struct hrtimer *curr_timer;
|
struct hrtimer *curr_timer;
|
||||||
};
|
};
|
||||||
@@ -125,8 +122,7 @@ static inline int hrtimer_active(const struct hrtimer *timer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Forward a hrtimer so it expires after now: */
|
/* Forward a hrtimer so it expires after now: */
|
||||||
extern unsigned long hrtimer_forward(struct hrtimer *timer,
|
extern unsigned long hrtimer_forward(struct hrtimer *timer, ktime_t interval);
|
||||||
const ktime_t interval);
|
|
||||||
|
|
||||||
/* Precise sleep: */
|
/* Precise sleep: */
|
||||||
extern long hrtimer_nanosleep(struct timespec *rqtp,
|
extern long hrtimer_nanosleep(struct timespec *rqtp,
|
||||||
|
@@ -272,8 +272,8 @@ static inline u64 ktime_to_ns(const ktime_t kt)
|
|||||||
* idea of the (in)accuracy of timers. Timer values are rounded up to
|
* idea of the (in)accuracy of timers. Timer values are rounded up to
|
||||||
* this resolution values.
|
* this resolution values.
|
||||||
*/
|
*/
|
||||||
#define KTIME_REALTIME_RES (NSEC_PER_SEC/HZ)
|
#define KTIME_REALTIME_RES (ktime_t){ .tv64 = TICK_NSEC }
|
||||||
#define KTIME_MONOTONIC_RES (NSEC_PER_SEC/HZ)
|
#define KTIME_MONOTONIC_RES (ktime_t){ .tv64 = TICK_NSEC }
|
||||||
|
|
||||||
/* Get the monotonic time in timespec format: */
|
/* Get the monotonic time in timespec format: */
|
||||||
extern void ktime_get_ts(struct timespec *ts);
|
extern void ktime_get_ts(struct timespec *ts);
|
||||||
|
@@ -275,7 +275,7 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
|
|||||||
* The number of overruns is added to the overrun field.
|
* The number of overruns is added to the overrun field.
|
||||||
*/
|
*/
|
||||||
unsigned long
|
unsigned long
|
||||||
hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
|
hrtimer_forward(struct hrtimer *timer, ktime_t interval)
|
||||||
{
|
{
|
||||||
unsigned long orun = 1;
|
unsigned long orun = 1;
|
||||||
ktime_t delta, now;
|
ktime_t delta, now;
|
||||||
@@ -287,6 +287,9 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
|
|||||||
if (delta.tv64 < 0)
|
if (delta.tv64 < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (interval.tv64 < timer->base->resolution.tv64)
|
||||||
|
interval.tv64 = timer->base->resolution.tv64;
|
||||||
|
|
||||||
if (unlikely(delta.tv64 >= interval.tv64)) {
|
if (unlikely(delta.tv64 >= interval.tv64)) {
|
||||||
nsec_t incr = ktime_to_ns(interval);
|
nsec_t incr = ktime_to_ns(interval);
|
||||||
|
|
||||||
@@ -314,7 +317,6 @@ hrtimer_forward(struct hrtimer *timer, const ktime_t interval)
|
|||||||
static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
|
static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
|
||||||
{
|
{
|
||||||
struct rb_node **link = &base->active.rb_node;
|
struct rb_node **link = &base->active.rb_node;
|
||||||
struct list_head *prev = &base->pending;
|
|
||||||
struct rb_node *parent = NULL;
|
struct rb_node *parent = NULL;
|
||||||
struct hrtimer *entry;
|
struct hrtimer *entry;
|
||||||
|
|
||||||
@@ -330,22 +332,23 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
|
|||||||
*/
|
*/
|
||||||
if (timer->expires.tv64 < entry->expires.tv64)
|
if (timer->expires.tv64 < entry->expires.tv64)
|
||||||
link = &(*link)->rb_left;
|
link = &(*link)->rb_left;
|
||||||
else {
|
else
|
||||||
link = &(*link)->rb_right;
|
link = &(*link)->rb_right;
|
||||||
prev = &entry->list;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert the timer to the rbtree and to the sorted list:
|
* Insert the timer to the rbtree and check whether it
|
||||||
|
* replaces the first pending timer
|
||||||
*/
|
*/
|
||||||
rb_link_node(&timer->node, parent, link);
|
rb_link_node(&timer->node, parent, link);
|
||||||
rb_insert_color(&timer->node, &base->active);
|
rb_insert_color(&timer->node, &base->active);
|
||||||
list_add(&timer->list, prev);
|
|
||||||
|
|
||||||
timer->state = HRTIMER_PENDING;
|
timer->state = HRTIMER_PENDING;
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!base->first || timer->expires.tv64 <
|
||||||
|
rb_entry(base->first, struct hrtimer, node)->expires.tv64)
|
||||||
|
base->first = &timer->node;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __remove_hrtimer - internal function to remove a timer
|
* __remove_hrtimer - internal function to remove a timer
|
||||||
@@ -355,9 +358,11 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
|
|||||||
static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
|
static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Remove the timer from the sorted list and from the rbtree:
|
* Remove the timer from the rbtree and replace the
|
||||||
|
* first entry pointer if necessary.
|
||||||
*/
|
*/
|
||||||
list_del(&timer->list);
|
if (base->first == &timer->node)
|
||||||
|
base->first = rb_next(&timer->node);
|
||||||
rb_erase(&timer->node, &base->active);
|
rb_erase(&timer->node, &base->active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,9 +521,8 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
|
|||||||
{
|
{
|
||||||
struct hrtimer_base *bases;
|
struct hrtimer_base *bases;
|
||||||
|
|
||||||
tp->tv_sec = 0;
|
|
||||||
bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
|
bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
|
||||||
tp->tv_nsec = bases[which_clock].resolution;
|
*tp = ktime_to_timespec(bases[which_clock].resolution);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -529,16 +533,17 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
|
|||||||
static inline void run_hrtimer_queue(struct hrtimer_base *base)
|
static inline void run_hrtimer_queue(struct hrtimer_base *base)
|
||||||
{
|
{
|
||||||
ktime_t now = base->get_time();
|
ktime_t now = base->get_time();
|
||||||
|
struct rb_node *node;
|
||||||
|
|
||||||
spin_lock_irq(&base->lock);
|
spin_lock_irq(&base->lock);
|
||||||
|
|
||||||
while (!list_empty(&base->pending)) {
|
while ((node = base->first)) {
|
||||||
struct hrtimer *timer;
|
struct hrtimer *timer;
|
||||||
int (*fn)(void *);
|
int (*fn)(void *);
|
||||||
int restart;
|
int restart;
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
timer = list_entry(base->pending.next, struct hrtimer, list);
|
timer = rb_entry(node, struct hrtimer, node);
|
||||||
if (now.tv64 <= timer->expires.tv64)
|
if (now.tv64 <= timer->expires.tv64)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -732,7 +737,6 @@ static void __devinit init_hrtimers_cpu(int cpu)
|
|||||||
|
|
||||||
for (i = 0; i < MAX_HRTIMER_BASES; i++) {
|
for (i = 0; i < MAX_HRTIMER_BASES; i++) {
|
||||||
spin_lock_init(&base->lock);
|
spin_lock_init(&base->lock);
|
||||||
INIT_LIST_HEAD(&base->pending);
|
|
||||||
base++;
|
base++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user