// 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 "base/logging.h" #include "base/run_loop.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<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() { scoped_refptr<base::TaskRunner> runner = mojo::core::GetIOTaskRunner(); return scoped_refptr<base::SingleThreadTaskRunner>( static_cast<base::SingleThreadTaskRunner*>(runner.get())); } ChannelReflectorListener::ChannelReflectorListener() : channel_(NULL) { VLOG(1) << "Client listener up"; } ChannelReflectorListener::~ChannelReflectorListener() { VLOG(1) << "Client listener down"; } void ChannelReflectorListener::Init(Sender* channel, const base::Closure& quit_closure) { DCHECK(!channel_); channel_ = channel; quit_closure_ = 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() { quit_closure_.Run(); } void ChannelReflectorListener::Send(IPC::Message* message) { channel_->Send(message); } LockThreadAffinity::LockThreadAffinity(int cpu_number) : affinity_set_ok_(false) { #if defined(OS_WIN) const DWORD_PTR thread_mask = static_cast<DWORD_PTR>(1) << cpu_number; old_affinity_ = SetThreadAffinityMask(GetCurrentThread(), thread_mask); affinity_set_ok_ = old_affinity_ != 0; #elif defined(OS_LINUX) 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 defined(OS_WIN) auto set_result = SetThreadAffinityMask(GetCurrentThread(), old_affinity_); DCHECK_NE(0u, set_result); #elif defined(OS_LINUX) 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<ChannelProxy> 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, const base::Closure& quit_closure) : quit_closure_(quit_closure), binding_(this, IPC::mojom::ReflectorRequest(std::move(handle))) {} ReflectorImpl::~ReflectorImpl() { ignore_result(binding_.Unbind().PassMessagePipe().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_) quit_closure_.Run(); } } // namespace IPC