1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/ipc_perftest_util.h"
9 #include "base/logging.h"
10 #include "base/run_loop.h"
11 #include "base/task/single_thread_task_runner.h"
12 #include "build/build_config.h"
13 #include "ipc/ipc_channel_proxy.h"
14 #include "ipc/ipc_perftest_messages.h"
15 #include "mojo/core/embedder/embedder.h"
16 #include "mojo/core/test/multiprocess_test_helper.h"
20 scoped_refptr<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() {
21 scoped_refptr<base::TaskRunner> runner = mojo::core::GetIOTaskRunner();
22 return scoped_refptr<base::SingleThreadTaskRunner>(
23 static_cast<base::SingleThreadTaskRunner*>(runner.get()));
26 ChannelReflectorListener::ChannelReflectorListener() : channel_(nullptr) {
27 VLOG(1) << "Client listener up";
30 ChannelReflectorListener::~ChannelReflectorListener() {
31 VLOG(1) << "Client listener down";
34 void ChannelReflectorListener::Init(Sender* channel,
35 base::OnceClosure quit_closure) {
38 quit_closure_ = std::move(quit_closure);
41 bool ChannelReflectorListener::OnMessageReceived(const Message& message) {
44 IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message)
45 IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello)
46 IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing)
47 IPC_MESSAGE_HANDLER(TestMsg_SyncPing, OnSyncPing)
48 IPC_MESSAGE_HANDLER(TestMsg_Quit, OnQuit)
49 IPC_MESSAGE_UNHANDLED(handled = false)
54 void ChannelReflectorListener::OnHello() {
55 channel_->Send(new TestMsg_Hello);
58 void ChannelReflectorListener::OnPing(const std::string& payload) {
59 channel_->Send(new TestMsg_Ping(payload));
62 void ChannelReflectorListener::OnSyncPing(const std::string& payload,
63 std::string* response) {
67 void ChannelReflectorListener::OnQuit() {
68 std::move(quit_closure_).Run();
71 void ChannelReflectorListener::Send(IPC::Message* message) {
72 channel_->Send(message);
75 LockThreadAffinity::LockThreadAffinity(int cpu_number)
76 : affinity_set_ok_(false) {
78 const DWORD_PTR thread_mask = static_cast<DWORD_PTR>(1) << cpu_number;
79 old_affinity_ = SetThreadAffinityMask(GetCurrentThread(), thread_mask);
80 affinity_set_ok_ = old_affinity_ != 0;
81 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
84 CPU_SET(cpu_number, &cpuset);
85 auto get_result = sched_getaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
86 DCHECK_EQ(0, get_result);
87 auto set_result = sched_setaffinity(0, sizeof(cpuset), &cpuset);
88 // Check for get_result failure, even though it should always succeed.
89 affinity_set_ok_ = (set_result == 0) && (get_result == 0);
91 if (!affinity_set_ok_)
92 LOG(WARNING) << "Failed to set thread affinity to CPU " << cpu_number;
95 LockThreadAffinity::~LockThreadAffinity() {
96 if (!affinity_set_ok_)
99 auto set_result = SetThreadAffinityMask(GetCurrentThread(), old_affinity_);
100 DCHECK_NE(0u, set_result);
101 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
102 auto set_result = sched_setaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
103 DCHECK_EQ(0, set_result);
107 MojoPerfTestClient::MojoPerfTestClient()
108 : listener_(new ChannelReflectorListener()) {
109 mojo::core::test::MultiprocessTestHelper::ChildSetup();
112 MojoPerfTestClient::~MojoPerfTestClient() = default;
114 int MojoPerfTestClient::Run(MojoHandle handle) {
115 handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle));
116 LockThreadAffinity thread_locker(kSharedCore);
118 base::RunLoop run_loop;
119 std::unique_ptr<ChannelProxy> channel = IPC::ChannelProxy::Create(
120 handle_.release(), Channel::MODE_CLIENT, listener_.get(),
121 GetIOThreadTaskRunner(),
122 base::SingleThreadTaskRunner::GetCurrentDefault());
123 listener_->Init(channel.get(), run_loop.QuitWhenIdleClosure());
128 ReflectorImpl::ReflectorImpl(mojo::ScopedMessagePipeHandle handle,
129 base::OnceClosure quit_closure)
130 : quit_closure_(std::move(quit_closure)),
133 mojo::PendingReceiver<IPC::mojom::Reflector>(std::move(handle))) {}
135 ReflectorImpl::~ReflectorImpl() {
136 std::ignore = receiver_.Unbind().PassPipe().release();
139 void ReflectorImpl::Ping(const std::string& value, PingCallback callback) {
140 std::move(callback).Run(value);
143 void ReflectorImpl::SyncPing(const std::string& value, PingCallback callback) {
144 std::move(callback).Run(value);
147 void ReflectorImpl::Quit() {
149 std::move(quit_closure_).Run();