1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/timers/alarm_timer_chromeos.h"
6 
7 #include <stdint.h>
8 #include <sys/timerfd.h>
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/files/file_util.h"
14 #include "base/lazy_instance.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/pending_task.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "base/threading/thread.h"
21 #include "base/trace_event/trace_event.h"
22 
23 namespace timers {
24 namespace {
25 // This class represents the IO thread that the AlarmTimer::Delegate may use for
26 // watching file descriptors if it gets called from a thread that does not have
27 // a MessageLoopForIO.  It is a lazy global instance because it may not always
28 // be necessary.
29 class RtcAlarmIOThread : public base::Thread {
30  public:
RtcAlarmIOThread()31   RtcAlarmIOThread() : Thread("RTC Alarm IO Thread") {
32     CHECK(
33         StartWithOptions(base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
34   }
~RtcAlarmIOThread()35   ~RtcAlarmIOThread() override { Stop(); }
36 };
37 
38 base::LazyInstance<RtcAlarmIOThread> g_io_thread = LAZY_INSTANCE_INITIALIZER;
39 
40 }  // namespace
41 
42 // Watches a MessageLoop and runs a callback if that MessageLoop will be
43 // destroyed.
44 class AlarmTimer::MessageLoopObserver
45     : public base::MessageLoop::DestructionObserver {
46  public:
47   // Constructs a MessageLoopObserver that will observe |message_loop| and will
48   // call |on_will_be_destroyed_callback| when |message_loop| is about to be
49   // destroyed.
MessageLoopObserver(base::MessageLoop * message_loop,base::Closure on_will_be_destroyed_callback)50   MessageLoopObserver(base::MessageLoop* message_loop,
51                       base::Closure on_will_be_destroyed_callback)
52       : message_loop_(message_loop),
53         on_will_be_destroyed_callback_(on_will_be_destroyed_callback) {
54     DCHECK(message_loop_);
55     message_loop_->AddDestructionObserver(this);
56   }
57 
~MessageLoopObserver()58   ~MessageLoopObserver() override {
59     // If |message_loop_| was destroyed, then this class will have already
60     // unregistered itself.  Doing it again will trigger a warning.
61     if (message_loop_)
62       message_loop_->RemoveDestructionObserver(this);
63   }
64 
65   // base::MessageLoop::DestructionObserver override.
WillDestroyCurrentMessageLoop()66   void WillDestroyCurrentMessageLoop() override {
67     message_loop_->RemoveDestructionObserver(this);
68     message_loop_ = NULL;
69 
70     on_will_be_destroyed_callback_.Run();
71   }
72 
73  private:
74   // The MessageLoop that this class should watch.  Is a weak pointer.
75   base::MessageLoop* message_loop_;
76 
77   // The callback to run when |message_loop_| will be destroyed.
78   base::Closure on_will_be_destroyed_callback_;
79 
80   DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver);
81 };
82 
83 // This class manages a Real Time Clock (RTC) alarm, a feature that is available
84 // from linux version 3.11 onwards.  It creates a file descriptor for the RTC
85 // alarm timer and then watches that file descriptor to see when it can be read
86 // without blocking, indicating that the timer has fired.
87 //
88 // A major problem for this class is that watching file descriptors is only
89 // available on a MessageLoopForIO but there is no guarantee the timer is going
90 // to be created on one.  To get around this, the timer has a dedicated thread
91 // with a MessageLoopForIO that posts tasks back to the thread that started the
92 // timer.
93 class AlarmTimer::Delegate
94     : public base::RefCountedThreadSafe<AlarmTimer::Delegate>,
95       public base::MessageLoopForIO::Watcher {
96  public:
97   // Construct a Delegate for the AlarmTimer.  It should be safe to call
98   // |on_timer_fired_callback| multiple times.
99   explicit Delegate(base::Closure on_timer_fired_callback);
100 
101   // Returns true if the system timer managed by this delegate is capable of
102   // waking the system from suspend.
103   bool CanWakeFromSuspend();
104 
105   // Resets the timer to fire after |delay| has passed.  Cancels any
106   // pre-existing delay.
107   void Reset(base::TimeDelta delay);
108 
109   // Stops the currently running timer.  It should be safe to call this even if
110   // the timer is not running.
111   void Stop();
112 
113   // Sets a hook that will be called when the timer fires and a task has been
114   // queued on |origin_task_runner_|.  Used by tests to wait until a task is
115   // pending in the MessageLoop.
116   void SetTimerFiredCallbackForTest(base::Closure test_callback);
117 
118   // base::MessageLoopForIO::Watcher overrides.
119   void OnFileCanReadWithoutBlocking(int fd) override;
120   void OnFileCanWriteWithoutBlocking(int fd) override;
121 
122  private:
123   friend class base::RefCountedThreadSafe<Delegate>;
124   ~Delegate() override;
125 
126   // Actually performs the system calls to set up the timer.  This must be
127   // called on a MessageLoopForIO.
128   void ResetImpl(base::TimeDelta delay, int reset_sequence_number);
129 
130   // Callback that is run when the timer fires.  Must be run on
131   // |origin_task_runner_|.
132   void OnTimerFired(int reset_sequence_number);
133 
134   // File descriptor associated with the alarm timer.
135   int alarm_fd_;
136 
137   // Task runner which initially started the timer.
138   scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
139 
140   // Callback that should be run when the timer fires.
141   base::Closure on_timer_fired_callback_;
142 
143   // Hook used by tests to be notified when the timer has fired and a task has
144   // been queued in the MessageLoop.
145   base::Closure on_timer_fired_callback_for_test_;
146 
147   // Manages watching file descriptors.
148   scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> fd_watcher_;
149 
150   // The sequence numbers of the last Reset() call handled respectively on
151   // |origin_task_runner_| and on the MessageLoopForIO used for watching the
152   // timer file descriptor.  Note that these can be the same MessageLoop.
153   // OnTimerFired() runs |on_timer_fired_callback_| only if the sequence number
154   // it receives from the MessageLoopForIO matches
155   // |origin_reset_sequence_number_|.
156   int origin_reset_sequence_number_;
157   int io_reset_sequence_number_;
158 
159   DISALLOW_COPY_AND_ASSIGN(Delegate);
160 };
161 
Delegate(base::Closure on_timer_fired_callback)162 AlarmTimer::Delegate::Delegate(base::Closure on_timer_fired_callback)
163     : alarm_fd_(timerfd_create(CLOCK_REALTIME_ALARM, 0)),
164       on_timer_fired_callback_(on_timer_fired_callback),
165       origin_reset_sequence_number_(0),
166       io_reset_sequence_number_(0) {
167   // The call to timerfd_create above may fail.  This is the only indication
168   // that CLOCK_REALTIME_ALARM is not supported on this system.
169   DPLOG_IF(INFO, (alarm_fd_ == -1))
170       << "CLOCK_REALTIME_ALARM not supported on this system";
171 }
172 
~Delegate()173 AlarmTimer::Delegate::~Delegate() {
174   if (alarm_fd_ != -1)
175     close(alarm_fd_);
176 }
177 
CanWakeFromSuspend()178 bool AlarmTimer::Delegate::CanWakeFromSuspend() {
179   return alarm_fd_ != -1;
180 }
181 
Reset(base::TimeDelta delay)182 void AlarmTimer::Delegate::Reset(base::TimeDelta delay) {
183   // Get a task runner for the current message loop.  When the timer fires, we
184   // will
185   // post tasks to this proxy to let the parent timer know.
186   origin_task_runner_ = base::ThreadTaskRunnerHandle::Get();
187 
188   // Increment the sequence number.  Used to invalidate any events that have
189   // been queued but not yet run since the last time Reset() was called.
190   origin_reset_sequence_number_++;
191 
192   // Calling timerfd_settime with a zero delay actually clears the timer so if
193   // the user has requested a zero delay timer, we need to handle it
194   // differently.  We queue the task here but we still go ahead and call
195   // timerfd_settime with the zero delay anyway to cancel any previous delay
196   // that might have been programmed.
197   if (delay <= base::TimeDelta::FromMicroseconds(0)) {
198     // The timerfd_settime documentation is vague on what happens when it is
199     // passed a negative delay.  We can sidestep the issue by ensuring that
200     // the delay is 0.
201     delay = base::TimeDelta::FromMicroseconds(0);
202     origin_task_runner_->PostTask(
203         FROM_HERE,
204         base::Bind(&Delegate::OnTimerFired, scoped_refptr<Delegate>(this),
205                    origin_reset_sequence_number_));
206   }
207 
208   // Run ResetImpl() on a MessageLoopForIO.
209   if (base::MessageLoopForIO::IsCurrent()) {
210     ResetImpl(delay, origin_reset_sequence_number_);
211   } else {
212     g_io_thread.Pointer()->task_runner()->PostTask(
213         FROM_HERE,
214         base::Bind(&Delegate::ResetImpl, scoped_refptr<Delegate>(this), delay,
215                    origin_reset_sequence_number_));
216   }
217 }
218 
Stop()219 void AlarmTimer::Delegate::Stop() {
220   // Stop the RTC from a MessageLoopForIO.
221   if (!base::MessageLoopForIO::IsCurrent()) {
222     g_io_thread.Pointer()->task_runner()->PostTask(
223         FROM_HERE, base::Bind(&Delegate::Stop, scoped_refptr<Delegate>(this)));
224     return;
225   }
226 
227   // Stop watching for events.
228   fd_watcher_.reset();
229 
230   // Now clear the timer.
231   DCHECK_NE(alarm_fd_, -1);
232   itimerspec blank_time;
233   memset(&blank_time, 0, sizeof(blank_time));
234   if (timerfd_settime(alarm_fd_, 0, &blank_time, NULL) < 0)
235     PLOG(ERROR) << "Unable to clear alarm time.  Timer may still fire.";
236 }
237 
OnFileCanReadWithoutBlocking(int fd)238 void AlarmTimer::Delegate::OnFileCanReadWithoutBlocking(int fd) {
239   DCHECK_EQ(alarm_fd_, fd);
240 
241   // Read from the fd to ack the event.
242   char val[sizeof(uint64_t)];
243   if (!base::ReadFromFD(alarm_fd_, val, sizeof(uint64_t)))
244     PLOG(DFATAL) << "Unable to read from timer file descriptor.";
245 
246   // Make sure that the parent timer is informed on the proper message loop.
247   if (origin_task_runner_->RunsTasksOnCurrentThread()) {
248     OnTimerFired(io_reset_sequence_number_);
249   } else {
250     origin_task_runner_->PostTask(
251         FROM_HERE,
252         base::Bind(&Delegate::OnTimerFired, scoped_refptr<Delegate>(this),
253                    io_reset_sequence_number_));
254   }
255 }
256 
OnFileCanWriteWithoutBlocking(int)257 void AlarmTimer::Delegate::OnFileCanWriteWithoutBlocking(int /* fd */) {
258   NOTREACHED();
259 }
260 
SetTimerFiredCallbackForTest(base::Closure test_callback)261 void AlarmTimer::Delegate::SetTimerFiredCallbackForTest(
262     base::Closure test_callback) {
263   on_timer_fired_callback_for_test_ = test_callback;
264 }
265 
ResetImpl(base::TimeDelta delay,int reset_sequence_number)266 void AlarmTimer::Delegate::ResetImpl(base::TimeDelta delay,
267                                      int reset_sequence_number) {
268   DCHECK(base::MessageLoopForIO::IsCurrent());
269   DCHECK_NE(alarm_fd_, -1);
270 
271   // Store the sequence number in the IO thread variable.  When the timer
272   // fires, we will bind this value to the OnTimerFired callback to ensure
273   // that we do the right thing if the timer gets reset.
274   io_reset_sequence_number_ = reset_sequence_number;
275 
276   // If we were already watching the fd, this will stop watching it.
277   fd_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
278 
279   // Start watching the fd to see when the timer fires.
280   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
281           alarm_fd_, false, base::MessageLoopForIO::WATCH_READ,
282           fd_watcher_.get(), this)) {
283     LOG(ERROR) << "Error while attempting to watch file descriptor for RTC "
284                << "alarm.  Timer will not fire.";
285   }
286 
287   // Actually set the timer.  This will also clear the pre-existing timer, if
288   // any.
289   itimerspec alarm_time;
290   memset(&alarm_time, 0, sizeof(alarm_time));
291   alarm_time.it_value.tv_sec = delay.InSeconds();
292   alarm_time.it_value.tv_nsec =
293       (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) *
294       base::Time::kNanosecondsPerMicrosecond;
295   if (timerfd_settime(alarm_fd_, 0, &alarm_time, NULL) < 0)
296     PLOG(ERROR) << "Error while setting alarm time.  Timer will not fire";
297 }
298 
OnTimerFired(int reset_sequence_number)299 void AlarmTimer::Delegate::OnTimerFired(int reset_sequence_number) {
300   DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
301 
302   // If a test wants to be notified when this function is about to run, then
303   // re-queue this task in the MessageLoop and run the test's callback.
304   if (!on_timer_fired_callback_for_test_.is_null()) {
305     origin_task_runner_->PostTask(
306         FROM_HERE,
307         base::Bind(&Delegate::OnTimerFired, scoped_refptr<Delegate>(this),
308                    reset_sequence_number));
309 
310     on_timer_fired_callback_for_test_.Run();
311     on_timer_fired_callback_for_test_.Reset();
312     return;
313   }
314 
315   // Check to make sure that the timer was not reset in the time between when
316   // this task was queued to run and now.  If it was reset, then don't do
317   // anything.
318   if (reset_sequence_number != origin_reset_sequence_number_)
319     return;
320 
321   on_timer_fired_callback_.Run();
322 }
323 
AlarmTimer(bool retain_user_task,bool is_repeating)324 AlarmTimer::AlarmTimer(bool retain_user_task, bool is_repeating)
325     : base::Timer(retain_user_task, is_repeating),
326       can_wake_from_suspend_(false),
327       origin_message_loop_(NULL),
328       weak_factory_(this) {
329   Init();
330 }
331 
AlarmTimer(const tracked_objects::Location & posted_from,base::TimeDelta delay,const base::Closure & user_task,bool is_repeating)332 AlarmTimer::AlarmTimer(const tracked_objects::Location& posted_from,
333                        base::TimeDelta delay,
334                        const base::Closure& user_task,
335                        bool is_repeating)
336     : base::Timer(posted_from, delay, user_task, is_repeating),
337       can_wake_from_suspend_(false),
338       origin_message_loop_(NULL),
339       weak_factory_(this) {
340   Init();
341 }
342 
~AlarmTimer()343 AlarmTimer::~AlarmTimer() {
344   Stop();
345 }
346 
SetTimerFiredCallbackForTest(base::Closure test_callback)347 void AlarmTimer::SetTimerFiredCallbackForTest(base::Closure test_callback) {
348   delegate_->SetTimerFiredCallbackForTest(test_callback);
349 }
350 
Init()351 void AlarmTimer::Init() {
352   delegate_ = make_scoped_refptr(new AlarmTimer::Delegate(
353       base::Bind(&AlarmTimer::OnTimerFired, weak_factory_.GetWeakPtr())));
354   can_wake_from_suspend_ = delegate_->CanWakeFromSuspend();
355 }
356 
Stop()357 void AlarmTimer::Stop() {
358   if (!base::Timer::is_running())
359     return;
360 
361   if (!can_wake_from_suspend_) {
362     base::Timer::Stop();
363     return;
364   }
365 
366   // Clear the running flag, stop the delegate, and delete the pending task.
367   base::Timer::set_is_running(false);
368   delegate_->Stop();
369   pending_task_.reset();
370 
371   // Stop watching |origin_message_loop_|.
372   origin_message_loop_ = NULL;
373   message_loop_observer_.reset();
374 
375   if (!base::Timer::retain_user_task())
376     base::Timer::set_user_task(base::Closure());
377 }
378 
Reset()379 void AlarmTimer::Reset() {
380   if (!can_wake_from_suspend_) {
381     base::Timer::Reset();
382     return;
383   }
384 
385   DCHECK(!base::Timer::user_task().is_null());
386   DCHECK(!origin_message_loop_ ||
387          origin_message_loop_->task_runner()->RunsTasksOnCurrentThread());
388 
389   // Make sure that the timer will stop if the underlying message loop is
390   // destroyed.
391   if (!origin_message_loop_) {
392     origin_message_loop_ = base::MessageLoop::current();
393     message_loop_observer_.reset(new MessageLoopObserver(
394         origin_message_loop_,
395         base::Bind(&AlarmTimer::WillDestroyCurrentMessageLoop,
396                    weak_factory_.GetWeakPtr())));
397   }
398 
399   // Set up the pending task.
400   if (base::Timer::GetCurrentDelay() > base::TimeDelta::FromMicroseconds(0)) {
401     base::Timer::set_desired_run_time(base::TimeTicks::Now() +
402                                       base::Timer::GetCurrentDelay());
403     pending_task_.reset(new base::PendingTask(
404         base::Timer::posted_from(), base::Timer::user_task(),
405         base::Timer::desired_run_time(), true /* nestable */));
406   } else {
407     base::Timer::set_desired_run_time(base::TimeTicks());
408     pending_task_.reset(new base::PendingTask(base::Timer::posted_from(),
409                                               base::Timer::user_task()));
410   }
411   base::MessageLoop::current()->task_annotator()->DidQueueTask(
412       "AlarmTimer::Reset", *pending_task_);
413 
414   // Now start up the timer.
415   delegate_->Reset(base::Timer::GetCurrentDelay());
416   base::Timer::set_is_running(true);
417 }
418 
WillDestroyCurrentMessageLoop()419 void AlarmTimer::WillDestroyCurrentMessageLoop() {
420   Stop();
421 }
422 
OnTimerFired()423 void AlarmTimer::OnTimerFired() {
424   if (!base::Timer::IsRunning())
425     return;
426 
427   DCHECK(pending_task_.get());
428 
429   // Take ownership of the pending user task, which is going to be cleared by
430   // the Stop() or Reset() functions below.
431   scoped_ptr<base::PendingTask> pending_user_task(std::move(pending_task_));
432 
433   // Re-schedule or stop the timer as requested.
434   if (base::Timer::is_repeating())
435     Reset();
436   else
437     Stop();
438 
439   TRACE_TASK_EXECUTION("AlarmTimer::OnTimerFired", *pending_user_task);
440 
441   // Now run the user task.
442   base::MessageLoop::current()->task_annotator()->RunTask("AlarmTimer::Reset",
443                                                           *pending_user_task);
444 }
445 
OneShotAlarmTimer()446 OneShotAlarmTimer::OneShotAlarmTimer() : AlarmTimer(false, false) {
447 }
448 
~OneShotAlarmTimer()449 OneShotAlarmTimer::~OneShotAlarmTimer() {
450 }
451 
RepeatingAlarmTimer()452 RepeatingAlarmTimer::RepeatingAlarmTimer() : AlarmTimer(true, true) {
453 }
454 
RepeatingAlarmTimer(const tracked_objects::Location & posted_from,base::TimeDelta delay,const base::Closure & user_task)455 RepeatingAlarmTimer::RepeatingAlarmTimer(
456     const tracked_objects::Location& posted_from,
457     base::TimeDelta delay,
458     const base::Closure& user_task)
459     : AlarmTimer(posted_from, delay, user_task, true) {
460 }
461 
~RepeatingAlarmTimer()462 RepeatingAlarmTimer::~RepeatingAlarmTimer() {
463 }
464 
SimpleAlarmTimer()465 SimpleAlarmTimer::SimpleAlarmTimer() : AlarmTimer(true, false) {
466 }
467 
SimpleAlarmTimer(const tracked_objects::Location & posted_from,base::TimeDelta delay,const base::Closure & user_task)468 SimpleAlarmTimer::SimpleAlarmTimer(const tracked_objects::Location& posted_from,
469                                    base::TimeDelta delay,
470                                    const base::Closure& user_task)
471     : AlarmTimer(posted_from, delay, user_task, false) {
472 }
473 
~SimpleAlarmTimer()474 SimpleAlarmTimer::~SimpleAlarmTimer() {
475 }
476 
477 }  // namespace timers
478