162 lines
4.9 KiB
C++
162 lines
4.9 KiB
C++
// Copyright 2017 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/threading/platform_thread.h"
|
|
|
|
#include <pthread.h>
|
|
#include <sched.h>
|
|
#include <zircon/syscalls.h>
|
|
|
|
#include <mutex>
|
|
|
|
#include <fidl/fuchsia.media/cpp/fidl.h>
|
|
#include <lib/fdio/directory.h>
|
|
#include <lib/sys/cpp/component_context.h>
|
|
|
|
#include "base/fuchsia/fuchsia_component_connect.h"
|
|
#include "base/fuchsia/fuchsia_logging.h"
|
|
#include "base/fuchsia/scheduler.h"
|
|
#include "base/no_destructor.h"
|
|
#include "base/threading/platform_thread_internal_posix.h"
|
|
#include "base/threading/thread_id_name_manager.h"
|
|
#include "base/threading/thread_local_storage.h"
|
|
|
|
namespace base {
|
|
|
|
namespace {
|
|
|
|
fidl::SyncClient<fuchsia_media::ProfileProvider> ConnectProfileProvider() {
|
|
auto profile_provider_client_end =
|
|
base::fuchsia_component::Connect<fuchsia_media::ProfileProvider>();
|
|
if (profile_provider_client_end.is_error()) {
|
|
LOG(ERROR) << base::FidlConnectionErrorMessage(profile_provider_client_end);
|
|
return {};
|
|
}
|
|
return fidl::SyncClient(std::move(profile_provider_client_end.value()));
|
|
}
|
|
|
|
// Sets the current thread to the given scheduling role, optionally including
|
|
// hints about the workload period and max CPU runtime (capacity * period) in
|
|
// that period.
|
|
// TODO(crbug.com/1365682): Migrate to the new fuchsia.scheduler.ProfileProvider
|
|
// API when available.
|
|
void SetThreadRole(StringPiece role_name,
|
|
TimeDelta period = {},
|
|
float capacity = 0.0f) {
|
|
DCHECK_GE(capacity, 0.0);
|
|
DCHECK_LE(capacity, 1.0);
|
|
|
|
static const base::NoDestructor<
|
|
fidl::SyncClient<fuchsia_media::ProfileProvider>>
|
|
profile_provider(ConnectProfileProvider());
|
|
|
|
if (!profile_provider->is_valid()) {
|
|
return;
|
|
}
|
|
|
|
zx::thread dup_thread;
|
|
zx_status_t status =
|
|
zx::thread::self()->duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_thread);
|
|
ZX_CHECK(status == ZX_OK, status) << "zx_object_duplicate";
|
|
|
|
std::string role_selector{role_name};
|
|
auto result = (*profile_provider)
|
|
->RegisterHandlerWithCapacity(
|
|
{{.thread_handle = std::move(dup_thread),
|
|
.name = role_selector,
|
|
.period = period.ToZxDuration(),
|
|
.capacity = capacity}});
|
|
if (result.is_error()) {
|
|
ZX_DLOG(ERROR, result.error_value().status())
|
|
<< "Failed call to RegisterHandlerWithCapacity";
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void InitThreading() {}
|
|
|
|
void TerminateOnThread() {}
|
|
|
|
size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
|
|
return 0;
|
|
}
|
|
|
|
// static
|
|
void PlatformThread::SetName(const std::string& name) {
|
|
zx_status_t status = zx_object_set_property(CurrentId(), ZX_PROP_NAME,
|
|
name.data(), name.size());
|
|
DCHECK_EQ(status, ZX_OK);
|
|
|
|
ThreadIdNameManager::GetInstance()->SetName(name);
|
|
}
|
|
|
|
// static
|
|
bool PlatformThread::CanChangeThreadType(ThreadType from, ThreadType to) {
|
|
return from == to || to == ThreadType::kDisplayCritical ||
|
|
to == ThreadType::kRealtimeAudio;
|
|
}
|
|
|
|
namespace internal {
|
|
|
|
void SetCurrentThreadTypeImpl(ThreadType thread_type,
|
|
MessagePumpType pump_type_hint) {
|
|
switch (thread_type) {
|
|
case ThreadType::kDefault:
|
|
SetThreadRole("chromium.base.threading.default");
|
|
|
|
break;
|
|
|
|
case ThreadType::kBackground:
|
|
SetThreadRole("chromium.base.threading.background");
|
|
break;
|
|
|
|
case ThreadType::kUtility:
|
|
SetThreadRole("chromium.base.threading.utility");
|
|
break;
|
|
|
|
case ThreadType::kResourceEfficient:
|
|
SetThreadRole("chromium.base.threading.resource-efficient");
|
|
break;
|
|
|
|
case ThreadType::kCompositing:
|
|
SetThreadRole("chromium.base.threading.compositing",
|
|
kDisplaySchedulingPeriod, kDisplaySchedulingCapacity);
|
|
break;
|
|
|
|
case ThreadType::kDisplayCritical:
|
|
SetThreadRole("chromium.base.threading.display", kDisplaySchedulingPeriod,
|
|
kDisplaySchedulingCapacity);
|
|
break;
|
|
|
|
case ThreadType::kRealtimeAudio:
|
|
SetThreadRole("chromium.base.threading.realtime-audio",
|
|
kAudioSchedulingPeriod, kAudioSchedulingCapacity);
|
|
break;
|
|
}
|
|
}
|
|
|
|
} // namespace internal
|
|
|
|
// static
|
|
ThreadPriorityForTest PlatformThread::GetCurrentThreadPriorityForTest() {
|
|
// Fuchsia doesn't provide a way to get the current thread's priority.
|
|
// Use ThreadType stored in TLS as a proxy.
|
|
const ThreadType thread_type = PlatformThread::GetCurrentThreadType();
|
|
switch (thread_type) {
|
|
case ThreadType::kBackground:
|
|
case ThreadType::kUtility:
|
|
case ThreadType::kResourceEfficient:
|
|
case ThreadType::kDefault:
|
|
case ThreadType::kCompositing:
|
|
return ThreadPriorityForTest::kNormal;
|
|
case ThreadType::kDisplayCritical:
|
|
return ThreadPriorityForTest::kDisplay;
|
|
case ThreadType::kRealtimeAudio:
|
|
return ThreadPriorityForTest::kRealtimeAudio;
|
|
}
|
|
}
|
|
|
|
} // namespace base
|