diff options
author | Björn Brandenburg <bbb@mpi-sws.org> | 2016-03-08 07:27:43 -0500 |
---|---|---|
committer | Björn Brandenburg <bbb@mpi-sws.org> | 2016-03-08 07:27:43 -0500 |
commit | a8037999bfc074ddfc231ae5af10be3da1511878 (patch) | |
tree | 25649b697aab3137d25cb9620a04d7011b4e24c0 | |
parent | 42dabcddf6995f50bd4acc1fad650fc6bb0a688a (diff) | |
parent | d2bdf416c9c9f5d204bc218a7a36a55605aef89c (diff) |
Merge pull request #6 from Mutinifni/master
Revamped hrtimer_start_on() support
Use smp_call_function_single_async() instead of custom IPI.
-rw-r--r-- | arch/arm/Kconfig | 3 | ||||
-rw-r--r-- | arch/x86/Kconfig | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/entry_arch.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/hw_irq.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/irq_vectors.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 2 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/smp.c | 35 | ||||
-rw-r--r-- | include/linux/hrtimer.h | 32 | ||||
-rw-r--r-- | include/linux/smp.h | 5 | ||||
-rw-r--r-- | include/litmus/litmus.h | 23 | ||||
-rw-r--r-- | kernel/time/hrtimer.c | 95 | ||||
-rw-r--r-- | litmus/Kconfig | 2 | ||||
-rw-r--r-- | litmus/litmus.c | 57 | ||||
-rw-r--r-- | litmus/rt_domain.c | 3 |
15 files changed, 81 insertions, 193 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d3bfc3a4e56a..ce948d46a1b3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -2123,8 +2123,5 @@ source "arch/arm/kvm/Kconfig" | |||
2123 | config ARCH_HAS_FEATHER_TRACE | 2123 | config ARCH_HAS_FEATHER_TRACE |
2124 | def_bool n | 2124 | def_bool n |
2125 | 2125 | ||
2126 | config ARCH_HAS_SEND_PULL_TIMERS | ||
2127 | def_bool n | ||
2128 | |||
2129 | source "litmus/Kconfig" | 2126 | source "litmus/Kconfig" |
2130 | 2127 | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f9c9a4d70b24..6331227b4686 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -2598,7 +2598,4 @@ source "lib/Kconfig" | |||
2598 | config ARCH_HAS_FEATHER_TRACE | 2598 | config ARCH_HAS_FEATHER_TRACE |
2599 | def_bool y | 2599 | def_bool y |
2600 | 2600 | ||
2601 | config ARCH_HAS_SEND_PULL_TIMERS | ||
2602 | def_bool y | ||
2603 | |||
2604 | source "litmus/Kconfig" | 2601 | source "litmus/Kconfig" |
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index e657219d7964..dc5fa661465f 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
@@ -13,7 +13,6 @@ | |||
13 | BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) | 13 | BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) |
14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) | 14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) |
15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) | 15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) |
16 | BUILD_INTERRUPT(pull_timers_interrupt,PULL_TIMERS_VECTOR) | ||
17 | BUILD_INTERRUPT3(irq_move_cleanup_interrupt, IRQ_MOVE_CLEANUP_VECTOR, | 16 | BUILD_INTERRUPT3(irq_move_cleanup_interrupt, IRQ_MOVE_CLEANUP_VECTOR, |
18 | smp_irq_move_cleanup_interrupt) | 17 | smp_irq_move_cleanup_interrupt) |
19 | BUILD_INTERRUPT3(reboot_interrupt, REBOOT_VECTOR, smp_reboot_interrupt) | 18 | BUILD_INTERRUPT3(reboot_interrupt, REBOOT_VECTOR, smp_reboot_interrupt) |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 3e860d1f9416..e9571ddabc4f 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -77,8 +77,6 @@ extern asmlinkage void threshold_interrupt(void); | |||
77 | extern asmlinkage void call_function_interrupt(void); | 77 | extern asmlinkage void call_function_interrupt(void); |
78 | extern asmlinkage void call_function_single_interrupt(void); | 78 | extern asmlinkage void call_function_single_interrupt(void); |
79 | 79 | ||
80 | extern asmlinkage void pull_timers_interrupt(void); | ||
81 | |||
82 | #ifdef CONFIG_TRACING | 80 | #ifdef CONFIG_TRACING |
83 | /* Interrupt handlers registered during init_IRQ */ | 81 | /* Interrupt handlers registered during init_IRQ */ |
84 | extern void trace_apic_timer_interrupt(void); | 82 | extern void trace_apic_timer_interrupt(void); |
@@ -91,7 +89,6 @@ extern void trace_reschedule_interrupt(void); | |||
91 | extern void trace_threshold_interrupt(void); | 89 | extern void trace_threshold_interrupt(void); |
92 | extern void trace_call_function_interrupt(void); | 90 | extern void trace_call_function_interrupt(void); |
93 | extern void trace_call_function_single_interrupt(void); | 91 | extern void trace_call_function_single_interrupt(void); |
94 | extern void trace_pull_timers_interrupt(void); | ||
95 | #define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt | 92 | #define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt |
96 | #define trace_reboot_interrupt reboot_interrupt | 93 | #define trace_reboot_interrupt reboot_interrupt |
97 | #define trace_kvm_posted_intr_ipi kvm_posted_intr_ipi | 94 | #define trace_kvm_posted_intr_ipi kvm_posted_intr_ipi |
@@ -182,7 +179,6 @@ extern __visible void smp_reschedule_interrupt(struct pt_regs *); | |||
182 | extern __visible void smp_call_function_interrupt(struct pt_regs *); | 179 | extern __visible void smp_call_function_interrupt(struct pt_regs *); |
183 | extern __visible void smp_call_function_single_interrupt(struct pt_regs *); | 180 | extern __visible void smp_call_function_single_interrupt(struct pt_regs *); |
184 | extern __visible void smp_invalidate_interrupt(struct pt_regs *); | 181 | extern __visible void smp_invalidate_interrupt(struct pt_regs *); |
185 | extern __visible void smp_pull_timers_interrupt(struct pt_regs *); | ||
186 | #endif | 182 | #endif |
187 | 183 | ||
188 | extern char irq_entries_start[]; | 184 | extern char irq_entries_start[]; |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 82545836e1a1..666c89ec4bd7 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -124,12 +124,6 @@ | |||
124 | */ | 124 | */ |
125 | #define LOCAL_TIMER_VECTOR 0xef | 125 | #define LOCAL_TIMER_VECTOR 0xef |
126 | 126 | ||
127 | /* | ||
128 | * LITMUS^RT pull timers IRQ vector. | ||
129 | * Make sure it's not used by Linux. | ||
130 | */ | ||
131 | #define PULL_TIMERS_VECTOR 0xdf | ||
132 | |||
133 | #define NR_VECTORS 256 | 127 | #define NR_VECTORS 256 |
134 | 128 | ||
135 | #ifdef CONFIG_X86_LOCAL_APIC | 129 | #ifdef CONFIG_X86_LOCAL_APIC |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index d810f5fea04f..02c2eff7478d 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -947,8 +947,6 @@ apicinterrupt CALL_FUNCTION_VECTOR \ | |||
947 | call_function_interrupt smp_call_function_interrupt | 947 | call_function_interrupt smp_call_function_interrupt |
948 | apicinterrupt RESCHEDULE_VECTOR \ | 948 | apicinterrupt RESCHEDULE_VECTOR \ |
949 | reschedule_interrupt smp_reschedule_interrupt | 949 | reschedule_interrupt smp_reschedule_interrupt |
950 | apicinterrupt PULL_TIMERS_VECTOR \ | ||
951 | pull_timers_interrupt smp_pull_timers_interrupt | ||
952 | #endif | 950 | #endif |
953 | 951 | ||
954 | apicinterrupt ERROR_APIC_VECTOR \ | 952 | apicinterrupt ERROR_APIC_VECTOR \ |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 834496ed9536..cd10a6437264 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -115,9 +115,6 @@ static void __init smp_intr_init(void) | |||
115 | alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, | 115 | alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, |
116 | call_function_single_interrupt); | 116 | call_function_single_interrupt); |
117 | 117 | ||
118 | /* IPI for hrtimer pulling on remote cpus */ | ||
119 | alloc_intr_gate(PULL_TIMERS_VECTOR, pull_timers_interrupt); | ||
120 | |||
121 | /* Low priority IPI to cleanup after moving an irq */ | 118 | /* Low priority IPI to cleanup after moving an irq */ |
122 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); | 119 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); |
123 | set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); | 120 | set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); |
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 431c3d29a667..cffff2a8eb8b 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/gfp.h> | 25 | #include <linux/gfp.h> |
26 | 26 | ||
27 | #include <litmus/preempt.h> | 27 | #include <litmus/preempt.h> |
28 | #include <litmus/debug_trace.h> | ||
29 | 28 | ||
30 | #include <asm/mtrr.h> | 29 | #include <asm/mtrr.h> |
31 | #include <asm/tlbflush.h> | 30 | #include <asm/tlbflush.h> |
@@ -167,16 +166,6 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) | |||
167 | return NMI_HANDLED; | 166 | return NMI_HANDLED; |
168 | } | 167 | } |
169 | 168 | ||
170 | /* trigger timers on remote cpu */ | ||
171 | void smp_send_pull_timers(int cpu) | ||
172 | { | ||
173 | if (unlikely(cpu_is_offline(cpu))) { | ||
174 | WARN_ON(1); | ||
175 | return; | ||
176 | } | ||
177 | apic->send_IPI_mask(cpumask_of(cpu), PULL_TIMERS_VECTOR); | ||
178 | } | ||
179 | |||
180 | /* | 169 | /* |
181 | * this function calls the 'stop' function on all other CPUs in the system. | 170 | * this function calls the 'stop' function on all other CPUs in the system. |
182 | */ | 171 | */ |
@@ -359,30 +348,6 @@ static int __init nonmi_ipi_setup(char *str) | |||
359 | 348 | ||
360 | __setup("nonmi_ipi", nonmi_ipi_setup); | 349 | __setup("nonmi_ipi", nonmi_ipi_setup); |
361 | 350 | ||
362 | extern void hrtimer_pull(void); | ||
363 | |||
364 | static inline void __smp_pull_timers_interrupt(void) | ||
365 | { | ||
366 | TRACE("pull timer interrupt\n"); | ||
367 | hrtimer_pull(); | ||
368 | } | ||
369 | |||
370 | __visible void smp_pull_timers_interrupt(struct pt_regs *regs) | ||
371 | { | ||
372 | smp_entering_irq(); | ||
373 | __smp_pull_timers_interrupt(); | ||
374 | exiting_irq(); | ||
375 | } | ||
376 | |||
377 | __visible void smp_trace_pull_timers_interrupt(struct pt_regs *regs) | ||
378 | { | ||
379 | smp_entering_irq(); | ||
380 | trace_call_function_single_entry(PULL_TIMERS_VECTOR); | ||
381 | __smp_pull_timers_interrupt(); | ||
382 | trace_call_function_single_exit(PULL_TIMERS_VECTOR); | ||
383 | exiting_irq(); | ||
384 | } | ||
385 | |||
386 | struct smp_ops smp_ops = { | 351 | struct smp_ops smp_ops = { |
387 | .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, | 352 | .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, |
388 | .smp_prepare_cpus = native_smp_prepare_cpus, | 353 | .smp_prepare_cpus = native_smp_prepare_cpus, |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index d1be5d2cb8fc..05f6df1fdf5b 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -178,7 +178,6 @@ enum hrtimer_base_type { | |||
178 | * @nr_hangs: Total number of hrtimer interrupt hangs | 178 | * @nr_hangs: Total number of hrtimer interrupt hangs |
179 | * @max_hang_time: Maximum time spent in hrtimer_interrupt | 179 | * @max_hang_time: Maximum time spent in hrtimer_interrupt |
180 | * @clock_base: array of clock bases for this cpu | 180 | * @clock_base: array of clock bases for this cpu |
181 | * @to_pull: LITMUS^RT list of timers to be pulled on this cpu | ||
182 | */ | 181 | */ |
183 | struct hrtimer_cpu_base { | 182 | struct hrtimer_cpu_base { |
184 | raw_spinlock_t lock; | 183 | raw_spinlock_t lock; |
@@ -196,32 +195,8 @@ struct hrtimer_cpu_base { | |||
196 | ktime_t max_hang_time; | 195 | ktime_t max_hang_time; |
197 | #endif | 196 | #endif |
198 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; | 197 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; |
199 | struct list_head to_pull; | ||
200 | }; | 198 | }; |
201 | 199 | ||
202 | #ifdef CONFIG_ARCH_HAS_SEND_PULL_TIMERS | ||
203 | |||
204 | #define HRTIMER_START_ON_INACTIVE 0 | ||
205 | #define HRTIMER_START_ON_QUEUED 1 | ||
206 | |||
207 | /* | ||
208 | * struct hrtimer_start_on_info - save timer info on remote cpu | ||
209 | * @list: list of hrtimer_start_on_info on remote cpu (to_pull) | ||
210 | * @timer: timer to be triggered on remote cpu | ||
211 | * @time: time event | ||
212 | * @mode: timer mode | ||
213 | * @state: activity flag | ||
214 | */ | ||
215 | struct hrtimer_start_on_info { | ||
216 | struct list_head list; | ||
217 | struct hrtimer *timer; | ||
218 | ktime_t time; | ||
219 | enum hrtimer_mode mode; | ||
220 | atomic_t state; | ||
221 | }; | ||
222 | |||
223 | #endif | ||
224 | |||
225 | static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time) | 200 | static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time) |
226 | { | 201 | { |
227 | timer->node.expires = time; | 202 | timer->node.expires = time; |
@@ -387,13 +362,6 @@ __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, | |||
387 | unsigned long delta_ns, | 362 | unsigned long delta_ns, |
388 | const enum hrtimer_mode mode, int wakeup); | 363 | const enum hrtimer_mode mode, int wakeup); |
389 | 364 | ||
390 | #ifdef CONFIG_ARCH_HAS_SEND_PULL_TIMERS | ||
391 | extern void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info); | ||
392 | extern int hrtimer_start_on(int cpu, struct hrtimer_start_on_info *info, | ||
393 | struct hrtimer *timer, ktime_t time, | ||
394 | const enum hrtimer_mode mode); | ||
395 | #endif | ||
396 | |||
397 | extern int hrtimer_cancel(struct hrtimer *timer); | 365 | extern int hrtimer_cancel(struct hrtimer *timer); |
398 | extern int hrtimer_try_to_cancel(struct hrtimer *timer); | 366 | extern int hrtimer_try_to_cancel(struct hrtimer *timer); |
399 | 367 | ||
diff --git a/include/linux/smp.h b/include/linux/smp.h index dfc63fe33a63..c4414074bd88 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
@@ -103,11 +103,6 @@ void kick_all_cpus_sync(void); | |||
103 | void wake_up_all_idle_cpus(void); | 103 | void wake_up_all_idle_cpus(void); |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * sends a 'pull timer' event to a remote CPU | ||
107 | */ | ||
108 | extern void smp_send_pull_timers(int cpu); | ||
109 | |||
110 | /* | ||
111 | * Generic and arch helpers | 106 | * Generic and arch helpers |
112 | */ | 107 | */ |
113 | void __init call_function_init(void); | 108 | void __init call_function_init(void); |
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h index a6eb534ee0fa..c3a52aea60fb 100644 --- a/include/litmus/litmus.h +++ b/include/litmus/litmus.h | |||
@@ -319,4 +319,27 @@ static inline int has_control_page(struct task_struct* t) | |||
319 | 319 | ||
320 | #endif | 320 | #endif |
321 | 321 | ||
322 | #ifdef CONFIG_SMP | ||
323 | |||
324 | /* | ||
325 | * struct hrtimer_start_on_info - timer info on remote cpu | ||
326 | * @timer: timer to be triggered on remote cpu | ||
327 | * @time: time event | ||
328 | * @mode: timer mode | ||
329 | * @csd: smp_call_function parameter to call hrtimer_pull on remote cpu | ||
330 | */ | ||
331 | struct hrtimer_start_on_info { | ||
332 | struct hrtimer *timer; | ||
333 | ktime_t time; | ||
334 | enum hrtimer_mode mode; | ||
335 | struct call_single_data csd; | ||
336 | }; | ||
337 | |||
338 | void hrtimer_pull(void *csd_info); | ||
339 | extern void hrtimer_start_on(int cpu, struct hrtimer_start_on_info *info, | ||
340 | struct hrtimer *timer, ktime_t time, | ||
341 | const enum hrtimer_mode mode); | ||
342 | |||
343 | #endif | ||
344 | |||
322 | #endif | 345 | #endif |
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index d5a8e4db0bf9..bb281cfa31e9 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c | |||
@@ -50,8 +50,6 @@ | |||
50 | #include <linux/timer.h> | 50 | #include <linux/timer.h> |
51 | #include <linux/freezer.h> | 51 | #include <linux/freezer.h> |
52 | 52 | ||
53 | #include <litmus/debug_trace.h> | ||
54 | |||
55 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
56 | 54 | ||
57 | #include <trace/events/timer.h> | 55 | #include <trace/events/timer.h> |
@@ -1049,98 +1047,6 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
1049 | } | 1047 | } |
1050 | EXPORT_SYMBOL_GPL(hrtimer_start); | 1048 | EXPORT_SYMBOL_GPL(hrtimer_start); |
1051 | 1049 | ||
1052 | #if defined(CONFIG_ARCH_HAS_SEND_PULL_TIMERS) && defined(CONFIG_SMP) | ||
1053 | |||
1054 | /** | ||
1055 | * hrtimer_start_on_info_init - Initialize hrtimer_start_on_info | ||
1056 | */ | ||
1057 | void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info) | ||
1058 | { | ||
1059 | memset(info, 0, sizeof(struct hrtimer_start_on_info)); | ||
1060 | atomic_set(&info->state, HRTIMER_START_ON_INACTIVE); | ||
1061 | } | ||
1062 | |||
1063 | /** | ||
1064 | * hrtimer_pull - PULL_TIMERS_VECTOR callback on remote cpu | ||
1065 | */ | ||
1066 | void hrtimer_pull(void) | ||
1067 | { | ||
1068 | struct hrtimer_cpu_base *base = this_cpu_ptr(&hrtimer_bases); | ||
1069 | struct hrtimer_start_on_info *info; | ||
1070 | struct list_head *pos, *safe, list; | ||
1071 | |||
1072 | raw_spin_lock(&base->lock); | ||
1073 | list_replace_init(&base->to_pull, &list); | ||
1074 | raw_spin_unlock(&base->lock); | ||
1075 | |||
1076 | list_for_each_safe(pos, safe, &list) { | ||
1077 | info = list_entry(pos, struct hrtimer_start_on_info, list); | ||
1078 | TRACE("pulled timer 0x%x\n", info->timer); | ||
1079 | list_del(pos); | ||
1080 | hrtimer_start(info->timer, info->time, info->mode); | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | /** | ||
1085 | * hrtimer_start_on - trigger timer arming on remote cpu | ||
1086 | * @cpu: remote cpu | ||
1087 | * @info: save timer information for enqueuing on remote cpu | ||
1088 | * @timer: timer to be pulled | ||
1089 | * @time: expire time | ||
1090 | * @mode: timer mode | ||
1091 | */ | ||
1092 | int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, | ||
1093 | struct hrtimer *timer, ktime_t time, | ||
1094 | const enum hrtimer_mode mode) | ||
1095 | { | ||
1096 | unsigned long flags; | ||
1097 | struct hrtimer_cpu_base* base; | ||
1098 | int in_use = 0, was_empty; | ||
1099 | |||
1100 | /* serialize access to info through the timer base */ | ||
1101 | lock_hrtimer_base(timer, &flags); | ||
1102 | |||
1103 | in_use = (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE); | ||
1104 | if (!in_use) { | ||
1105 | INIT_LIST_HEAD(&info->list); | ||
1106 | info->timer = timer; | ||
1107 | info->time = time; | ||
1108 | info->mode = mode; | ||
1109 | /* mark as in use */ | ||
1110 | atomic_set(&info->state, HRTIMER_START_ON_QUEUED); | ||
1111 | } | ||
1112 | |||
1113 | unlock_hrtimer_base(timer, &flags); | ||
1114 | |||
1115 | if (!in_use) { | ||
1116 | /* initiate pull */ | ||
1117 | preempt_disable(); | ||
1118 | if (cpu == smp_processor_id()) { | ||
1119 | /* start timer locally; we may get called | ||
1120 | * with rq->lock held, do not wake up anything | ||
1121 | */ | ||
1122 | TRACE("hrtimer_start_on: starting on local CPU\n"); | ||
1123 | __hrtimer_start_range_ns(info->timer, info->time, | ||
1124 | 0, info->mode, 0); | ||
1125 | } else { | ||
1126 | TRACE("hrtimer_start_on: pulling to remote CPU\n"); | ||
1127 | base = &per_cpu(hrtimer_bases, cpu); | ||
1128 | raw_spin_lock_irqsave(&base->lock, flags); | ||
1129 | was_empty = list_empty(&base->to_pull); | ||
1130 | list_add(&info->list, &base->to_pull); | ||
1131 | raw_spin_unlock_irqrestore(&base->lock, flags); | ||
1132 | if (was_empty) | ||
1133 | /* only send IPI if other no else | ||
1134 | * has done so already | ||
1135 | */ | ||
1136 | smp_send_pull_timers(cpu); | ||
1137 | } | ||
1138 | preempt_enable(); | ||
1139 | } | ||
1140 | return in_use; | ||
1141 | } | ||
1142 | |||
1143 | #endif | ||
1144 | 1050 | ||
1145 | /** | 1051 | /** |
1146 | * hrtimer_try_to_cancel - try to deactivate a timer | 1052 | * hrtimer_try_to_cancel - try to deactivate a timer |
@@ -1722,7 +1628,6 @@ static void init_hrtimers_cpu(int cpu) | |||
1722 | 1628 | ||
1723 | cpu_base->cpu = cpu; | 1629 | cpu_base->cpu = cpu; |
1724 | hrtimer_init_hres(cpu_base); | 1630 | hrtimer_init_hres(cpu_base); |
1725 | INIT_LIST_HEAD(&cpu_base->to_pull); | ||
1726 | } | 1631 | } |
1727 | 1632 | ||
1728 | #ifdef CONFIG_HOTPLUG_CPU | 1633 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/litmus/Kconfig b/litmus/Kconfig index babb43deffb5..b0ea45d82532 100644 --- a/litmus/Kconfig +++ b/litmus/Kconfig | |||
@@ -27,7 +27,7 @@ config PLUGIN_PFAIR | |||
27 | 27 | ||
28 | config RELEASE_MASTER | 28 | config RELEASE_MASTER |
29 | bool "Release-master Support" | 29 | bool "Release-master Support" |
30 | depends on ARCH_HAS_SEND_PULL_TIMERS && SMP | 30 | depends on SMP |
31 | default n | 31 | default n |
32 | help | 32 | help |
33 | Allow one processor to act as a dedicated interrupt processor | 33 | Allow one processor to act as a dedicated interrupt processor |
diff --git a/litmus/litmus.c b/litmus/litmus.c index 885d75493118..c03de2dcea0c 100644 --- a/litmus/litmus.c +++ b/litmus/litmus.c | |||
@@ -648,6 +648,63 @@ static struct notifier_block shutdown_notifier = { | |||
648 | .notifier_call = litmus_shutdown_nb, | 648 | .notifier_call = litmus_shutdown_nb, |
649 | }; | 649 | }; |
650 | 650 | ||
651 | /** | ||
652 | * Triggering hrtimers on specific cpus as required by arm_release_timer(_on) | ||
653 | */ | ||
654 | #ifdef CONFIG_SMP | ||
655 | |||
656 | /** | ||
657 | * hrtimer_pull - smp_call_function_single_async callback on remote cpu | ||
658 | */ | ||
659 | void hrtimer_pull(void *csd_info) | ||
660 | { | ||
661 | struct hrtimer_start_on_info *info = csd_info; | ||
662 | TRACE("pulled timer 0x%x\n", info->timer); | ||
663 | hrtimer_start_range_ns(info->timer, info->time, 0, info->mode); | ||
664 | } | ||
665 | |||
666 | /** | ||
667 | * hrtimer_start_on - trigger timer arming on remote cpu | ||
668 | * @cpu: remote cpu | ||
669 | * @info: save timer information for enqueuing on remote cpu | ||
670 | * @timer: timer to be pulled | ||
671 | * @time: expire time | ||
672 | * @mode: timer mode | ||
673 | */ | ||
674 | void hrtimer_start_on(int cpu, struct hrtimer_start_on_info *info, | ||
675 | struct hrtimer *timer, ktime_t time, | ||
676 | const enum hrtimer_mode mode) | ||
677 | { | ||
678 | info->timer = timer; | ||
679 | info->time = time; | ||
680 | info->mode = mode; | ||
681 | |||
682 | /* initialize call_single_data struct */ | ||
683 | info->csd.func = &hrtimer_pull; | ||
684 | info->csd.info = info; | ||
685 | info->csd.flags = 0; | ||
686 | |||
687 | /* initiate pull */ | ||
688 | preempt_disable(); | ||
689 | if (cpu == smp_processor_id()) { | ||
690 | /* start timer locally; we may get called | ||
691 | * with rq->lock held, do not wake up anything | ||
692 | */ | ||
693 | TRACE("hrtimer_start_on: starting on local CPU\n"); | ||
694 | __hrtimer_start_range_ns(info->timer, info->time, | ||
695 | 0, info->mode, 0); | ||
696 | } else { | ||
697 | /* call hrtimer_pull() on remote cpu | ||
698 | * to start remote timer asynchronously | ||
699 | */ | ||
700 | TRACE("hrtimer_start_on: pulling to remote CPU\n"); | ||
701 | smp_call_function_single_async(cpu, &info->csd); | ||
702 | } | ||
703 | preempt_enable(); | ||
704 | } | ||
705 | |||
706 | #endif /* CONFIG_SMP */ | ||
707 | |||
651 | static int __init _init_litmus(void) | 708 | static int __init _init_litmus(void) |
652 | { | 709 | { |
653 | /* Common initializers, | 710 | /* Common initializers, |
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c index e5dec0bbbba9..c7638d0bd0d5 100644 --- a/litmus/rt_domain.c +++ b/litmus/rt_domain.c | |||
@@ -169,9 +169,6 @@ static void reinit_release_heap(struct task_struct* t) | |||
169 | 169 | ||
170 | /* initialize */ | 170 | /* initialize */ |
171 | bheap_init(&rh->heap); | 171 | bheap_init(&rh->heap); |
172 | #ifdef CONFIG_RELEASE_MASTER | ||
173 | atomic_set(&rh->info.state, HRTIMER_START_ON_INACTIVE); | ||
174 | #endif | ||
175 | } | 172 | } |
176 | /* arm_release_timer() - start local release timer or trigger | 173 | /* arm_release_timer() - start local release timer or trigger |
177 | * remote timer (pull timer) | 174 | * remote timer (pull timer) |