blob: e20a2b8b116f8446f416cb7ab103262100d1e239 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "profile_manager.h"
#include <fuchsia/scheduler/cpp/fidl.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/zx/profile.h>
#include <lib/zx/status.h>
#include <threads.h>
#include <zircon/assert.h>
#include <zircon/threads.h>
#include <memory>
#include <thread>
#include <unordered_map>
#include <utility>
#include "src/lib/fxl/strings/string_printf.h"
namespace hwstress {
zx::unowned<zx::thread> HandleFromThread(std::thread* thread) {
// The native handle is a thrd_t. We don't currently provide any nice way to convert this, other
// than this ugly cast.
zx_handle_t handle = thrd_get_zx_handle(static_cast<thrd_t>(thread->native_handle()));
return zx::unowned<zx::thread>(handle);
}
std::unique_ptr<ProfileManager> ProfileManager::CreateFromEnvironment() {
std::shared_ptr<sys::ServiceDirectory> svc = sys::ServiceDirectory::CreateFromNamespace();
if (svc == nullptr) {
return nullptr;
}
fuchsia::scheduler::ProfileProviderSyncPtr profile_provider;
zx_status_t status = svc->Connect(profile_provider.NewRequest());
if (status != ZX_OK) {
return nullptr;
}
return std::make_unique<ProfileManager>(std::move(profile_provider));
}
ProfileManager::ProfileManager(fuchsia::scheduler::ProfileProviderSyncPtr profile_provider)
: profile_provider_(std::move(profile_provider)) {}
zx_status_t ProfileManager::SetThreadAffinity(const zx::thread& thread, uint32_t mask) {
return CreateAndApplyProfile<uint32_t>(
&affinity_profiles_, mask,
[this](uint32_t mask) -> zx::status<zx::profile> {
zx::profile profile;
zx_status_t server_status;
zx_status_t status =
profile_provider_->GetCpuAffinityProfile({mask}, &server_status, &profile);
if (status != ZX_OK) {
return zx::error(status);
}
if (server_status != ZX_OK) {
return zx::error(server_status);
}
return zx::ok(std::move(profile));
},
thread);
}
zx_status_t ProfileManager::SetThreadAffinity(std::thread* thread, uint32_t mask) {
return SetThreadAffinity(*HandleFromThread(thread), mask);
}
zx_status_t ProfileManager::SetThreadPriority(const zx::thread& thread, uint32_t priority) {
return CreateAndApplyProfile<uint32_t>(
&priority_profiles_, priority,
[this](uint32_t priority) -> zx::status<zx::profile> {
zx::profile profile;
zx_status_t server_status;
zx_status_t status = profile_provider_->GetProfile(
priority, fxl::StringPrintf("hwstress-priority-%d", priority), &server_status,
&profile);
if (status != ZX_OK) {
return zx::error(status);
}
if (server_status != ZX_OK) {
return zx::error(server_status);
}
return zx::ok(std::move(profile));
},
thread);
}
zx_status_t ProfileManager::SetThreadPriority(std::thread* thread, uint32_t priority) {
return SetThreadPriority(*HandleFromThread(thread), priority);
}
} // namespace hwstress