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
23namespace timers {
24namespace {
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.
29class RtcAlarmIOThread : public base::Thread {
30 public:
31  RtcAlarmIOThread() : Thread("RTC Alarm IO Thread") {
32    CHECK(
33        StartWithOptions(base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
34  }
35  ~RtcAlarmIOThread() override { Stop(); }
36};
37
38base::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.
44class 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.
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
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.
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.
93class 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
162AlarmTimer::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
173AlarmTimer::Delegate::~Delegate() {
174  if (alarm_fd_ != -1)
175    close(alarm_fd_);
176}
177
178bool AlarmTimer::Delegate::CanWakeFromSuspend() {
179  return alarm_fd_ != -1;
180}
181
182void 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
219void 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
238void 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
257void AlarmTimer::Delegate::OnFileCanWriteWithoutBlocking(int /* fd */) {
258  NOTREACHED();
259}
260
261void AlarmTimer::Delegate::SetTimerFiredCallbackForTest(
262    base::Closure test_callback) {
263  on_timer_fired_callback_for_test_ = test_callback;
264}
265
266void 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
299void 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
324AlarmTimer::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
332AlarmTimer::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
343AlarmTimer::~AlarmTimer() {
344  Stop();
345}
346
347void AlarmTimer::SetTimerFiredCallbackForTest(base::Closure test_callback) {
348  delegate_->SetTimerFiredCallbackForTest(test_callback);
349}
350
351void 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
357void 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
379void 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
419void AlarmTimer::WillDestroyCurrentMessageLoop() {
420  Stop();
421}
422
423void 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
446OneShotAlarmTimer::OneShotAlarmTimer() : AlarmTimer(false, false) {
447}
448
449OneShotAlarmTimer::~OneShotAlarmTimer() {
450}
451
452RepeatingAlarmTimer::RepeatingAlarmTimer() : AlarmTimer(true, true) {
453}
454
455RepeatingAlarmTimer::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
462RepeatingAlarmTimer::~RepeatingAlarmTimer() {
463}
464
465SimpleAlarmTimer::SimpleAlarmTimer() : AlarmTimer(true, false) {
466}
467
468SimpleAlarmTimer::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
474SimpleAlarmTimer::~SimpleAlarmTimer() {
475}
476
477}  // namespace timers
478