OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/gpu/gpu_child_thread.h" | 5 #include "content/gpu/gpu_child_thread.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 29 matching lines...) Expand all Loading... | |
40 } else { | 40 } else { |
41 ChildThread::current()->Send(new GpuHostMsg_OnLogMessage(severity, header, | 41 ChildThread::current()->Send(new GpuHostMsg_OnLogMessage(severity, header, |
42 message)); | 42 message)); |
43 } | 43 } |
44 | 44 |
45 return false; | 45 return false; |
46 } | 46 } |
47 | 47 |
48 } // namespace | 48 } // namespace |
49 | 49 |
50 GpuChildThread::GpuChildThread(bool dead_on_arrival, | 50 GpuChildThread::GpuChildThread() { |
51 const content::GPUInfo& gpu_info) | |
52 : dead_on_arrival_(dead_on_arrival), | |
53 gpu_info_(gpu_info) { | |
54 #if defined(OS_WIN) | 51 #if defined(OS_WIN) |
55 target_services_ = NULL; | 52 target_services_ = NULL; |
56 collecting_dx_diagnostics_ = false; | 53 collecting_dx_diagnostics_ = false; |
57 #endif | 54 #endif |
58 } | 55 } |
59 | 56 |
60 GpuChildThread::GpuChildThread(const std::string& channel_id) | 57 GpuChildThread::GpuChildThread(const std::string& channel_id) |
61 : ChildThread(channel_id), | 58 : ChildThread(channel_id) { |
62 dead_on_arrival_(false) { | |
63 #if defined(OS_WIN) | 59 #if defined(OS_WIN) |
64 target_services_ = NULL; | 60 target_services_ = NULL; |
65 collecting_dx_diagnostics_ = false; | 61 collecting_dx_diagnostics_ = false; |
66 #endif | 62 #endif |
67 if (!gpu_info_collector::CollectGraphicsInfo(&gpu_info_)) { | |
68 LOG(INFO) << "gpu_info_collector::CollectGraphicsInfo failed"; | |
69 } | |
70 } | 63 } |
71 | 64 |
72 | |
73 GpuChildThread::~GpuChildThread() { | 65 GpuChildThread::~GpuChildThread() { |
74 logging::SetLogMessageHandler(NULL); | 66 logging::SetLogMessageHandler(NULL); |
75 } | 67 } |
76 | 68 |
77 void GpuChildThread::Init(const base::Time& process_start_time) { | 69 void GpuChildThread::Init(const base::Time& process_start_time) { |
78 process_start_time_ = process_start_time; | 70 process_start_time_ = process_start_time; |
79 } | 71 } |
80 | 72 |
81 bool GpuChildThread::Send(IPC::Message* msg) { | 73 bool GpuChildThread::Send(IPC::Message* msg) { |
82 // The GPU process must never send a synchronous IPC message to the browser | 74 // The GPU process must never send a synchronous IPC message to the browser |
(...skipping 16 matching lines...) Expand all Loading... | |
99 IPC_END_MESSAGE_MAP_EX() | 91 IPC_END_MESSAGE_MAP_EX() |
100 | 92 |
101 if (handled) | 93 if (handled) |
102 return true; | 94 return true; |
103 | 95 |
104 return gpu_channel_manager_.get() && | 96 return gpu_channel_manager_.get() && |
105 gpu_channel_manager_->OnMessageReceived(msg); | 97 gpu_channel_manager_->OnMessageReceived(msg); |
106 } | 98 } |
107 | 99 |
108 void GpuChildThread::OnInitialize() { | 100 void GpuChildThread::OnInitialize() { |
109 if (dead_on_arrival_) { | |
110 LOG(INFO) << "Exiting GPU process due to errors during initialization"; | |
111 MessageLoop::current()->Quit(); | |
112 return; | |
113 } | |
114 | |
115 // We don't need to pipe log messages if we are running the GPU thread in | 101 // We don't need to pipe log messages if we are running the GPU thread in |
116 // the browser process. | 102 // the browser process. |
117 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && | 103 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && |
118 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) | 104 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) |
119 logging::SetLogMessageHandler(GpuProcessLogMessageHandler); | 105 logging::SetLogMessageHandler(GpuProcessLogMessageHandler); |
120 | 106 |
121 // Record initialization only after collecting the GPU info because that can | 107 // Record initialization only after collecting the GPU info because that can |
122 // take a significant amount of time. | 108 // take a significant amount of time. |
123 gpu_info_.initialization_time = base::Time::Now() - process_start_time_; | 109 gpu_info_.initialization_time = base::Time::Now() - process_start_time_; |
124 | 110 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 | 142 |
157 // Defer creation of the render thread. This is to prevent it from handling | 143 // Defer creation of the render thread. This is to prevent it from handling |
158 // IPC messages before the sandbox has been enabled and all other necessary | 144 // IPC messages before the sandbox has been enabled and all other necessary |
159 // initialization has succeeded. | 145 // initialization has succeeded. |
160 gpu_channel_manager_.reset(new GpuChannelManager( | 146 gpu_channel_manager_.reset(new GpuChannelManager( |
161 this, | 147 this, |
162 watchdog_thread_, | 148 watchdog_thread_, |
163 ChildProcess::current()->io_message_loop_proxy(), | 149 ChildProcess::current()->io_message_loop_proxy(), |
164 ChildProcess::current()->GetShutDownEvent())); | 150 ChildProcess::current()->GetShutDownEvent())); |
165 | 151 |
166 // Ensure the browser process receives the GPU info before a reply to any | 152 #if defined(OS_LINUX) |
167 // subsequent IPC it might send. | 153 OnCollectGraphicsInfo(); |
168 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_)); | 154 #endif |
169 } | 155 } |
170 | 156 |
171 void GpuChildThread::StopWatchdog() { | 157 void GpuChildThread::StopWatchdog() { |
172 if (watchdog_thread_.get()) { | 158 if (watchdog_thread_.get()) { |
173 watchdog_thread_->Stop(); | 159 watchdog_thread_->Stop(); |
174 } | 160 } |
175 } | 161 } |
176 | 162 |
177 void GpuChildThread::OnCollectGraphicsInfo() { | 163 void GpuChildThread::OnCollectGraphicsInfo() { |
164 DCHECK(CommandLine::ForCurrentProcess()->HasSwitch( | |
165 switches::kDisableGpuSandbox)); | |
166 if (!gpu_info_.finalized) { | |
167 // Load and initialize the GL implementation and locate the GL entry points. | |
168 if (gfx::GLSurface::InitializeOneOff()) { | |
apatrick_chromium
2012/05/16 18:02:35
At this point, the GPU sandbox might have been tur
| |
169 // Collect information about the GPU. | |
170 if (!gpu_info_collector::CollectGraphicsInfo(&gpu_info_)) { | |
apatrick_chromium
2012/05/16 18:02:35
.. ditto this.
| |
171 VLOG(1) << "gpu_info_collector::CollectGraphicsInfo failed"; | |
172 } | |
173 | |
174 #if defined(OS_LINUX) | |
175 if (gpu_info_.gpu.vendor_id == 0x10de && // NVIDIA | |
176 gpu_info_.driver_vendor == "NVIDIA") { | |
177 base::ThreadRestrictions::AssertIOAllowed(); | |
178 if (access("/dev/nvidiactl", R_OK) != 0) { | |
apatrick_chromium
2012/05/16 18:02:35
... and I suspect this might fail on Linux once th
| |
179 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; | |
180 gpu_info_.gpu_accessible = false; | |
181 } | |
182 } | |
183 #endif | |
184 } else { | |
185 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; | |
186 gpu_info_.gpu_accessible = false; | |
187 } | |
188 #if !defined(OS_WIN) | |
189 gpu_info_.finalized = true; | |
190 #endif | |
191 } | |
178 #if defined(OS_WIN) | 192 #if defined(OS_WIN) |
179 if (!gpu_info_.finalized && !collecting_dx_diagnostics_) { | 193 if (!gpu_info_.finalized && !collecting_dx_diagnostics_) { |
180 // Prevent concurrent collection of DirectX diagnostics. | 194 // Prevent concurrent collection of DirectX diagnostics. |
181 collecting_dx_diagnostics_ = true; | 195 collecting_dx_diagnostics_ = true; |
182 | 196 |
183 if (CommandLine::ForCurrentProcess()->HasSwitch( | 197 // Asynchronously collect the DirectX diagnostics because this can take a |
184 switches::kDisableGpuSandbox)) { | 198 // couple of seconds. |
185 // Asynchronously collect the DirectX diagnostics because this can take a | 199 if (!base::WorkerPool::PostTask( |
186 // couple of seconds. | 200 FROM_HERE, base::Bind(&GpuChildThread::CollectDxDiagnostics, this), |
187 if (!base::WorkerPool::PostTask( | 201 true)) { |
188 FROM_HERE, base::Bind(&GpuChildThread::CollectDxDiagnostics, this), | 202 // Flag GPU info as complete if the DirectX diagnostics cannot be |
189 true)) { | 203 // collected. |
190 // Flag GPU info as complete if the DirectX diagnostics cannot be | 204 collecting_dx_diagnostics_ = false; |
191 // collected. | 205 gpu_info_.finalized = true; |
192 collecting_dx_diagnostics_ = false; | |
193 gpu_info_.finalized = true; | |
194 } else { | |
195 // Do not send response if we are still completing the GPUInfo struct | |
196 return; | |
197 } | |
198 } | 206 } |
199 } | 207 } |
200 #endif | 208 #endif |
201 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_)); | 209 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_)); |
202 } | 210 } |
203 | 211 |
204 void GpuChildThread::OnClean() { | 212 void GpuChildThread::OnClean() { |
205 LOG(INFO) << "GPU: Removing all contexts"; | 213 VLOG(1) << "GPU: Removing all contexts"; |
206 if (gpu_channel_manager_.get()) | 214 if (gpu_channel_manager_.get()) |
207 gpu_channel_manager_->LoseAllContexts(); | 215 gpu_channel_manager_->LoseAllContexts(); |
208 } | 216 } |
209 | 217 |
210 void GpuChildThread::OnCrash() { | 218 void GpuChildThread::OnCrash() { |
211 LOG(INFO) << "GPU: Simulating GPU crash"; | 219 VLOG(1) << "GPU: Simulating GPU crash"; |
212 // Good bye, cruel world. | 220 // Good bye, cruel world. |
213 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL; | 221 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL; |
214 *it_s_the_end_of_the_world_as_we_know_it = 0xdead; | 222 *it_s_the_end_of_the_world_as_we_know_it = 0xdead; |
215 } | 223 } |
216 | 224 |
217 void GpuChildThread::OnHang() { | 225 void GpuChildThread::OnHang() { |
218 LOG(INFO) << "GPU: Simulating GPU hang"; | 226 VLOG(1) << "GPU: Simulating GPU hang"; |
219 for (;;) { | 227 for (;;) { |
220 // Do not sleep here. The GPU watchdog timer tracks the amount of user | 228 // Do not sleep here. The GPU watchdog timer tracks the amount of user |
221 // time this thread is using and it doesn't use much while calling Sleep. | 229 // time this thread is using and it doesn't use much while calling Sleep. |
222 } | 230 } |
223 } | 231 } |
224 | 232 |
225 #if defined(OS_WIN) | 233 #if defined(OS_WIN) |
226 | 234 |
227 // Runs on a worker thread. The GPU process never terminates voluntarily so | 235 // Runs on a worker thread. The GPU process never terminates voluntarily so |
228 // it is safe to assume that its message loop is valid. | 236 // it is safe to assume that its message loop is valid. |
229 void GpuChildThread::CollectDxDiagnostics(GpuChildThread* thread) { | 237 void GpuChildThread::CollectDxDiagnostics(GpuChildThread* thread) { |
230 content::DxDiagNode node; | 238 content::DxDiagNode node; |
231 gpu_info_collector::GetDxDiagnostics(&node); | 239 gpu_info_collector::GetDxDiagnostics(&node); |
232 | 240 |
233 thread->message_loop()->PostTask( | 241 thread->message_loop()->PostTask( |
234 FROM_HERE, base::Bind(&GpuChildThread::SetDxDiagnostics, thread, node)); | 242 FROM_HERE, base::Bind(&GpuChildThread::SetDxDiagnostics, thread, node)); |
235 } | 243 } |
236 | 244 |
237 // Runs on the main thread. | 245 // Runs on the main thread. |
238 void GpuChildThread::SetDxDiagnostics(GpuChildThread* thread, | 246 void GpuChildThread::SetDxDiagnostics(GpuChildThread* thread, |
239 const content::DxDiagNode& node) { | 247 const content::DxDiagNode& node) { |
240 thread->gpu_info_.dx_diagnostics = node; | 248 thread->gpu_info_.dx_diagnostics = node; |
241 thread->gpu_info_.finalized = true; | 249 thread->gpu_info_.finalized = true; |
242 thread->collecting_dx_diagnostics_ = false; | 250 thread->collecting_dx_diagnostics_ = false; |
243 thread->Send(new GpuHostMsg_GraphicsInfoCollected(thread->gpu_info_)); | 251 thread->Send(new GpuHostMsg_GraphicsInfoCollected(thread->gpu_info_)); |
244 } | 252 } |
245 | 253 |
246 #endif | 254 #endif |
OLD | NEW |