Skip to content

Commit 597d027

Browse files
Arun R BharadwajKAGA-KOKO
authored andcommitted
timers: Framework for identifying pinned timers
* Arun R Bharadwaj <[email protected]> [2009-04-16 12:11:36]: This patch creates a new framework for identifying cpu-pinned timers and hrtimers. This framework is needed because pinned timers are expected to fire on the same CPU on which they are queued. So it is essential to identify these and not migrate them, in case there are any. For regular timers, the currently existing add_timer_on() can be used queue pinned timers and subsequently mod_timer_pinned() can be used to modify the 'expires' field. For hrtimers, new modes HRTIMER_ABS_PINNED and HRTIMER_REL_PINNED are added to queue cpu-pinned hrtimer. [ tglx: use .._PINNED mode argument instead of creating tons of new functions ] Signed-off-by: Arun R Bharadwaj <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]>
1 parent a041988 commit 597d027

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

include/linux/hrtimer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ struct hrtimer_cpu_base;
3030
* Mode arguments of xxx_hrtimer functions:
3131
*/
3232
enum hrtimer_mode {
33-
HRTIMER_MODE_ABS, /* Time value is absolute */
34-
HRTIMER_MODE_REL, /* Time value is relative to now */
33+
HRTIMER_MODE_ABS = 0x0, /* Time value is absolute */
34+
HRTIMER_MODE_REL = 0x1, /* Time value is relative to now */
35+
HRTIMER_MODE_PINNED = 0x02, /* Timer is bound to CPU */
36+
HRTIMER_MODE_ABS_PINNED = 0x02,
37+
HRTIMER_MODE_REL_PINNED = 0x03,
3538
};
3639

3740
/*

include/linux/timer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ extern void add_timer_on(struct timer_list *timer, int cpu);
163163
extern int del_timer(struct timer_list * timer);
164164
extern int mod_timer(struct timer_list *timer, unsigned long expires);
165165
extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
166+
extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);
166167

168+
#define TIMER_NOT_PINNED 0
169+
#define TIMER_PINNED 1
167170
/*
168171
* The jiffies value which is added to now, when there is no timer
169172
* in the timer wheel:

kernel/hrtimer.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
193193
* Switch the timer base to the current CPU when possible.
194194
*/
195195
static inline struct hrtimer_clock_base *
196-
switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base)
196+
switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
197+
int pinned)
197198
{
198199
struct hrtimer_clock_base *new_base;
199200
struct hrtimer_cpu_base *new_cpu_base;
@@ -907,9 +908,9 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
907908
ret = remove_hrtimer(timer, base);
908909

909910
/* Switch the timer base, if necessary: */
910-
new_base = switch_hrtimer_base(timer, base);
911+
new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
911912

912-
if (mode == HRTIMER_MODE_REL) {
913+
if (mode & HRTIMER_MODE_REL) {
913914
tim = ktime_add_safe(tim, new_base->get_time());
914915
/*
915916
* CONFIG_TIME_LOW_RES is a temporary way for architectures

kernel/timer.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,8 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer,
604604
}
605605

606606
static inline int
607-
__mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
607+
__mod_timer(struct timer_list *timer, unsigned long expires,
608+
bool pending_only, int pinned)
608609
{
609610
struct tvec_base *base, *new_base;
610611
unsigned long flags;
@@ -668,7 +669,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
668669
*/
669670
int mod_timer_pending(struct timer_list *timer, unsigned long expires)
670671
{
671-
return __mod_timer(timer, expires, true);
672+
return __mod_timer(timer, expires, true, TIMER_NOT_PINNED);
672673
}
673674
EXPORT_SYMBOL(mod_timer_pending);
674675

@@ -702,10 +703,32 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
702703
if (timer->expires == expires && timer_pending(timer))
703704
return 1;
704705

705-
return __mod_timer(timer, expires, false);
706+
return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
706707
}
707708
EXPORT_SYMBOL(mod_timer);
708709

710+
/**
711+
* mod_timer_pinned - modify a timer's timeout
712+
* @timer: the timer to be modified
713+
* @expires: new timeout in jiffies
714+
*
715+
* mod_timer_pinned() is a way to update the expire field of an
716+
* active timer (if the timer is inactive it will be activated)
717+
* and not allow the timer to be migrated to a different CPU.
718+
*
719+
* mod_timer_pinned(timer, expires) is equivalent to:
720+
*
721+
* del_timer(timer); timer->expires = expires; add_timer(timer);
722+
*/
723+
int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
724+
{
725+
if (timer->expires == expires && timer_pending(timer))
726+
return 1;
727+
728+
return __mod_timer(timer, expires, false, TIMER_PINNED);
729+
}
730+
EXPORT_SYMBOL(mod_timer_pinned);
731+
709732
/**
710733
* add_timer - start a timer
711734
* @timer: the timer to be added
@@ -1356,7 +1379,7 @@ signed long __sched schedule_timeout(signed long timeout)
13561379
expire = timeout + jiffies;
13571380

13581381
setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
1359-
__mod_timer(&timer, expire, false);
1382+
__mod_timer(&timer, expire, false, TIMER_NOT_PINNED);
13601383
schedule();
13611384
del_singleshot_timer_sync(&timer);
13621385

0 commit comments

Comments
 (0)