aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 957869fd596..2f3c57417c5 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>
@@ -1038,6 +1040,98 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
1038} 1040}
1039EXPORT_SYMBOL_GPL(hrtimer_start); 1041EXPORT_SYMBOL_GPL(hrtimer_start);
1040 1042
1043#ifdef CONFIG_ARCH_HAS_SEND_PULL_TIMERS
1044
1045/**
1046 * hrtimer_start_on_info_init - Initialize hrtimer_start_on_info
1047 */
1048void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info)
1049{
1050 memset(info, 0, sizeof(struct hrtimer_start_on_info));
1051 atomic_set(&info->state, HRTIMER_START_ON_INACTIVE);
1052}
1053
1054/**
1055 * hrtimer_pull - PULL_TIMERS_VECTOR callback on remote cpu
1056 */
1057void hrtimer_pull(void)
1058{
1059 struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
1060 struct hrtimer_start_on_info *info;
1061 struct list_head *pos, *safe, list;
1062
1063 raw_spin_lock(&base->lock);
1064 list_replace_init(&base->to_pull, &list);
1065 raw_spin_unlock(&base->lock);
1066
1067 list_for_each_safe(pos, safe, &list) {
1068 info = list_entry(pos, struct hrtimer_start_on_info, list);
1069 TRACE("pulled timer 0x%x\n", info->timer);
1070 list_del(pos);
1071 hrtimer_start(info->timer, info->time, info->mode);
1072 }
1073}
1074
1075/**
1076 * hrtimer_start_on - trigger timer arming on remote cpu
1077 * @cpu: remote cpu
1078 * @info: save timer information for enqueuing on remote cpu
1079 * @timer: timer to be pulled
1080 * @time: expire time
1081 * @mode: timer mode
1082 */
1083int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info,
1084 struct hrtimer *timer, ktime_t time,
1085 const enum hrtimer_mode mode)
1086{
1087 unsigned long flags;
1088 struct hrtimer_cpu_base* base;
1089 int in_use = 0, was_empty;
1090
1091 /* serialize access to info through the timer base */
1092 lock_hrtimer_base(timer, &flags);
1093
1094 in_use = (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE);
1095 if (!in_use) {
1096 INIT_LIST_HEAD(&info->list);
1097 info->timer = timer;
1098 info->time = time;
1099 info->mode = mode;
1100 /* mark as in use */
1101 atomic_set(&info->state, HRTIMER_START_ON_QUEUED);
1102 }
1103
1104 unlock_hrtimer_base(timer, &flags);
1105
1106 if (!in_use) {
1107 /* initiate pull */
1108 preempt_disable();
1109 if (cpu == smp_processor_id()) {
1110 /* start timer locally; we may get called
1111 * with rq->lock held, do not wake up anything
1112 */
1113 TRACE("hrtimer_start_on: starting on local CPU\n");
1114 __hrtimer_start_range_ns(info->timer, info->time,
1115 0, info->mode, 0);
1116 } else {
1117 TRACE("hrtimer_start_on: pulling to remote CPU\n");
1118 base = &per_cpu(hrtimer_bases, cpu);
1119 raw_spin_lock_irqsave(&base->lock, flags);
1120 was_empty = list_empty(&base->to_pull);
1121 list_add(&info->list, &base->to_pull);
1122 raw_spin_unlock_irqrestore(&base->lock, flags);
1123 if (was_empty)
1124 /* only send IPI if other no else
1125 * has done so already
1126 */
1127 smp_send_pull_timers(cpu);
1128 }
1129 preempt_enable();
1130 }
1131 return in_use;
1132}
1133
1134#endif
1041 1135
1042/** 1136/**
1043 * hrtimer_try_to_cancel - try to deactivate a timer 1137 * hrtimer_try_to_cancel - try to deactivate a timer
@@ -1648,6 +1742,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
1648 } 1742 }
1649 1743
1650 hrtimer_init_hres(cpu_base); 1744 hrtimer_init_hres(cpu_base);
1745 INIT_LIST_HEAD(&cpu_base->to_pull);
1651} 1746}
1652 1747
1653#ifdef CONFIG_HOTPLUG_CPU 1748#ifdef CONFIG_HOTPLUG_CPU