diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 2288fbdada16..c7f0c79b2cb5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #include <linux/sched/rt.h> | 48 | #include <linux/sched/rt.h> |
49 | #include <linux/timer.h> | 49 | #include <linux/timer.h> |
50 | 50 | ||
51 | #include <litmus/debug_trace.h> | ||
52 | |||
51 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
52 | 54 | ||
53 | #include <trace/events/timer.h> | 55 | #include <trace/events/timer.h> |
@@ -1064,6 +1066,98 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
1064 | } | 1066 | } |
1065 | EXPORT_SYMBOL_GPL(hrtimer_start); | 1067 | EXPORT_SYMBOL_GPL(hrtimer_start); |
1066 | 1068 | ||
1069 | #if defined(CONFIG_ARCH_HAS_SEND_PULL_TIMERS) && defined(CONFIG_SMP) | ||
1070 | |||
1071 | /** | ||
1072 | * hrtimer_start_on_info_init - Initialize hrtimer_start_on_info | ||
1073 | */ | ||
1074 | void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info) | ||
1075 | { | ||
1076 | memset(info, 0, sizeof(struct hrtimer_start_on_info)); | ||
1077 | atomic_set(&info->state, HRTIMER_START_ON_INACTIVE); | ||
1078 | } | ||
1079 | |||
1080 | /** | ||
1081 | * hrtimer_pull - PULL_TIMERS_VECTOR callback on remote cpu | ||
1082 | */ | ||
1083 | void hrtimer_pull(void) | ||
1084 | { | ||
1085 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | ||
1086 | struct hrtimer_start_on_info *info; | ||
1087 | struct list_head *pos, *safe, list; | ||
1088 | |||
1089 | raw_spin_lock(&base->lock); | ||
1090 | list_replace_init(&base->to_pull, &list); | ||
1091 | raw_spin_unlock(&base->lock); | ||
1092 | |||
1093 | list_for_each_safe(pos, safe, &list) { | ||
1094 | info = list_entry(pos, struct hrtimer_start_on_info, list); | ||
1095 | TRACE("pulled timer 0x%x\n", info->timer); | ||
1096 | list_del(pos); | ||
1097 | hrtimer_start(info->timer, info->time, info->mode); | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1102 | * hrtimer_start_on - trigger timer arming on remote cpu | ||
1103 | * @cpu: remote cpu | ||
1104 | * @info: save timer information for enqueuing on remote cpu | ||
1105 | * @timer: timer to be pulled | ||
1106 | * @time: expire time | ||
1107 | * @mode: timer mode | ||
1108 | */ | ||
1109 | int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, | ||
1110 | struct hrtimer *timer, ktime_t time, | ||
1111 | const enum hrtimer_mode mode) | ||
1112 | { | ||
1113 | unsigned long flags; | ||
1114 | struct hrtimer_cpu_base* base; | ||
1115 | int in_use = 0, was_empty; | ||
1116 | |||
1117 | /* serialize access to info through the timer base */ | ||
1118 | lock_hrtimer_base(timer, &flags); | ||
1119 | |||
1120 | in_use = (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE); | ||
1121 | if (!in_use) { | ||
1122 | INIT_LIST_HEAD(&info->list); | ||
1123 | info->timer = timer; | ||
1124 | info->time = time; | ||
1125 | info->mode = mode; | ||
1126 | /* mark as in use */ | ||
1127 | atomic_set(&info->state, HRTIMER_START_ON_QUEUED); | ||
1128 | } | ||
1129 | |||
1130 | unlock_hrtimer_base(timer, &flags); | ||
1131 | |||
1132 | if (!in_use) { | ||
1133 | /* initiate pull */ | ||
1134 | preempt_disable(); | ||
1135 | if (cpu == smp_processor_id()) { | ||
1136 | /* start timer locally; we may get called | ||
1137 | * with rq->lock held, do not wake up anything | ||
1138 | */ | ||
1139 | TRACE("hrtimer_start_on: starting on local CPU\n"); | ||
1140 | __hrtimer_start_range_ns(info->timer, info->time, | ||
1141 | 0, info->mode, 0); | ||
1142 | } else { | ||
1143 | TRACE("hrtimer_start_on: pulling to remote CPU\n"); | ||
1144 | base = &per_cpu(hrtimer_bases, cpu); | ||
1145 | raw_spin_lock_irqsave(&base->lock, flags); | ||
1146 | was_empty = list_empty(&base->to_pull); | ||
1147 | list_add(&info->list, &base->to_pull); | ||
1148 | raw_spin_unlock_irqrestore(&base->lock, flags); | ||
1149 | if (was_empty) | ||
1150 | /* only send IPI if other no else | ||
1151 | * has done so already | ||
1152 | */ | ||
1153 | smp_send_pull_timers(cpu); | ||
1154 | } | ||
1155 | preempt_enable(); | ||
1156 | } | ||
1157 | return in_use; | ||
1158 | } | ||
1159 | |||
1160 | #endif | ||
1067 | 1161 | ||
1068 | /** | 1162 | /** |
1069 | * hrtimer_try_to_cancel - try to deactivate a timer | 1163 | * hrtimer_try_to_cancel - try to deactivate a timer |
@@ -1667,6 +1761,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu) | |||
1667 | } | 1761 | } |
1668 | 1762 | ||
1669 | hrtimer_init_hres(cpu_base); | 1763 | hrtimer_init_hres(cpu_base); |
1764 | INIT_LIST_HEAD(&cpu_base->to_pull); | ||
1670 | } | 1765 | } |
1671 | 1766 | ||
1672 | #ifdef CONFIG_HOTPLUG_CPU | 1767 | #ifdef CONFIG_HOTPLUG_CPU |