[go: nahoru, domu]

blob: 4a5915a3f94b54984f6a3d8b530da3c5301854ab [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// 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 <tuple>
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.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<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_(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<DWORD_PTR>(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<ChannelProxy> channel = IPC::ChannelProxy::Create(
handle_.release(), Channel::MODE_CLIENT, listener_.get(),
GetIOThreadTaskRunner(),
base::SingleThreadTaskRunner::GetCurrentDefault());
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<IPC::mojom::Reflector>(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