aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 0086628b6e97..c0b440b1f6ee 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -46,6 +46,8 @@
46#include <linux/sched.h> 46#include <linux/sched.h>
47#include <linux/timer.h> 47#include <linux/timer.h>
48 48
49#include <litmus/litmus.h>
50
49#include <asm/uaccess.h> 51#include <asm/uaccess.h>
50 52
51#include <trace/events/timer.h> 53#include <trace/events/timer.h>
@@ -1041,6 +1043,85 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
1041} 1043}
1042EXPORT_SYMBOL_GPL(hrtimer_start); 1044EXPORT_SYMBOL_GPL(hrtimer_start);
1043 1045
1046/**
1047 * hrtimer_pull - PULL_TIMERS_VECTOR callback on remote cpu
1048 */
1049void hrtimer_pull(void)
1050{
1051 struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
1052 struct hrtimer_start_on_info *info;
1053 struct list_head *pos, *safe, list;
1054
1055 spin_lock(&base->lock);
1056 list_replace_init(&base->to_pull, &list);
1057 spin_unlock(&base->lock);
1058
1059 list_for_each_safe(pos, safe, &list) {
1060 info = list_entry(pos, struct hrtimer_start_on_info, list);
1061 TRACE("pulled timer 0x%x\n", info->timer);
1062 list_del(pos);
1063 hrtimer_start(info->timer, info->time, info->mode);
1064 }
1065}
1066
1067/**
1068 * hrtimer_start_on - trigger timer arming on remote cpu
1069 * @cpu: remote cpu
1070 * @info: save timer information for enqueuing on remote cpu
1071 * @timer: timer to be pulled
1072 * @time: expire time
1073 * @mode: timer mode
1074 */
1075int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info,
1076 struct hrtimer *timer, ktime_t time,
1077 const enum hrtimer_mode mode)
1078{
1079 unsigned long flags;
1080 struct hrtimer_cpu_base* base;
1081 int in_use = 0, was_empty;
1082
1083 /* serialize access to info through the timer base */
1084 lock_hrtimer_base(timer, &flags);
1085
1086 in_use = (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE);
1087 if (!in_use) {
1088 INIT_LIST_HEAD(&info->list);
1089 info->timer = timer;
1090 info->time = time;
1091 info->mode = mode;
1092 /* mark as in use */
1093 atomic_set(&info->state, HRTIMER_START_ON_QUEUED);
1094 }
1095
1096 unlock_hrtimer_base(timer, &flags);
1097
1098 if (!in_use) {
1099 /* initiate pull */
1100 preempt_disable();
1101 if (cpu == smp_processor_id()) {
1102 /* start timer locally; we may get called
1103 * with rq->lock held, do not wake up anything
1104 */
1105 TRACE("hrtimer_start_on: starting on local CPU\n");
1106 __hrtimer_start_range_ns(info->timer, info->time,
1107 0, info->mode, 0);
1108 } else {
1109 TRACE("hrtimer_start_on: pulling to remote CPU\n");
1110 base = &per_cpu(hrtimer_bases, cpu);
1111 spin_lock_irqsave(&base->lock, flags);
1112 was_empty = list_empty(&base->to_pull);
1113 list_add(&info->list, &base->to_pull);
1114 spin_unlock_irqrestore(&base->lock, flags);
1115 if (was_empty)
1116 /* only send IPI if other no else
1117 * has done so already
1118 */
1119 smp_send_pull_timers(cpu);
1120 }
1121 preempt_enable();
1122 }
1123 return in_use;
1124}
1044 1125
1045/** 1126/**
1046 * hrtimer_try_to_cancel - try to deactivate a timer 1127 * hrtimer_try_to_cancel - try to deactivate a timer
@@ -1631,6 +1712,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
1631 cpu_base->clock_base[i].cpu_base = cpu_base; 1712 cpu_base->clock_base[i].cpu_base = cpu_base;
1632 1713
1633 hrtimer_init_hres(cpu_base); 1714 hrtimer_init_hres(cpu_base);
1715 INIT_LIST_HEAD(&cpu_base->to_pull);
1634} 1716}
1635 1717
1636#ifdef CONFIG_HOTPLUG_CPU 1718#ifdef CONFIG_HOTPLUG_CPU