// Copyright 2017 The Chromium 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 "ipc/ipc_perftest_util.h" #include #include "base/logging.h" #include "base/run_loop.h" #include "build/build_config.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_perftest_messages.h" #include "mojo/core/embedder/embedder.h" #include "mojo/core/test/multiprocess_test_helper.h" namespace IPC { scoped_refptr GetIOThreadTaskRunner() { scoped_refptr runner = mojo::core::GetIOTaskRunner(); return scoped_refptr( static_cast(runner.get())); } ChannelReflectorListener::ChannelReflectorListener() : channel_(nullptr) { VLOG(1) << "Client listener up"; } ChannelReflectorListener::~ChannelReflectorListener() { VLOG(1) << "Client listener down"; } void ChannelReflectorListener::Init(Sender* channel, base::OnceClosure quit_closure) { DCHECK(!channel_); channel_ = channel; quit_closure_ = std::move(quit_closure); } bool ChannelReflectorListener::OnMessageReceived(const Message& message) { CHECK(channel_); bool handled = true; IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message) IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello) IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing) IPC_MESSAGE_HANDLER(TestMsg_SyncPing, OnSyncPing) IPC_MESSAGE_HANDLER(TestMsg_Quit, OnQuit) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void ChannelReflectorListener::OnHello() { channel_->Send(new TestMsg_Hello); } void ChannelReflectorListener::OnPing(const std::string& payload) { channel_->Send(new TestMsg_Ping(payload)); } void ChannelReflectorListener::OnSyncPing(const std::string& payload, std::string* response) { *response = payload; } void ChannelReflectorListener::OnQuit() { std::move(quit_closure_).Run(); } void ChannelReflectorListener::Send(IPC::Message* message) { channel_->Send(message); } LockThreadAffinity::LockThreadAffinity(int cpu_number) : affinity_set_ok_(false) { #if BUILDFLAG(IS_WIN) const DWORD_PTR thread_mask = static_cast(1) << cpu_number; old_affinity_ = SetThreadAffinityMask(GetCurrentThread(), thread_mask); affinity_set_ok_ = old_affinity_ != 0; #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(cpu_number, &cpuset); auto get_result = sched_getaffinity(0, sizeof(old_cpuset_), &old_cpuset_); DCHECK_EQ(0, get_result); auto set_result = sched_setaffinity(0, sizeof(cpuset), &cpuset); // Check for get_result failure, even though it should always succeed. affinity_set_ok_ = (set_result == 0) && (get_result == 0); #endif if (!affinity_set_ok_) LOG(WARNING) << "Failed to set thread affinity to CPU " << cpu_number; } LockThreadAffinity::~LockThreadAffinity() { if (!affinity_set_ok_) return; #if BUILDFLAG(IS_WIN) auto set_result = SetThreadAffinityMask(GetCurrentThread(), old_affinity_); DCHECK_NE(0u, set_result); #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) auto set_result = sched_setaffinity(0, sizeof(old_cpuset_), &old_cpuset_); DCHECK_EQ(0, set_result); #endif } MojoPerfTestClient::MojoPerfTestClient() : listener_(new ChannelReflectorListener()) { mojo::core::test::MultiprocessTestHelper::ChildSetup(); } MojoPerfTestClient::~MojoPerfTestClient() = default; int MojoPerfTestClient::Run(MojoHandle handle) { handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle)); LockThreadAffinity thread_locker(kSharedCore); base::RunLoop run_loop; std::unique_ptr channel = IPC::ChannelProxy::Create( handle_.release(), Channel::MODE_CLIENT, listener_.get(), GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get()); listener_->Init(channel.get(), run_loop.QuitWhenIdleClosure()); run_loop.Run(); return 0; } ReflectorImpl::ReflectorImpl(mojo::ScopedMessagePipeHandle handle, base::OnceClosure quit_closure) : quit_closure_(std::move(quit_closure)), receiver_( this, mojo::PendingReceiver(std::move(handle))) {} ReflectorImpl::~ReflectorImpl() { std::ignore = receiver_.Unbind().PassPipe().release(); } void ReflectorImpl::Ping(const std::string& value, PingCallback callback) { std::move(callback).Run(value); } void ReflectorImpl::SyncPing(const std::string& value, PingCallback callback) { std::move(callback).Run(value); } void ReflectorImpl::Quit() { if (quit_closure_) std::move(quit_closure_).Run(); } } // namespace IPC