1*635a8641SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_perftest_util.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
8*635a8641SAndroid Build Coastguard Worker #include "base/run_loop.h"
9*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_channel_proxy.h"
10*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_perftest_messages.h"
11*635a8641SAndroid Build Coastguard Worker #include "mojo/core/embedder/embedder.h"
12*635a8641SAndroid Build Coastguard Worker #include "mojo/core/test/multiprocess_test_helper.h"
13*635a8641SAndroid Build Coastguard Worker
14*635a8641SAndroid Build Coastguard Worker namespace IPC {
15*635a8641SAndroid Build Coastguard Worker
GetIOThreadTaskRunner()16*635a8641SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() {
17*635a8641SAndroid Build Coastguard Worker scoped_refptr<base::TaskRunner> runner = mojo::core::GetIOTaskRunner();
18*635a8641SAndroid Build Coastguard Worker return scoped_refptr<base::SingleThreadTaskRunner>(
19*635a8641SAndroid Build Coastguard Worker static_cast<base::SingleThreadTaskRunner*>(runner.get()));
20*635a8641SAndroid Build Coastguard Worker }
21*635a8641SAndroid Build Coastguard Worker
ChannelReflectorListener()22*635a8641SAndroid Build Coastguard Worker ChannelReflectorListener::ChannelReflectorListener() : channel_(NULL) {
23*635a8641SAndroid Build Coastguard Worker VLOG(1) << "Client listener up";
24*635a8641SAndroid Build Coastguard Worker }
25*635a8641SAndroid Build Coastguard Worker
~ChannelReflectorListener()26*635a8641SAndroid Build Coastguard Worker ChannelReflectorListener::~ChannelReflectorListener() {
27*635a8641SAndroid Build Coastguard Worker VLOG(1) << "Client listener down";
28*635a8641SAndroid Build Coastguard Worker }
29*635a8641SAndroid Build Coastguard Worker
Init(Sender * channel,const base::Closure & quit_closure)30*635a8641SAndroid Build Coastguard Worker void ChannelReflectorListener::Init(Sender* channel,
31*635a8641SAndroid Build Coastguard Worker const base::Closure& quit_closure) {
32*635a8641SAndroid Build Coastguard Worker DCHECK(!channel_);
33*635a8641SAndroid Build Coastguard Worker channel_ = channel;
34*635a8641SAndroid Build Coastguard Worker quit_closure_ = quit_closure;
35*635a8641SAndroid Build Coastguard Worker }
36*635a8641SAndroid Build Coastguard Worker
OnMessageReceived(const Message & message)37*635a8641SAndroid Build Coastguard Worker bool ChannelReflectorListener::OnMessageReceived(const Message& message) {
38*635a8641SAndroid Build Coastguard Worker CHECK(channel_);
39*635a8641SAndroid Build Coastguard Worker bool handled = true;
40*635a8641SAndroid Build Coastguard Worker IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message)
41*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello)
42*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing)
43*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(TestMsg_SyncPing, OnSyncPing)
44*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_HANDLER(TestMsg_Quit, OnQuit)
45*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_UNHANDLED(handled = false)
46*635a8641SAndroid Build Coastguard Worker IPC_END_MESSAGE_MAP()
47*635a8641SAndroid Build Coastguard Worker return handled;
48*635a8641SAndroid Build Coastguard Worker }
49*635a8641SAndroid Build Coastguard Worker
OnHello()50*635a8641SAndroid Build Coastguard Worker void ChannelReflectorListener::OnHello() {
51*635a8641SAndroid Build Coastguard Worker channel_->Send(new TestMsg_Hello);
52*635a8641SAndroid Build Coastguard Worker }
53*635a8641SAndroid Build Coastguard Worker
OnPing(const std::string & payload)54*635a8641SAndroid Build Coastguard Worker void ChannelReflectorListener::OnPing(const std::string& payload) {
55*635a8641SAndroid Build Coastguard Worker channel_->Send(new TestMsg_Ping(payload));
56*635a8641SAndroid Build Coastguard Worker }
57*635a8641SAndroid Build Coastguard Worker
OnSyncPing(const std::string & payload,std::string * response)58*635a8641SAndroid Build Coastguard Worker void ChannelReflectorListener::OnSyncPing(const std::string& payload,
59*635a8641SAndroid Build Coastguard Worker std::string* response) {
60*635a8641SAndroid Build Coastguard Worker *response = payload;
61*635a8641SAndroid Build Coastguard Worker }
62*635a8641SAndroid Build Coastguard Worker
OnQuit()63*635a8641SAndroid Build Coastguard Worker void ChannelReflectorListener::OnQuit() {
64*635a8641SAndroid Build Coastguard Worker quit_closure_.Run();
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker
Send(IPC::Message * message)67*635a8641SAndroid Build Coastguard Worker void ChannelReflectorListener::Send(IPC::Message* message) {
68*635a8641SAndroid Build Coastguard Worker channel_->Send(message);
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker
LockThreadAffinity(int cpu_number)71*635a8641SAndroid Build Coastguard Worker LockThreadAffinity::LockThreadAffinity(int cpu_number)
72*635a8641SAndroid Build Coastguard Worker : affinity_set_ok_(false) {
73*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
74*635a8641SAndroid Build Coastguard Worker const DWORD_PTR thread_mask = static_cast<DWORD_PTR>(1) << cpu_number;
75*635a8641SAndroid Build Coastguard Worker old_affinity_ = SetThreadAffinityMask(GetCurrentThread(), thread_mask);
76*635a8641SAndroid Build Coastguard Worker affinity_set_ok_ = old_affinity_ != 0;
77*635a8641SAndroid Build Coastguard Worker #elif defined(OS_LINUX)
78*635a8641SAndroid Build Coastguard Worker cpu_set_t cpuset;
79*635a8641SAndroid Build Coastguard Worker CPU_ZERO(&cpuset);
80*635a8641SAndroid Build Coastguard Worker CPU_SET(cpu_number, &cpuset);
81*635a8641SAndroid Build Coastguard Worker auto get_result = sched_getaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
82*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(0, get_result);
83*635a8641SAndroid Build Coastguard Worker auto set_result = sched_setaffinity(0, sizeof(cpuset), &cpuset);
84*635a8641SAndroid Build Coastguard Worker // Check for get_result failure, even though it should always succeed.
85*635a8641SAndroid Build Coastguard Worker affinity_set_ok_ = (set_result == 0) && (get_result == 0);
86*635a8641SAndroid Build Coastguard Worker #endif
87*635a8641SAndroid Build Coastguard Worker if (!affinity_set_ok_)
88*635a8641SAndroid Build Coastguard Worker LOG(WARNING) << "Failed to set thread affinity to CPU " << cpu_number;
89*635a8641SAndroid Build Coastguard Worker }
90*635a8641SAndroid Build Coastguard Worker
~LockThreadAffinity()91*635a8641SAndroid Build Coastguard Worker LockThreadAffinity::~LockThreadAffinity() {
92*635a8641SAndroid Build Coastguard Worker if (!affinity_set_ok_)
93*635a8641SAndroid Build Coastguard Worker return;
94*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
95*635a8641SAndroid Build Coastguard Worker auto set_result = SetThreadAffinityMask(GetCurrentThread(), old_affinity_);
96*635a8641SAndroid Build Coastguard Worker DCHECK_NE(0u, set_result);
97*635a8641SAndroid Build Coastguard Worker #elif defined(OS_LINUX)
98*635a8641SAndroid Build Coastguard Worker auto set_result = sched_setaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
99*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(0, set_result);
100*635a8641SAndroid Build Coastguard Worker #endif
101*635a8641SAndroid Build Coastguard Worker }
102*635a8641SAndroid Build Coastguard Worker
MojoPerfTestClient()103*635a8641SAndroid Build Coastguard Worker MojoPerfTestClient::MojoPerfTestClient()
104*635a8641SAndroid Build Coastguard Worker : listener_(new ChannelReflectorListener()) {
105*635a8641SAndroid Build Coastguard Worker mojo::core::test::MultiprocessTestHelper::ChildSetup();
106*635a8641SAndroid Build Coastguard Worker }
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker MojoPerfTestClient::~MojoPerfTestClient() = default;
109*635a8641SAndroid Build Coastguard Worker
Run(MojoHandle handle)110*635a8641SAndroid Build Coastguard Worker int MojoPerfTestClient::Run(MojoHandle handle) {
111*635a8641SAndroid Build Coastguard Worker handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle));
112*635a8641SAndroid Build Coastguard Worker LockThreadAffinity thread_locker(kSharedCore);
113*635a8641SAndroid Build Coastguard Worker
114*635a8641SAndroid Build Coastguard Worker base::RunLoop run_loop;
115*635a8641SAndroid Build Coastguard Worker std::unique_ptr<ChannelProxy> channel = IPC::ChannelProxy::Create(
116*635a8641SAndroid Build Coastguard Worker handle_.release(), Channel::MODE_CLIENT, listener_.get(),
117*635a8641SAndroid Build Coastguard Worker GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get());
118*635a8641SAndroid Build Coastguard Worker listener_->Init(channel.get(), run_loop.QuitWhenIdleClosure());
119*635a8641SAndroid Build Coastguard Worker run_loop.Run();
120*635a8641SAndroid Build Coastguard Worker return 0;
121*635a8641SAndroid Build Coastguard Worker }
122*635a8641SAndroid Build Coastguard Worker
ReflectorImpl(mojo::ScopedMessagePipeHandle handle,const base::Closure & quit_closure)123*635a8641SAndroid Build Coastguard Worker ReflectorImpl::ReflectorImpl(mojo::ScopedMessagePipeHandle handle,
124*635a8641SAndroid Build Coastguard Worker const base::Closure& quit_closure)
125*635a8641SAndroid Build Coastguard Worker : quit_closure_(quit_closure),
126*635a8641SAndroid Build Coastguard Worker binding_(this, IPC::mojom::ReflectorRequest(std::move(handle))) {}
127*635a8641SAndroid Build Coastguard Worker
~ReflectorImpl()128*635a8641SAndroid Build Coastguard Worker ReflectorImpl::~ReflectorImpl() {
129*635a8641SAndroid Build Coastguard Worker ignore_result(binding_.Unbind().PassMessagePipe().release());
130*635a8641SAndroid Build Coastguard Worker }
131*635a8641SAndroid Build Coastguard Worker
Ping(const std::string & value,PingCallback callback)132*635a8641SAndroid Build Coastguard Worker void ReflectorImpl::Ping(const std::string& value, PingCallback callback) {
133*635a8641SAndroid Build Coastguard Worker std::move(callback).Run(value);
134*635a8641SAndroid Build Coastguard Worker }
135*635a8641SAndroid Build Coastguard Worker
SyncPing(const std::string & value,PingCallback callback)136*635a8641SAndroid Build Coastguard Worker void ReflectorImpl::SyncPing(const std::string& value, PingCallback callback) {
137*635a8641SAndroid Build Coastguard Worker std::move(callback).Run(value);
138*635a8641SAndroid Build Coastguard Worker }
139*635a8641SAndroid Build Coastguard Worker
Quit()140*635a8641SAndroid Build Coastguard Worker void ReflectorImpl::Quit() {
141*635a8641SAndroid Build Coastguard Worker if (quit_closure_)
142*635a8641SAndroid Build Coastguard Worker quit_closure_.Run();
143*635a8641SAndroid Build Coastguard Worker }
144*635a8641SAndroid Build Coastguard Worker
145*635a8641SAndroid Build Coastguard Worker } // namespace IPC
146