Skip to content

Commit

Permalink
Add ThreadConfigSetter for Embedder api that can set thread priority (f…
Browse files Browse the repository at this point in the history
  • Loading branch information
JsouLiang authored Mar 2, 2022
1 parent d433fe4 commit 2c396fe
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 18 deletions.
2 changes: 1 addition & 1 deletion fml/thread_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "flutter/fml/thread.h"

#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
#if defined(FML_OS_MACOSX) || defined(FML_OS_LINUX) || defined(FML_OS_ANDROID)
#define FLUTTER_PTHREAD_SUPPORTED 1
#else
#define FLUTTER_PTHREAD_SUPPORTED 0
Expand Down
27 changes: 27 additions & 0 deletions shell/common/thread_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,33 @@ std::string ThreadHost::ThreadHostConfig::MakeThreadName(
}
}

void ThreadHost::ThreadHostConfig::SetIOConfig(const ThreadConfig& config) {
type_mask |= ThreadHost::Type::IO;
io_config = config;
}

void ThreadHost::ThreadHostConfig::SetUIConfig(const ThreadConfig& config) {
type_mask |= ThreadHost::Type::UI;
ui_config = config;
}

void ThreadHost::ThreadHostConfig::SetPlatformConfig(
const ThreadConfig& config) {
type_mask |= ThreadHost::Type::Platform;
platform_config = config;
}

void ThreadHost::ThreadHostConfig::SetRasterConfig(const ThreadConfig& config) {
type_mask |= ThreadHost::Type::RASTER;
raster_config = config;
}

void ThreadHost::ThreadHostConfig::SetProfilerConfig(
const ThreadConfig& config) {
type_mask |= ThreadHost::Type::Profiler;
profiler_config = config;
}

std::unique_ptr<fml::Thread> ThreadHost::CreateThread(
Type type,
std::optional<ThreadConfig> thread_config,
Expand Down
19 changes: 18 additions & 1 deletion shell/common/thread_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ struct ThreadHost {
/// The collection of all the thread configures, and we create custom thread
/// configure in engine to info the thread.
struct ThreadHostConfig {
ThreadHostConfig() : type_mask(0) {}
explicit ThreadHostConfig(
const ThreadConfigSetter& setter = fml::Thread::SetCurrentThreadName)
: type_mask(0), config_setter(setter) {}

ThreadHostConfig(
const std::string& name_prefix,
Expand All @@ -49,6 +51,21 @@ struct ThreadHost {
/// Use the prefix and thread type to generator a thread name.
static std::string MakeThreadName(Type type, const std::string& prefix);

/// Specified the UI Thread Config, meanwhile set the mask.
void SetUIConfig(const ThreadConfig&);

/// Specified the Platform Thread Config, meanwhile set the mask.
void SetPlatformConfig(const ThreadConfig&);

/// Specified the IO Thread Config, meanwhile set the mask.
void SetRasterConfig(const ThreadConfig&);

/// Specified the IO Thread Config, meanwhile set the mask.
void SetIOConfig(const ThreadConfig&);

/// Specified the ProfilerThread Config, meanwhile set the mask.
void SetProfilerConfig(const ThreadConfig&);

uint64_t type_mask;

std::string name_prefix = "";
Expand Down
50 changes: 37 additions & 13 deletions shell/platform/embedder/embedder_thread_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ CreateEmbedderTaskRunner(const FlutterTaskRunnerDescription* description) {

std::unique_ptr<EmbedderThreadHost>
EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
const FlutterCustomTaskRunners* custom_task_runners) {
const FlutterCustomTaskRunners* custom_task_runners,
flutter::ThreadConfigSetter config_setter) {
{
auto host = CreateEmbedderManagedThreadHost(custom_task_runners);
auto host =
CreateEmbedderManagedThreadHost(custom_task_runners, config_setter);
if (host && host->IsValid()) {
return host;
}
Expand All @@ -94,7 +96,7 @@ EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
// configuration if the embedder attempted to specify a configuration but
// messed up with an incorrect configuration.
if (custom_task_runners == nullptr) {
auto host = CreateEngineManagedThreadHost();
auto host = CreateEngineManagedThreadHost(config_setter);
if (host && host->IsValid()) {
return host;
}
Expand All @@ -110,20 +112,34 @@ static fml::RefPtr<fml::TaskRunner> GetCurrentThreadTaskRunner() {

constexpr const char* kFlutterThreadName = "io.flutter";

fml::Thread::ThreadConfig MakeThreadConfig(
flutter::ThreadHost::Type type,
fml::Thread::ThreadPriority priority) {
return fml::Thread::ThreadConfig(
flutter::ThreadHost::ThreadHostConfig::MakeThreadName(type,
kFlutterThreadName),
priority);
}

// static
std::unique_ptr<EmbedderThreadHost>
EmbedderThreadHost::CreateEmbedderManagedThreadHost(
const FlutterCustomTaskRunners* custom_task_runners) {
const FlutterCustomTaskRunners* custom_task_runners,
flutter::ThreadConfigSetter config_setter) {
if (custom_task_runners == nullptr) {
return nullptr;
}

auto thread_host_config = ThreadHost::ThreadHostConfig(config_setter);

// The UI and IO threads are always created by the engine and the embedder has
// no opportunity to specify task runners for the same.
//
// If/when more task runners are exposed, this mask will need to be updated.
uint64_t engine_thread_host_mask =
ThreadHost::Type::UI | ThreadHost::Type::IO;
thread_host_config.SetUIConfig(MakeThreadConfig(
ThreadHost::Type::UI, fml::Thread::ThreadPriority::DISPLAY));
thread_host_config.SetIOConfig(MakeThreadConfig(
ThreadHost::Type::IO, fml::Thread::ThreadPriority::BACKGROUND));

auto platform_task_runner_pair = CreateEmbedderTaskRunner(
SAFE_ACCESS(custom_task_runners, platform_task_runner, nullptr));
Expand All @@ -140,7 +156,8 @@ EmbedderThreadHost::CreateEmbedderManagedThreadHost(
// If the embedder has not supplied a raster task runner, one needs to be
// created.
if (!render_task_runner_pair.second) {
engine_thread_host_mask |= ThreadHost::Type::RASTER;
thread_host_config.SetRasterConfig(MakeThreadConfig(
ThreadHost::Type::RASTER, fml::Thread::ThreadPriority::RASTER));
}

// If both the platform task runner and the raster task runner are specified
Expand All @@ -154,8 +171,7 @@ EmbedderThreadHost::CreateEmbedderManagedThreadHost(

// Create a thread host with just the threads that need to be managed by the
// engine. The embedder has provided the rest.
ThreadHost thread_host(ThreadHost::ThreadHostConfig(kFlutterThreadName,
engine_thread_host_mask));
ThreadHost thread_host(thread_host_config);

// If the embedder has supplied a platform task runner, use that. If not, use
// the current thread task runner.
Expand Down Expand Up @@ -206,12 +222,20 @@ EmbedderThreadHost::CreateEmbedderManagedThreadHost(

// static
std::unique_ptr<EmbedderThreadHost>
EmbedderThreadHost::CreateEngineManagedThreadHost() {
EmbedderThreadHost::CreateEngineManagedThreadHost(
flutter::ThreadConfigSetter config_setter) {
// Crate a thraed host config, and specified the thread name and priority.
auto thread_host_config = ThreadHost::ThreadHostConfig(config_setter);
thread_host_config.SetUIConfig(MakeThreadConfig(
flutter::ThreadHost::UI, fml::Thread::ThreadPriority::DISPLAY));
thread_host_config.SetRasterConfig(MakeThreadConfig(
flutter::ThreadHost::RASTER, fml::Thread::ThreadPriority::RASTER));
thread_host_config.SetIOConfig(MakeThreadConfig(
flutter::ThreadHost::IO, fml::Thread::ThreadPriority::BACKGROUND));

// Create a thread host with the current thread as the platform thread and all
// other threads managed.
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
kFlutterThreadName,
ThreadHost::Type::RASTER | ThreadHost::Type::IO | ThreadHost::Type::UI));
ThreadHost thread_host(thread_host_config);

// For embedder platforms that don't have native message loop interop, this
// will reference a task runner that points to a null message loop
Expand Down
12 changes: 9 additions & 3 deletions shell/platform/embedder/embedder_thread_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class EmbedderThreadHost {
public:
static std::unique_ptr<EmbedderThreadHost>
CreateEmbedderOrEngineManagedThreadHost(
const FlutterCustomTaskRunners* custom_task_runners);
const FlutterCustomTaskRunners* custom_task_runners,
flutter::ThreadConfigSetter config_setter =
fml::Thread::SetCurrentThreadName);

EmbedderThreadHost(
ThreadHost host,
Expand All @@ -42,9 +44,13 @@ class EmbedderThreadHost {
std::map<int64_t, fml::RefPtr<EmbedderTaskRunner>> runners_map_;

static std::unique_ptr<EmbedderThreadHost> CreateEmbedderManagedThreadHost(
const FlutterCustomTaskRunners* custom_task_runners);
const FlutterCustomTaskRunners* custom_task_runners,
flutter::ThreadConfigSetter config_setter =
fml::Thread::SetCurrentThreadName);

static std::unique_ptr<EmbedderThreadHost> CreateEngineManagedThreadHost();
static std::unique_ptr<EmbedderThreadHost> CreateEngineManagedThreadHost(
flutter::ThreadConfigSetter config_setter =
fml::Thread::SetCurrentThreadName);

FML_DISALLOW_COPY_AND_ASSIGN(EmbedderThreadHost);
};
Expand Down
44 changes: 44 additions & 0 deletions shell/platform/embedder/tests/embedder_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/tonic/converter/dart_converter.h"

#if defined(FML_OS_MACOSX)
#include <pthread.h>
#endif

// CREATE_NATIVE_ENTRY is leaky by design
// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)

Expand Down Expand Up @@ -1772,6 +1776,46 @@ TEST_F(EmbedderTest, CanScheduleFrame) {
check_latch.Wait();
}

#if defined(FML_OS_MACOSX)

static void MockThreadConfigSetter(const fml::Thread::ThreadConfig& config) {
pthread_t tid = pthread_self();
struct sched_param param;
int policy = SCHED_OTHER;
switch (config.priority) {
case fml::Thread::ThreadPriority::DISPLAY:
param.sched_priority = 10;
break;
default:
param.sched_priority = 1;
}
pthread_setschedparam(tid, policy, &param);
}

TEST_F(EmbedderTest, EmbedderThreadHostUseCustomThreadConfig) {
auto thread_host =
flutter::EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
nullptr, MockThreadConfigSetter);

int ui_policy;
struct sched_param ui_param;

thread_host->GetTaskRunners().GetUITaskRunner()->PostTask([&] {
pthread_t current_thread = pthread_self();
pthread_getschedparam(current_thread, &ui_policy, &ui_param);
ASSERT_EQ(ui_param.sched_priority, 10);
});

int io_policy;
struct sched_param io_param;
thread_host->GetTaskRunners().GetIOTaskRunner()->PostTask([&] {
pthread_t current_thread = pthread_self();
pthread_getschedparam(current_thread, &io_policy, &io_param);
ASSERT_EQ(io_param.sched_priority, 1);
});
}
#endif

} // namespace testing
} // namespace flutter

Expand Down

0 comments on commit 2c396fe

Please sign in to comment.