blob: b6403600631c97100c7356265b88ed32d9d7716b [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2012 The Chromium Authors
[email protected]c0fc0942010-01-13 00:55:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi66a07722015-12-25 23:38:125#include <stddef.h>
[email protected]e09cee42010-11-09 01:50:086#include <stdlib.h>
7
mostynb6682b1c42016-04-19 10:17:308#include <memory>
Avi Drissman9a3ed4e2022-01-26 14:15:379#include <tuple>
dchengf26eed32016-01-13 10:58:1410#include <utility>
11
Arthur Sonzognia570236352022-12-19 13:18:5412#include "base/allocator/partition_alloc_support.h"
Joe Mason94bebf12022-06-03 15:03:5313#include "base/check.h"
Gabriel Charettef3851332022-04-28 23:39:1814#include "base/command_line.h"
Sunny Sachanandani5cd10e962019-06-13 22:55:3215#include "base/feature_list.h"
Zhuang Xue24dfc32025-05-26 02:45:0516#include "base/files/scoped_file.h"
Avi Drissmanadac21992023-01-11 23:46:3917#include "base/functional/bind.h"
Keishi Hattori0e45c022021-11-27 09:25:5218#include "base/memory/raw_ptr.h"
Carlos Caballerodd8bf7b042019-07-30 14:14:1519#include "base/message_loop/message_pump_type.h"
asvitkine8d51e9d2016-09-02 23:55:4320#include "base/metrics/histogram_macros.h"
Jeff Chenfce90f32022-01-31 19:49:3421#include "base/numerics/clamped_math.h"
Aman Verma0bf8c112022-11-15 13:01:2422#include "base/process/current_process.h"
Jeff Chenfce90f32022-01-31 19:49:3423#include "base/process/process_metrics.h"
[email protected]2436a6b2012-04-13 21:08:5124#include "base/rand_util.h"
fdoraye716a902016-07-05 16:05:4925#include "base/run_loop.h"
[email protected]d0ea4782013-06-11 04:58:2426#include "base/strings/string_number_conversions.h"
Sebastien Marchand75a7cdf2018-11-13 23:47:0327#include "base/system/sys_info.h"
henrika3cee59b2024-05-03 16:20:5228#include "base/task/current_thread.h"
Alex Clarke636e7052019-05-30 10:49:3729#include "base/task/single_thread_task_executor.h"
Joe Mason94bebf12022-06-03 15:03:5330#include "base/task/thread_pool/thread_pool_instance.h"
[email protected]ce072a72010-12-31 20:02:1631#include "base/threading/platform_thread.h"
Kramer Gea805bb012025-04-30 07:08:5132#include "base/threading/thread.h"
Gabriel Charetted87f10f2022-03-31 00:44:2233#include "base/time/time.h"
stanisc61507092017-07-06 16:36:5834#include "base/timer/hi_res_timer_manager.h"
primiano50b7444c2015-01-28 04:17:0035#include "base/trace_event/trace_event.h"
[email protected]c0fc0942010-01-13 00:55:3736#include "build/build_config.h"
Zhuang Xue24dfc32025-05-26 02:45:0537#include "components/viz/service/gl/gpu_log_message_manager.h"
Sadrul Habib Chowdhury55fc2f02017-10-27 02:40:0638#include "components/viz/service/main/viz_main_impl.h"
Joe Mason94bebf12022-06-03 15:03:5339#include "content/child/child_process.h"
[email protected]91a2aea2013-07-08 23:14:3940#include "content/common/content_constants_internal.h"
John Abd-El-Malek884291c2017-08-09 06:43:4841#include "content/common/content_switches_internal.h"
Matthew Denton66b2fa52023-10-17 00:54:2242#include "content/common/features.h"
Khushala4e236f2018-06-01 03:00:4643#include "content/common/skia_utils.h"
[email protected]7a31f7c2011-03-21 23:22:0444#include "content/gpu/gpu_child_thread.h"
[email protected]c9e2cbbb2012-05-12 21:17:2745#include "content/public/common/content_client.h"
Shintaro Kawamura65a33062024-03-28 03:40:0846#include "content/public/common/content_features.h"
[email protected]c9e2cbbb2012-05-12 21:17:2747#include "content/public/common/content_switches.h"
48#include "content/public/common/main_function_params.h"
jbaumana19f1df2017-01-18 03:01:1749#include "content/public/common/result_codes.h"
Kramer Gea805bb012025-04-30 07:08:5150#include "content/public/common/zygote/zygote_buildflags.h"
Zhenyao Moc76e9032018-01-19 21:15:4651#include "content/public/gpu/content_gpu_client.h"
[email protected]40c19e722013-11-05 23:51:2452#include "gpu/command_buffer/service/gpu_switches.h"
sadruled395922016-09-07 17:32:5853#include "gpu/config/gpu_driver_bug_list.h"
Sunny Sachanandani5cd10e962019-06-13 22:55:3254#include "gpu/config/gpu_finch_features.h"
[email protected]d7b5cc72013-05-23 20:05:0055#include "gpu/config/gpu_info_collector.h"
Jonathan Backer16cc8fd2018-05-31 19:59:2256#include "gpu/config/gpu_preferences.h"
tfarina15525c42015-04-28 19:04:1657#include "gpu/config/gpu_switches.h"
[email protected]40c19e722013-11-05 23:51:2458#include "gpu/config/gpu_util.h"
markdittmerd88b8352016-04-08 15:28:4559#include "gpu/ipc/service/gpu_config.h"
sadrul454af332016-09-09 18:14:3260#include "gpu/ipc/service/gpu_init.h"
sadrul2fb7e152016-08-30 05:21:4561#include "gpu/ipc/service/gpu_watchdog_thread.h"
Scott Violeta35f9a42018-03-22 22:00:4462#include "media/gpu/buildflags.h"
Michael Thiessendd70b612024-08-17 18:25:2563#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
kylechar60e12ed2021-03-15 15:56:0364#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
Kramer Gea805bb012025-04-30 07:08:5165#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
Dale Curtis12cfe022020-02-21 01:18:4266#include "services/tracing/public/cpp/trace_startup.h"
Kramer Geb79116d2024-12-12 21:41:2067#include "services/tracing/public/cpp/trace_startup_config.h"
Tom Sepeza0950c62017-10-18 20:39:1468#include "third_party/angle/src/gpu_info_util/SystemInfo.h"
Maksim Sisov459eada2020-06-25 08:16:3169#include "ui/base/ui_base_features.h"
[email protected]c0939182014-05-24 00:09:1970#include "ui/events/platform/platform_event_source.h"
skyostilb354f882016-12-13 18:42:4571#include "ui/gfx/switches.h"
martina.kollarovaa34211d2015-06-25 11:49:0772#include "ui/gl/gl_context.h"
Scott Violet833ff162023-04-19 00:32:3173#include "ui/gl/gl_features.h"
[email protected]db6101db2012-10-25 15:20:0874#include "ui/gl/gl_implementation.h"
[email protected]c9e2cbbb2012-05-12 21:17:2775#include "ui/gl/gl_surface.h"
76#include "ui/gl/gl_switches.h"
[email protected]1bb06b02012-09-23 19:37:2477#include "ui/gl/gpu_switching_manager.h"
kylechar5b9dec12016-05-16 15:40:5778#include "ui/gl/init/gl_factory.h"
[email protected]c0fc0942010-01-13 00:55:3779
Xiaohan Wang62737b52022-01-15 18:09:0280#if BUILDFLAG(IS_WIN)
Benoit Lize7ee77d32021-03-04 17:26:1481#include <windows.h>
Takuto Ikutac8d6b16f2024-04-15 16:59:1982
83#include <dwmapi.h>
avi66a07722015-12-25 23:38:1284#endif
85
Xiaohan Wang62737b52022-01-15 18:09:0286#if BUILDFLAG(IS_ANDROID)
Benoit Lizeb6fa4ac2023-02-13 11:59:4387#include "base/android/meminfo_dump_provider.h"
Ben Scarlato5ece30c72025-05-09 22:13:2088#include "base/posix/eintr_wrapper.h"
primianob3fb6412015-10-14 16:03:5189#include "base/trace_event/memory_dump_manager.h"
primianoccb26c62016-06-01 21:50:0290#include "components/tracing/common/graphics_memory_dump_provider_android.h"
Ben Scarlato5ece30c72025-05-09 22:13:2091#include "sandbox/linux/services/thread_helpers.h" // nogncheck
92#include "sandbox/policy/features.h"
93#include "sandbox/policy/linux/landlock_gpu_policy_android.h"
94#include "sandbox/policy/sandbox_type.h"
primianob3fb6412015-10-14 16:03:5195#endif
96
Xiaohan Wang62737b52022-01-15 18:09:0297#if BUILDFLAG(IS_WIN)
[email protected]5f7e4512012-10-01 20:51:3798#include "base/win/scoped_com_initializer.h"
Bill Carrba4cbb972022-10-10 18:24:1199#include "base/win/win_util.h"
kylechar5b9dec12016-05-16 15:40:57100#include "base/win/windows_version.h"
Dale Curtis56f208fc2023-04-07 18:55:25101#include "media/base/win/mf_initializer.h"
Alex Gough76f652f2023-06-16 14:00:17102#include "sandbox/policy/win/sandbox_warmup.h"
[email protected]181491782012-07-18 00:59:15103#include "sandbox/win/src/sandbox.h"
[email protected]802a13a02010-12-02 01:48:37104#endif
105
Xiaohan Wang62737b52022-01-15 18:09:02106#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Matthew Denton66b2fa52023-10-17 00:54:22107#include "content/child/sandboxed_process_thread_type_handler.h"
Ken Rockot9c9d3da2023-11-28 22:58:32108#include "content/common/gpu_pre_sandbox_hook_linux.h"
Robert Sesek7d0b49b2020-07-08 18:31:27109#include "sandbox/policy/linux/sandbox_linux.h"
Alex Gougheb6a38f2021-10-22 01:55:13110#include "sandbox/policy/sandbox_type.h"
[email protected]2436a6b2012-04-13 21:08:51111#endif
112
Xiaohan Wang62737b52022-01-15 18:09:02113#if BUILDFLAG(IS_MAC)
Avi Drissman5d32f182023-08-16 15:26:39114#include "base/message_loop/message_pump_apple.h"
Kai Ninomiyae2c55582019-12-19 23:51:03115#include "components/metal_util/device_removal.h"
Greg Kerr3480aa82018-02-01 00:53:03116#include "sandbox/mac/seatbelt.h"
[email protected]826aab02014-05-14 02:58:59117#endif
118
Alexandre Courbotc13a5972017-07-23 03:48:48119#if BUILDFLAG(USE_VAAPI)
Miguel Casas42e955c2017-12-04 14:18:12120#include "media/gpu/vaapi/vaapi_wrapper.h"
hshi95837052015-05-12 15:39:51121#endif
122
[email protected]eb398192012-10-22 20:16:19123namespace content {
[email protected]ec4bda62013-06-14 15:51:03124
[email protected]6ec3a572012-08-17 02:09:51125namespace {
[email protected]ec4bda62013-06-14 15:51:03126
Xiaohan Wang62737b52022-01-15 18:09:02127#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Zhenyao Moe9187a862017-10-20 04:26:33128bool StartSandboxLinux(gpu::GpuWatchdogThread*,
129 const gpu::GPUInfo*,
130 const gpu::GpuPreferences&);
Ben Scarlato5ece30c72025-05-09 22:13:20131#elif BUILDFLAG(IS_ANDROID)
132bool StartSandboxAndroid(gpu::GpuWatchdogThread*);
Xiaohan Wang62737b52022-01-15 18:09:02133#elif BUILDFLAG(IS_WIN)
[email protected]663c4b32013-04-18 05:52:54134bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*);
135#endif
[email protected]ec4bda62013-06-14 15:51:03136
sadrul454af332016-09-09 18:14:32137class ContentSandboxHelper : public gpu::GpuSandboxHelper {
138 public:
139 ContentSandboxHelper() {}
Peter Boström828b9022021-09-21 02:28:43140
141 ContentSandboxHelper(const ContentSandboxHelper&) = delete;
142 ContentSandboxHelper& operator=(const ContentSandboxHelper&) = delete;
143
sadrul454af332016-09-09 18:14:32144 ~ContentSandboxHelper() override {}
145
Xiaohan Wang62737b52022-01-15 18:09:02146#if BUILDFLAG(IS_WIN)
sadrul454af332016-09-09 18:14:32147 void set_sandbox_info(const sandbox::SandboxInterfaceInfo* info) {
148 sandbox_info_ = info;
149 }
150#endif
151
sadrul454af332016-09-09 18:14:32152 private:
153 // SandboxHelper:
Ted Meyer6801a072020-10-28 03:25:02154 void PreSandboxStartup(const gpu::GpuPreferences& gpu_prefs) override {
Kramer Ge0de97b152025-06-05 16:28:55155 TRACE_EVENT("gpu,startup", "gpu_main::PreSandboxStartup");
sadrul454af332016-09-09 18:14:32156 // Warm up resources that don't need access to GPUInfo.
157 {
158 TRACE_EVENT0("gpu", "Warm up rand");
159 // Warm up the random subsystem, which needs to be done pre-sandbox on all
160 // platforms.
Alex Gough76f652f2023-06-16 14:00:17161#if BUILDFLAG(IS_WIN)
162 sandbox::policy::WarmupRandomnessInfrastructure();
163#else
Avi Drissman9a3ed4e2022-01-26 14:15:37164 std::ignore = base::RandUint64();
Alex Gough76f652f2023-06-16 14:00:17165#endif // BUILDFLAG(IS_WIN)
sadrul454af332016-09-09 18:14:32166 }
167
Alexandre Courbotc13a5972017-07-23 03:48:48168#if BUILDFLAG(USE_VAAPI)
Xiaohan Wang62737b52022-01-15 18:09:02169#if BUILDFLAG(IS_CHROMEOS)
sadrul454af332016-09-09 18:14:32170 media::VaapiWrapper::PreSandboxInitialization();
Pilar Molina Lopezfb5103b72021-02-26 23:35:52171#else // For Linux with VA-API support.
Ted Meyer6801a072020-10-28 03:25:02172 if (!gpu_prefs.disable_accelerated_video_decode)
Ted Meyer6f266fd2020-10-23 01:54:06173 media::VaapiWrapper::PreSandboxInitialization();
sadrul454af332016-09-09 18:14:32174#endif
Ted Meyer6f266fd2020-10-23 01:54:06175#endif // BUILDFLAG(USE_VAAPI)
Xiaohan Wang62737b52022-01-15 18:09:02176#if BUILDFLAG(IS_WIN)
Dale Curtis51f418c2023-06-02 16:31:57177 media::PreSandboxMediaFoundationInitialization();
sadrul454af332016-09-09 18:14:32178#endif
Eric Karle35050e2017-09-07 01:44:35179
180 // On Linux, reading system memory doesn't work through the GPU sandbox.
181 // This value is cached, so access it here to populate the cache.
182 base::SysInfo::AmountOfPhysicalMemory();
sadrul454af332016-09-09 18:14:32183 }
184
Satyajit Sahu82a76e02017-09-18 14:50:14185 bool EnsureSandboxInitialized(gpu::GpuWatchdogThread* watchdog_thread,
Zhenyao Moe9187a862017-10-20 04:26:33186 const gpu::GPUInfo* gpu_info,
187 const gpu::GpuPreferences& gpu_prefs) override {
Kramer Ge0de97b152025-06-05 16:28:55188 TRACE_EVENT("gpu,startup", "gpu_main::EnsureSandboxInitialized");
Xiaohan Wang62737b52022-01-15 18:09:02189#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Zhenyao Moe9187a862017-10-20 04:26:33190 return StartSandboxLinux(watchdog_thread, gpu_info, gpu_prefs);
Xiaohan Wang62737b52022-01-15 18:09:02191#elif BUILDFLAG(IS_WIN)
sadrul454af332016-09-09 18:14:32192 return StartSandboxWindows(sandbox_info_);
Xiaohan Wang62737b52022-01-15 18:09:02193#elif BUILDFLAG(IS_MAC)
Greg Kerr3480aa82018-02-01 00:53:03194 return sandbox::Seatbelt::IsSandboxed();
Ben Scarlato5ece30c72025-05-09 22:13:20195#elif BUILDFLAG(IS_ANDROID)
196 if (base::FeatureList::IsEnabled(
197 sandbox::policy::features::kAndroidGpuSandbox)) {
198 return StartSandboxAndroid(watchdog_thread);
199 }
200 return false;
sadrul454af332016-09-09 18:14:32201#else
202 return false;
203#endif
204 }
205
Xiaohan Wang62737b52022-01-15 18:09:02206#if BUILDFLAG(IS_WIN)
Keishi Hattori0e45c022021-11-27 09:25:52207 raw_ptr<const sandbox::SandboxInterfaceInfo> sandbox_info_ = nullptr;
sadrul454af332016-09-09 18:14:32208#endif
sadrul454af332016-09-09 18:14:32209};
210
kylechar476993472016-09-14 16:03:48211} // namespace
[email protected]ec4bda62013-06-14 15:51:03212
[email protected]c0fc0942010-01-13 00:55:37213// Main function for starting the Gpu process.
Gabriel Charettefbeeb1c2021-11-10 20:50:06214int GpuMain(MainFunctionParams parameters) {
Kramer Gea805bb012025-04-30 07:08:51215 TRACE_EVENT("gpu,startup", "GpuMain");
Kramer Geb79116d2024-12-12 21:41:20216
Aman Verma0bf8c112022-11-15 13:01:24217 base::CurrentProcess::GetInstance().SetProcessType(
218 base::CurrentProcessType::PROCESS_GPU);
[email protected]d13f35d2012-05-18 02:28:15219
Gabriel Charettefbeeb1c2021-11-10 20:50:06220 const base::CommandLine& command_line = *parameters.command_line;
Zhenyao Mo910beb82017-10-25 03:23:00221
222 gpu::GpuPreferences gpu_preferences;
223 if (command_line.HasSwitch(switches::kGpuPreferences)) {
224 std::string value =
225 command_line.GetSwitchValueASCII(switches::kGpuPreferences);
Jonathan Backer16cc8fd2018-05-31 19:59:22226 bool success = gpu_preferences.FromSwitchValue(value);
Zhenyao Mo910beb82017-10-25 03:23:00227 CHECK(success);
228 }
229
kylechar60e12ed2021-03-15 15:56:03230 // Disallow sending sync IPCs from the GPU process, in particular CrGpuMain
231 // and VizCompositorThreads. Incoming sync IPCs can be received out of order
232 // when waiting on response to an outgoing sync IPC. Both viz and gpu
233 // interfaces rely on receiving messages in order so this message reordering
234 // would break things.
235 mojo::SyncCallRestrictions::DisallowSyncCall();
236
Zhenyao Mo910beb82017-10-25 03:23:00237 if (gpu_preferences.gpu_startup_dialog)
John Abd-El-Malek884291c2017-08-09 06:43:48238 WaitForDebugger("Gpu");
[email protected]6b889fb2010-03-23 20:09:49239
Sean Maherf36d8122022-08-05 02:33:35240 base::TimeTicks start_time = base::TimeTicks::Now();
[email protected]ca23992b02013-06-13 17:25:19241
Xiaohan Wang62737b52022-01-15 18:09:02242#if BUILDFLAG(IS_WIN)
Bill Carrba4cbb972022-10-10 18:24:11243 base::win::EnableHighDPISupport();
Daniel Libby1700bbe82019-01-30 22:22:36244
[email protected]52819472013-11-24 22:49:55245 // Prevent Windows from displaying a modal dialog on failures like not being
246 // able to load a DLL.
Benoit Lize7ee77d32021-03-04 17:26:14247 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
248 SEM_NOOPENFILEERRORBOX);
Robert Liao98bb92d2017-06-15 22:20:39249
Chris Davis3360a372025-02-06 23:21:30250 // Disable high resolution timer throttling to prevent the OS from degrading
251 // performance.
252 base::win::SetProcessTimerThrottleState(
253 base::GetCurrentProcessHandle(), base::win::ProcessPowerState::kDisabled);
254
Robert Liao98bb92d2017-06-15 22:20:39255 // COM is used by some Windows Media Foundation calls made on this thread and
256 // must be MTA so we don't have to worry about pumping messages to handle
257 // COM callbacks.
258 base::win::ScopedCOMInitializer com_initializer(
259 base::win::ScopedCOMInitializer::kMTA);
Sunny Sachanandani35c727c2019-07-09 13:12:52260
Zhenyao Modca79a22024-07-16 01:11:59261 // A higher priority class is used for the GPU process so that it remains at
262 // a higher priority than renderer processes.
263 ::SetPriorityClass(::GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
[email protected]23f46562011-09-07 01:42:39264#endif
[email protected]ec4bda62013-06-14 15:51:03265
Dale Curtis1b6becebb2020-03-30 20:13:35266 // Installs a base::LogMessageHandlerFunction which ensures messages are sent
267 // to the GpuProcessHost once the GpuServiceImpl has started.
Zhuang Xue24dfc32025-05-26 02:45:05268 viz::GpuLogMessageManager::GetInstance()->InstallPreInitializeLogHandler();
[email protected]23f46562011-09-07 01:42:39269
ericrk1d9e17f2016-11-30 01:51:28270 // We are experiencing what appear to be memory-stomp issues in the GPU
Alex Clarkef7fb8a82019-06-06 15:41:53271 // process. These issues seem to be impacting the task executor and listeners
272 // registered to it. Create the task executor on the heap to guard against
ericrk1d9e17f2016-11-30 01:51:28273 // this.
274 // TODO(ericrk): Revisit this once we assess its impact on crbug.com/662802
275 // and crbug.com/609252.
Alex Clarke636e7052019-05-30 10:49:37276 std::unique_ptr<base::SingleThreadTaskExecutor> main_thread_task_executor;
skyostil82befc52016-12-19 13:48:59277 std::unique_ptr<ui::PlatformEventSource> event_source;
skyostilb354f882016-12-13 18:42:45278 if (command_line.HasSwitch(switches::kHeadless)) {
Maggie Chenb539c3b2024-10-01 20:08:37279#if BUILDFLAG(IS_MAC)
280 // CADisplayLink (Mac HW VSync) callback only works with NS_RUNLOOP.
281 main_thread_task_executor =
282 std::make_unique<base::SingleThreadTaskExecutor>(
283 base::MessagePumpType::NS_RUNLOOP);
284 main_thread_task_executor->SetWorkBatchSize(2);
285#else
Alex Clarke636e7052019-05-30 10:49:37286 main_thread_task_executor =
287 std::make_unique<base::SingleThreadTaskExecutor>(
Carlos Caballerodd8bf7b042019-07-30 14:14:15288 base::MessagePumpType::DEFAULT);
Maggie Chenb539c3b2024-10-01 20:08:37289#endif
skyostilb354f882016-12-13 18:42:45290 } else {
Xiaohan Wang62737b52022-01-15 18:09:02291#if BUILDFLAG(IS_WIN)
Robert Liao98bb92d2017-06-15 22:20:39292 // The GpuMain thread should not be pumping Windows messages because no UI
293 // is expected to run on this thread.
Alex Clarke636e7052019-05-30 10:49:37294 main_thread_task_executor =
295 std::make_unique<base::SingleThreadTaskExecutor>(
Carlos Caballerodd8bf7b042019-07-30 14:14:15296 base::MessagePumpType::DEFAULT);
kylechar2d463872022-11-02 16:14:30297#elif BUILDFLAG(IS_OZONE)
Alex Clarke636e7052019-05-30 10:49:37298 // The MessagePump type required depends on the Ozone platform selected at
tonikitoofb807b102017-02-08 19:52:03299 // runtime.
Maksim Sisov459eada2020-06-25 08:16:31300 if (!main_thread_task_executor) {
301 main_thread_task_executor =
302 std::make_unique<base::SingleThreadTaskExecutor>(
303 gpu_preferences.message_pump_type);
304 }
Xiaohan Wang62737b52022-01-15 18:09:02305#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
kylechar476993472016-09-14 16:03:48306#error "Unsupported Linux platform."
Xiaohan Wang62737b52022-01-15 18:09:02307#elif BUILDFLAG(IS_MAC)
Christopher Cameron1732f2b02017-11-17 10:56:50308 // Cross-process CoreAnimation requires a CFRunLoop to function at all, and
309 // requires a NSRunLoop to not starve under heavy load. See:
310 // https://crbug.com/312462#c51 and https://crbug.com/783298
Maggie Chenb539c3b2024-10-01 20:08:37311 // CADisplayLink (Mac HW VSync) callback only works with NS_RUNLOOP. DEFAULT
312 // type does not support NSObject.
Alex Clarke636e7052019-05-30 10:49:37313 main_thread_task_executor =
314 std::make_unique<base::SingleThreadTaskExecutor>(
Carlos Caballerodd8bf7b042019-07-30 14:14:15315 base::MessagePumpType::NS_RUNLOOP);
Etienne Pierre-doray2163f3012020-04-02 21:37:14316 // As part of the migration to DoWork(), this policy is required to keep
Etienne Pierre-doray9eb4f5a2020-01-15 16:29:24317 // previous behavior and avoid regressions.
Alison Gale59c007a2024-04-20 03:05:40318 // TODO(crbug.com/40668161): Consider updating the policy.
Etienne Pierre-doray9eb4f5a2020-01-15 16:29:24319 main_thread_task_executor->SetWorkBatchSize(2);
[email protected]826aab02014-05-14 02:58:59320#else
Alex Clarke636e7052019-05-30 10:49:37321 main_thread_task_executor =
322 std::make_unique<base::SingleThreadTaskExecutor>(
Carlos Caballerodd8bf7b042019-07-30 14:14:15323 base::MessagePumpType::DEFAULT);
[email protected]db6101db2012-10-25 15:20:08324#endif
skyostilb354f882016-12-13 18:42:45325 }
[email protected]db6101db2012-10-25 15:20:08326
[email protected]db6101db2012-10-25 15:20:08327 base::PlatformThread::SetName("CrGpuMain");
Michael Thiessendd70b612024-08-17 18:25:25328 mojo::InterfaceEndpointClient::SetThreadNameSuffixForMetrics("GpuMain");
[email protected]db6101db2012-10-25 15:20:08329
Shintaro Kawamura65a33062024-03-28 03:40:08330#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
331 // Thread type delegate of the process should be registered before
332 // thread type change below for the main thread and for thread pool in
333 // ChildProcess constructor.
334 // It also needs to be registered before the process has multiple threads,
335 // which may race with application of the sandbox. InitializeAndStartSandbox()
336 // sandboxes the process and starts threads so this has to happen first.
Nathan Memmott6ce8cb02024-12-13 18:16:51337 SandboxedProcessThreadTypeHandler::Create();
Shintaro Kawamura65a33062024-03-28 03:40:08338#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
339
Etienne Pierre-doray8439625b8b2024-08-21 16:42:37340 base::PlatformThread::SetCurrentThreadType(
341 base::ThreadType::kDisplayCritical);
revemane7acf842016-02-05 08:24:32342
Sadrul Habib Chowdhurydb9021e2017-10-03 03:07:57343 auto gpu_init = std::make_unique<gpu::GpuInit>();
sadrul454af332016-09-09 18:14:32344 ContentSandboxHelper sandbox_helper;
Xiaohan Wang62737b52022-01-15 18:09:02345#if BUILDFLAG(IS_WIN)
sadrul454af332016-09-09 18:14:32346 sandbox_helper.set_sandbox_info(parameters.sandbox_info);
[email protected]af7c5d92014-02-03 19:53:15347#endif
[email protected]af7c5d92014-02-03 19:53:15348
Sadrul Habib Chowdhurydb9021e2017-10-03 03:07:57349 gpu_init->set_sandbox_helper(&sandbox_helper);
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24350
Gabriel Charettec7e363c62020-06-24 17:39:35351 // Since GPU initialization calls into skia, it's important to initialize skia
Khushal1d055592018-07-28 02:00:39352 // before it.
Kramer Geb79116d2024-12-12 21:41:20353 {
Kramer Ge0de97b152025-06-05 16:28:55354 TRACE_EVENT("gpu,startup", "gpu_main::InitializeSkia");
Kramer Geb79116d2024-12-12 21:41:20355 InitializeSkia();
356 }
Khushal1d055592018-07-28 02:00:39357
Joe Mason94bebf12022-06-03 15:03:53358 // The ThreadPool must have been created before invoking |gpu_init| as it
359 // needs the ThreadPool (in angle::InitializePlatform()). Do not start it
360 // until after the sandbox is initialized however to avoid creating threads
361 // outside the sandbox.
362 DCHECK(base::ThreadPoolInstance::Get());
Gabriel Charettec7e363c62020-06-24 17:39:35363
sadrul454af332016-09-09 18:14:32364 // Gpu initialization may fail for various reasons, in which case we will need
365 // to tear down this process. However, we can not do so safely until the IPC
366 // channel is set up, because the detection of early return of a child process
367 // is implemented using an IPC channel error. If the IPC channel is not fully
368 // set up between the browser and GPU process, and the GPU process crashes or
369 // exits early, the browser process will never detect it. For this reason we
sadrul72aae8a2017-01-24 04:52:32370 // defer tearing down the GPU process until receiving the initialization
Sadrul Habib Chowdhury55fc2f02017-10-27 02:40:06371 // message from the browser (through mojom::VizMain::CreateGpuService()).
Sadrul Habib Chowdhurydb9021e2017-10-03 03:07:57372 const bool init_success = gpu_init->InitializeAndStartSandbox(
Zhenyao Moe23f75262018-02-07 02:15:00373 const_cast<base::CommandLine*>(&command_line), gpu_preferences);
Georg Neis18fc5142024-12-18 00:58:41374#if BUILDFLAG(IS_CHROMEOS)
Jenny Zhang06beeb02024-03-19 23:24:16375 LOG(WARNING) << "gpu initialization completed init_success:" << init_success;
376#endif
sadrul454af332016-09-09 18:14:32377 const bool dead_on_arrival = !init_success;
Sadrul Habib Chowdhuryc0a4a9b92016-08-29 21:43:24378
Ian Barkley-Yeung48418c12022-08-16 01:10:16379 auto* client = GetContentClient()->gpu();
380 if (client) {
381 client->PostSandboxInitialized();
382 }
383
Etienne Pierre-doray06b3b7842025-07-04 17:01:39384 // Startup tracing creates a tracing thread, which is incompatible on
385 // platforms that require single-threaded sandbox initialization. In these
386 // cases, startup tracing is either initialized right after sandbox
387 // initialization, or we restart the tracing thread during sandbox
388 // initialization.
389 if (parameters.needs_startup_tracing_after_sandbox_init) {
390 tracing::InitTracingPostFeatureList(/*enable_consumer=*/false,
391 /*will_trace_thread_restart=*/false);
392 }
393
Sadrul Habib Chowdhurydb9021e2017-10-03 03:07:57394 GetContentClient()->SetGpuInfo(gpu_init->gpu_info());
[email protected]ec4bda62013-06-14 15:51:03395
Etienne Pierre-doray8439625b8b2024-08-21 16:42:37396 base::ThreadType io_thread_type = base::ThreadType::kDisplayCritical;
Joe Mason94bebf12022-06-03 15:03:53397 // ChildProcess will start the ThreadPoolInstance now that the sandbox is
398 // initialized.
Zhibo Wangd9e4a002022-07-07 04:34:59399 ChildProcess gpu_process(io_thread_type);
Joe Mason94bebf12022-06-03 15:03:53400 DCHECK(base::ThreadPoolInstance::Get()->WasStarted());
Xi Chengd6390812018-01-24 00:01:50401
Ian Barkley-Yeung48418c12022-08-16 01:10:16402 if (client) {
Xi Chengd6390812018-01-24 00:01:50403 client->PostIOThreadCreated(gpu_process.io_task_runner());
Ian Barkley-Yeung48418c12022-08-16 01:10:16404 }
Xi Chengd6390812018-01-24 00:01:50405
Wez6979109b2018-09-07 17:30:56406 base::RunLoop run_loop;
407 GpuChildThread* child_thread =
Dale Curtis1b6becebb2020-03-30 20:13:35408 new GpuChildThread(run_loop.QuitClosure(), std::move(gpu_init));
[email protected]7a31f7c2011-03-21 23:22:04409 child_thread->Init(start_time);
[email protected]995a7f12011-02-11 23:07:17410
[email protected]7a31f7c2011-03-21 23:22:04411 gpu_process.set_main_thread(child_thread);
[email protected]983c33d2010-11-16 22:38:44412
Xiaohan Wang62737b52022-01-15 18:09:02413#if BUILDFLAG(IS_MAC)
Kai Ninomiyae2c55582019-12-19 23:51:03414 // A GPUEjectPolicy of 'wait' is set in the Info.plist of the browser
415 // process, meaning it is "responsible" for making sure it and its
416 // subordinate processes (i.e. the GPU process) drop references to the
417 // external GPU. Despite this, the system still sends the device removal
418 // notifications to the GPU process, so the GPU process handles its own
419 // graceful shutdown without help from the browser process.
420 //
421 // Using the "SafeEjectGPU" tool, we can see that when the browser process
422 // has a policy of 'wait', the GPU process gets the 'rwait' policy: "Eject
423 // actions apply to the responsible process, who in turn deals with
424 // subordinates to eliminate their ejecting eGPU references" [man 8
425 // SafeEjectGPU]. Empirically, the browser does not relaunch. Once the GPU
426 // process exits, it appears that the browser process is no longer considered
427 // to be using the GPU, so it "succeeds" the 'wait'.
428 metal::RegisterGracefulExitOnDeviceRemoval();
Christopher Cameron21c4abc2019-11-15 04:06:15429#endif
430
Xiaohan Wang62737b52022-01-15 18:09:02431#if BUILDFLAG(IS_ANDROID)
primianob3fb6412015-10-14 16:03:51432 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
primiano186d6bfe2015-10-30 13:21:40433 tracing::GraphicsMemoryDumpProvider::GetInstance(), "AndroidGraphics",
434 nullptr);
Benoit Lizeb6fa4ac2023-02-13 11:59:43435
436 base::android::MeminfoDumpProvider::Initialize();
primianob3fb6412015-10-14 16:03:51437#endif
438
Arthur Sonzognia570236352022-12-19 13:18:54439 base::allocator::PartitionAllocSupport::Get()->ReconfigureAfterTaskRunnerInit(
Benoit Lize7ee77d32021-03-04 17:26:14440 switches::kGpuProcess);
441
stanisc61507092017-07-06 16:36:58442 base::HighResolutionTimerManager hi_res_timer_manager;
443
henrika3cee59b2024-05-03 16:20:52444 // Adds support of wall-time based TimerKeeper metrics for the main GPU thread
445 // when command-line flag is set. CrGpuMain will be used as suffix for each
446 // metric.
447 if (command_line.HasSwitch(switches::kEnableGpuMainTimeKeeperMetrics)) {
448 base::CurrentThread::Get()->EnableMessagePumpTimeKeeperMetrics(
449 "CrGpuMain",
450 /*wall_time_based_metrics_enabled_for_testing=*/true);
451 }
452
Kramer Geb79116d2024-12-12 21:41:20453 DCHECK(tracing::IsTracingInitialized());
Kramer Geb79116d2024-12-12 21:41:20454
[email protected]d13f35d2012-05-18 02:28:15455 {
456 TRACE_EVENT0("gpu", "Run Message Loop");
Wez6979109b2018-09-07 17:30:56457 run_loop.Run();
[email protected]d13f35d2012-05-18 02:28:15458 }
[email protected]c0fc0942010-01-13 00:55:37459
jbaumana19f1df2017-01-18 03:01:17460 return dead_on_arrival ? RESULT_CODE_GPU_DEAD_ON_ARRIVAL : 0;
[email protected]c0fc0942010-01-13 00:55:37461}
[email protected]6ec3a572012-08-17 02:09:51462
463namespace {
464
Xiaohan Wang62737b52022-01-15 18:09:02465#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Satyajit Sahu82a76e02017-09-18 14:50:14466bool StartSandboxLinux(gpu::GpuWatchdogThread* watchdog_thread,
Zhenyao Moe9187a862017-10-20 04:26:33467 const gpu::GPUInfo* gpu_info,
468 const gpu::GpuPreferences& gpu_prefs) {
Kramer Ge0de97b152025-06-05 16:28:55469 TRACE_EVENT("gpu,startup", "Initialize sandbox");
[email protected]663c4b32013-04-18 05:52:54470
[email protected]f330b762014-02-08 04:52:46471 if (watchdog_thread) {
Tom Sepez437e2202017-10-24 21:26:47472 // SandboxLinux needs to be able to ensure that the thread
[email protected]f330b762014-02-08 04:52:46473 // has really been stopped.
Robert Sesek7d0b49b2020-07-08 18:31:27474 sandbox::policy::SandboxLinux::GetInstance()->StopThread(watchdog_thread);
[email protected]f330b762014-02-08 04:52:46475 }
[email protected]655abd522014-06-02 15:23:43476
Kramer Gea805bb012025-04-30 07:08:51477 base::Thread* trace_thread =
478 tracing::IsTracingInitialized()
479 ? tracing::PerfettoTracedProcess::GetTraceThread()
480 : nullptr;
481 if (trace_thread) {
482 sandbox::policy::SandboxLinux::GetInstance()->StopThread(trace_thread);
483 }
484
Tom Sepez437e2202017-10-24 21:26:47485 // SandboxLinux::InitializeSandbox() must always be called
[email protected]663c4b32013-04-18 05:52:54486 // with only one thread.
Robert Sesek7d0b49b2020-07-08 18:31:27487 sandbox::policy::SandboxLinux::Options sandbox_options;
Dominik Behr1ce8bff2022-07-13 00:54:11488 if (gpu_info) {
489 // We have to enable sandbox settings for all GPUs in the system
490 // for Chrome to be able to access/use them.
491 sandbox_options.use_amd_specific_policies =
492 angle::IsAMD(gpu_info->active_gpu().vendor_id);
493 sandbox_options.use_intel_specific_policies =
494 angle::IsIntel(gpu_info->active_gpu().vendor_id);
Kramer Ge545ba6d2023-01-17 17:14:48495 sandbox_options.use_virtio_specific_policies =
496 angle::IsVirtIO(gpu_info->active_gpu().vendor_id);
Dominik Behr1ce8bff2022-07-13 00:54:11497 sandbox_options.use_nvidia_specific_policies =
498 angle::IsNVIDIA(gpu_info->active_gpu().vendor_id);
499 for (const auto& gpu : gpu_info->secondary_gpus) {
500 if (angle::IsAMD(gpu.vendor_id))
501 sandbox_options.use_amd_specific_policies = true;
502 else if (angle::IsIntel(gpu.vendor_id))
503 sandbox_options.use_intel_specific_policies = true;
504 else if (angle::IsNVIDIA(gpu.vendor_id))
505 sandbox_options.use_nvidia_specific_policies = true;
506 }
507 }
Zhenyao Moe9187a862017-10-20 04:26:33508 sandbox_options.accelerated_video_decode_enabled =
509 !gpu_prefs.disable_accelerated_video_decode;
Sheng-Hao Tsaoea6aa852018-01-03 06:48:16510 sandbox_options.accelerated_video_encode_enabled =
511 !gpu_prefs.disable_accelerated_video_encode;
Tom Sepez085507ab2017-10-18 22:36:00512
Yaowei Zhoudbaba1b2023-05-24 05:23:55513#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
Peter McNeeley114d30182023-02-17 22:09:10514 // Video decoding of many video streams can use thousands of FDs as well as
Georg Neis18fc5142024-12-18 00:58:41515 // Exo clients.
Peter McNeeley114d30182023-02-17 22:09:10516 // See https://crbug.com/1417237
Jeff Chenfce90f32022-01-31 19:49:34517 const auto current_max_fds =
518 base::saturated_cast<unsigned int>(base::GetMaxFds());
Peter McNeeley114d30182023-02-17 22:09:10519 constexpr unsigned int kMaxFDsDelta = 1u << 13;
Jeff Chenfce90f32022-01-31 19:49:34520 const auto new_max_fds =
Peter McNeeley114d30182023-02-17 22:09:10521 static_cast<unsigned int>(base::ClampMax(current_max_fds, kMaxFDsDelta));
Hirokazu Honda53243142023-01-25 01:45:52522 base::IncreaseFdLimitTo(new_max_fds);
Jeff Chenfce90f32022-01-31 19:49:34523#endif
524
Robert Sesek7d0b49b2020-07-08 18:31:27525 bool res = sandbox::policy::SandboxLinux::GetInstance()->InitializeSandbox(
526 sandbox::policy::SandboxTypeFromCommandLine(
Tom Sepez2255db72017-10-26 18:50:09527 *base::CommandLine::ForCurrentProcess()),
Ken Rockot9c9d3da2023-11-28 22:58:32528 base::BindOnce(GpuPreSandboxHook), sandbox_options);
Tom Sepeza0950c62017-10-18 20:39:14529
[email protected]f330b762014-02-08 04:52:46530 if (watchdog_thread) {
Etienne Pierre-dorayef5dcca2023-07-11 16:46:27531 watchdog_thread->Start();
[email protected]f330b762014-02-08 04:52:46532 }
[email protected]663c4b32013-04-18 05:52:54533
Kramer Gea805bb012025-04-30 07:08:51534 if (trace_thread) {
535 tracing::PerfettoTracedProcess::Get().RestartThreadInSandbox();
536 }
537
[email protected]663c4b32013-04-18 05:52:54538 return res;
539}
Xiaohan Wang62737b52022-01-15 18:09:02540#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
[email protected]663c4b32013-04-18 05:52:54541
Ben Scarlato5ece30c72025-05-09 22:13:20542#if BUILDFLAG(IS_ANDROID)
543bool StartSandboxAndroid(gpu::GpuWatchdogThread* watchdog_thread) {
544 if (watchdog_thread) {
545 // Stop the watchdog thread temporarily.
546 base::ScopedFD proc_fd(
547 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC)));
548
549 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_fd.get(),
550 watchdog_thread);
551 }
552
553 bool res = sandbox::landlock::ApplyLandlock(
554 sandbox::policy::SandboxTypeFromCommandLine(
555 *base::CommandLine::ForCurrentProcess()));
556
557 if (watchdog_thread) {
558 watchdog_thread->Start();
559 }
560
561 return res;
562}
563#endif // BUILDFLAG(IS_ANDROID)
564
Xiaohan Wang62737b52022-01-15 18:09:02565#if BUILDFLAG(IS_WIN)
[email protected]663c4b32013-04-18 05:52:54566bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) {
Kramer Ge0de97b152025-06-05 16:28:55567 TRACE_EVENT("gpu,startup", "Lower token");
[email protected]663c4b32013-04-18 05:52:54568
569 // For Windows, if the target_services interface is not zero, the process
570 // is sandboxed and we must call LowerToken() before rendering untrusted
571 // content.
572 sandbox::TargetServices* target_services = sandbox_info->target_services;
573 if (target_services) {
574 target_services->LowerToken();
575 return true;
576 }
577
578 return false;
579}
Xiaohan Wang62737b52022-01-15 18:09:02580#endif // BUILDFLAG(IS_WIN)
[email protected]663c4b32013-04-18 05:52:54581
[email protected]6ec3a572012-08-17 02:09:51582} // namespace.
583
[email protected]eb398192012-10-22 20:16:19584} // namespace content