1// Copyright (c) 2012 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#ifndef CONTENT_GPU_GPU_WATCHDOG_THREAD_H_
6#define CONTENT_GPU_GPU_WATCHDOG_THREAD_H_
7
8#include "base/memory/ref_counted.h"
9#include "base/memory/weak_ptr.h"
10#include "base/message_loop/message_loop.h"
11#include "base/power_monitor/power_observer.h"
12#include "base/threading/thread.h"
13#include "base/time/time.h"
14#include "content/common/gpu/gpu_watchdog.h"
15
16namespace content {
17
18// A thread that intermitently sends tasks to a group of watched message loops
19// and deliberately crashes if one of them does not respond after a timeout.
20class GpuWatchdogThread : public base::Thread,
21                          public GpuWatchdog,
22                          public base::PowerObserver,
23                          public base::RefCountedThreadSafe<GpuWatchdogThread> {
24 public:
25  explicit GpuWatchdogThread(int timeout);
26
27  // Accessible on watched thread but only modified by watchdog thread.
28  bool armed() const { return armed_; }
29  void PostAcknowledge();
30
31  // Implement GpuWatchdog.
32  virtual void CheckArmed() OVERRIDE;
33
34  // Must be called after a PowerMonitor has been created. Can be called from
35  // any thread.
36  void AddPowerObserver();
37
38 protected:
39  virtual void Init() OVERRIDE;
40  virtual void CleanUp() OVERRIDE;
41
42 private:
43  friend class base::RefCountedThreadSafe<GpuWatchdogThread>;
44
45  // An object of this type intercepts the reception and completion of all tasks
46  // on the watched thread and checks whether the watchdog is armed.
47  class GpuWatchdogTaskObserver : public base::MessageLoop::TaskObserver {
48   public:
49    explicit GpuWatchdogTaskObserver(GpuWatchdogThread* watchdog);
50    virtual ~GpuWatchdogTaskObserver();
51
52    // Implements MessageLoop::TaskObserver.
53    virtual void WillProcessTask(
54        const base::PendingTask& pending_task) OVERRIDE;
55    virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE;
56
57   private:
58    GpuWatchdogThread* watchdog_;
59  };
60
61  virtual ~GpuWatchdogThread();
62
63  void OnAcknowledge();
64  void OnCheck(bool after_suspend);
65  void DeliberatelyTerminateToRecoverFromHang();
66
67  void OnAddPowerObserver();
68
69  // Implement PowerObserver.
70  virtual void OnSuspend() OVERRIDE;
71  virtual void OnResume() OVERRIDE;
72
73#if defined(OS_WIN)
74  base::TimeDelta GetWatchedThreadTime();
75#endif
76
77  base::MessageLoop* watched_message_loop_;
78  base::TimeDelta timeout_;
79  volatile bool armed_;
80  GpuWatchdogTaskObserver task_observer_;
81
82#if defined(OS_WIN)
83  void* watched_thread_handle_;
84  base::TimeDelta arm_cpu_time_;
85#endif
86
87  // Time after which it's assumed that the computer has been suspended since
88  // the task was posted.
89  base::Time suspension_timeout_;
90
91  bool suspended_;
92
93#if defined(OS_CHROMEOS)
94  FILE* tty_file_;
95#endif
96
97  base::WeakPtrFactory<GpuWatchdogThread> weak_factory_;
98
99  DISALLOW_COPY_AND_ASSIGN(GpuWatchdogThread);
100};
101
102}  // namespace content
103
104#endif  // CONTENT_GPU_GPU_WATCHDOG_THREAD_H_
105