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