diff options
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/timekeeping.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 4c7de02eacdc..cbc6acb0db3f 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/tick.h> | 22 | #include <linux/tick.h> |
23 | #include <linux/stop_machine.h> | 23 | #include <linux/stop_machine.h> |
24 | #include <linux/pvclock_gtod.h> | ||
24 | 25 | ||
25 | 26 | ||
26 | static struct timekeeper timekeeper; | 27 | static struct timekeeper timekeeper; |
@@ -174,6 +175,54 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | |||
174 | return nsec + arch_gettimeoffset(); | 175 | return nsec + arch_gettimeoffset(); |
175 | } | 176 | } |
176 | 177 | ||
178 | static RAW_NOTIFIER_HEAD(pvclock_gtod_chain); | ||
179 | |||
180 | static void update_pvclock_gtod(struct timekeeper *tk) | ||
181 | { | ||
182 | raw_notifier_call_chain(&pvclock_gtod_chain, 0, tk); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * pvclock_gtod_register_notifier - register a pvclock timedata update listener | ||
187 | * | ||
188 | * Must hold write on timekeeper.lock | ||
189 | */ | ||
190 | int pvclock_gtod_register_notifier(struct notifier_block *nb) | ||
191 | { | ||
192 | struct timekeeper *tk = &timekeeper; | ||
193 | unsigned long flags; | ||
194 | int ret; | ||
195 | |||
196 | write_seqlock_irqsave(&tk->lock, flags); | ||
197 | ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb); | ||
198 | /* update timekeeping data */ | ||
199 | update_pvclock_gtod(tk); | ||
200 | write_sequnlock_irqrestore(&tk->lock, flags); | ||
201 | |||
202 | return ret; | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(pvclock_gtod_register_notifier); | ||
205 | |||
206 | /** | ||
207 | * pvclock_gtod_unregister_notifier - unregister a pvclock | ||
208 | * timedata update listener | ||
209 | * | ||
210 | * Must hold write on timekeeper.lock | ||
211 | */ | ||
212 | int pvclock_gtod_unregister_notifier(struct notifier_block *nb) | ||
213 | { | ||
214 | struct timekeeper *tk = &timekeeper; | ||
215 | unsigned long flags; | ||
216 | int ret; | ||
217 | |||
218 | write_seqlock_irqsave(&tk->lock, flags); | ||
219 | ret = raw_notifier_chain_unregister(&pvclock_gtod_chain, nb); | ||
220 | write_sequnlock_irqrestore(&tk->lock, flags); | ||
221 | |||
222 | return ret; | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier); | ||
225 | |||
177 | /* must hold write on timekeeper.lock */ | 226 | /* must hold write on timekeeper.lock */ |
178 | static void timekeeping_update(struct timekeeper *tk, bool clearntp) | 227 | static void timekeeping_update(struct timekeeper *tk, bool clearntp) |
179 | { | 228 | { |
@@ -182,6 +231,7 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp) | |||
182 | ntp_clear(); | 231 | ntp_clear(); |
183 | } | 232 | } |
184 | update_vsyscall(tk); | 233 | update_vsyscall(tk); |
234 | update_pvclock_gtod(tk); | ||
185 | } | 235 | } |
186 | 236 | ||
187 | /** | 237 | /** |