Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1132)

Side by Side Diff: mojo/system/raw_channel_posix.cc

Issue 226263005: Mojo: Abstract out write/writev vs send/sendmsg (for Unix domain sockets). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mojo/mojo.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/system/raw_channel.h" 5 #include "mojo/system/raw_channel.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <sys/types.h>
10 #include <sys/uio.h> 8 #include <sys/uio.h>
11 #include <unistd.h> 9 #include <unistd.h>
12 10
13 #include <algorithm> 11 #include <algorithm>
14 12
15 #include "base/basictypes.h" 13 #include "base/basictypes.h"
16 #include "base/bind.h" 14 #include "base/bind.h"
17 #include "base/compiler_specific.h" 15 #include "base/compiler_specific.h"
18 #include "base/location.h" 16 #include "base/location.h"
19 #include "base/logging.h" 17 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/weak_ptr.h" 19 #include "base/memory/weak_ptr.h"
22 #include "base/message_loop/message_loop.h" 20 #include "base/message_loop/message_loop.h"
23 #include "base/posix/eintr_wrapper.h" 21 #include "base/posix/eintr_wrapper.h"
24 #include "base/synchronization/lock.h" 22 #include "base/synchronization/lock.h"
25 #include "build/build_config.h" 23 #include "mojo/embedder/platform_channel_utils_posix.h"
26 #include "mojo/embedder/platform_handle.h" 24 #include "mojo/embedder/platform_handle.h"
27 25
28 namespace mojo { 26 namespace mojo {
29 namespace system { 27 namespace system {
30 28
31 namespace { 29 namespace {
32 30
33 class RawChannelPosix : public RawChannel, 31 class RawChannelPosix : public RawChannel,
34 public base::MessageLoopForIO::Watcher { 32 public base::MessageLoopForIO::Watcher {
35 public: 33 public:
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 write_lock().AssertAcquired(); 136 write_lock().AssertAcquired();
139 137
140 DCHECK(!pending_write_); 138 DCHECK(!pending_write_);
141 139
142 std::vector<WriteBuffer::Buffer> buffers; 140 std::vector<WriteBuffer::Buffer> buffers;
143 write_buffer_no_lock()->GetBuffers(&buffers); 141 write_buffer_no_lock()->GetBuffers(&buffers);
144 DCHECK(!buffers.empty()); 142 DCHECK(!buffers.empty());
145 143
146 ssize_t write_result = -1; 144 ssize_t write_result = -1;
147 if (buffers.size() == 1) { 145 if (buffers.size() == 1) {
148 write_result = HANDLE_EINTR( 146 write_result = embedder::PlatformChannelWrite(fd_.get(), buffers[0].addr,
149 write(fd_.get().fd, buffers[0].addr, buffers[0].size)); 147 buffers[0].size);
150 } else { 148 } else {
151 // Note that using |writev()|/|sendmsg()| is measurably slower than using 149 // Note that using |writev()|/|sendmsg()| is measurably slower than using
152 // |write()| -- at least in a microbenchmark -- but much faster than using 150 // |write()| -- at least in a microbenchmark -- but much faster than using
153 // multiple |write()|s. (|sendmsg()| is also measurably slightly slower than 151 // multiple |write()|s. (|sendmsg()| is also measurably slightly slower than
154 // |writev()|.) 152 // |writev()|.)
155 // 153 //
156 // On Linux, we need to use |sendmsg()| since it's the only way to suppress 154 // On Linux, we need to use |sendmsg()| since it's the only way to suppress
157 // |SIGPIPE| (on Mac, this is suppressed on the socket itself using 155 // |SIGPIPE| (on Mac, this is suppressed on the socket itself using
158 // |setsockopt()|, since |MSG_NOSIGNAL| is not supported -- see 156 // |setsockopt()|, since |MSG_NOSIGNAL| is not supported -- see
159 // platform_channel_pair_posix.cc). 157 // platform_channel_pair_posix.cc).
160 const size_t kMaxBufferCount = 10; 158 const size_t kMaxBufferCount = 10;
161 iovec iov[kMaxBufferCount]; 159 iovec iov[kMaxBufferCount];
162 size_t buffer_count = std::min(buffers.size(), kMaxBufferCount); 160 size_t buffer_count = std::min(buffers.size(), kMaxBufferCount);
163 161
164 for (size_t i = 0; i < buffer_count; ++i) { 162 for (size_t i = 0; i < buffer_count; ++i) {
165 iov[i].iov_base = const_cast<char*>(buffers[i].addr); 163 iov[i].iov_base = const_cast<char*>(buffers[i].addr);
166 iov[i].iov_len = buffers[i].size; 164 iov[i].iov_len = buffers[i].size;
167 } 165 }
168 166
169 // On Mac, we can use |writev()|, which is slightly faster, but on Linux we 167 write_result = embedder::PlatformChannelWritev(fd_.get(), iov,
170 // need to use |sendmsg()|. See comment above. 168 buffer_count);
171 // TODO(vtl): We should have an actual test that |SIGPIPE| is suppressed for
172 // |RawChannelPosix|, since it has to be suppressed at "use" time on Linux.
173 // Or maybe I should abstract out |write()|/|send()| and
174 // |writev()|/|sendmsg()|. crbug.com/356195
175 #if defined(OS_MACOSX)
176 write_result = HANDLE_EINTR(writev(fd_.get().fd, iov, buffer_count));
177 #else
178 struct msghdr msg = {};
179 msg.msg_iov = iov;
180 msg.msg_iovlen = buffer_count;
181 write_result = HANDLE_EINTR(sendmsg(fd_.get().fd, &msg, MSG_NOSIGNAL));
182 #endif
183 } 169 }
184 170
185 if (write_result >= 0) { 171 if (write_result >= 0) {
186 *bytes_written = static_cast<size_t>(write_result); 172 *bytes_written = static_cast<size_t>(write_result);
187 return IO_SUCCEEDED; 173 return IO_SUCCEEDED;
188 } 174 }
189 175
190 if (errno != EAGAIN && errno != EWOULDBLOCK) { 176 if (errno != EAGAIN && errno != EWOULDBLOCK) {
191 PLOG(ERROR) << "write of size " 177 PLOG(ERROR) << "write of size "
192 << write_buffer_no_lock()->GetTotalBytesToWrite(); 178 << write_buffer_no_lock()->GetTotalBytesToWrite();
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 316
331 // Static factory method declared in raw_channel.h. 317 // Static factory method declared in raw_channel.h.
332 // static 318 // static
333 scoped_ptr<RawChannel> RawChannel::Create( 319 scoped_ptr<RawChannel> RawChannel::Create(
334 embedder::ScopedPlatformHandle handle) { 320 embedder::ScopedPlatformHandle handle) {
335 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); 321 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass()));
336 } 322 }
337 323
338 } // namespace system 324 } // namespace system
339 } // namespace mojo 325 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/mojo.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698