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

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

Issue 430473004: Reland r285211: "Debugging RawChannelWin: replace DCHECK with CHECK and record write stats." (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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/system/raw_channel.cc ('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 <windows.h> 7 #include <windows.h>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/debug/alias.h"
12 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
13 #include "base/location.h" 14 #include "base/location.h"
14 #include "base/logging.h" 15 #include "base/logging.h"
15 #include "base/macros.h" 16 #include "base/macros.h"
16 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
18 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
19 #include "base/win/windows_version.h" 20 #include "base/win/windows_version.h"
20 #include "mojo/embedder/platform_handle.h" 21 #include "mojo/embedder/platform_handle.h"
21 22
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 // RawChannelIOHandler receives OS notifications for I/O completion. It must 82 // RawChannelIOHandler receives OS notifications for I/O completion. It must
82 // be created on the I/O thread. 83 // be created on the I/O thread.
83 // 84 //
84 // It manages its own destruction. Destruction happens on the I/O thread when 85 // It manages its own destruction. Destruction happens on the I/O thread when
85 // all the following conditions are satisfied: 86 // all the following conditions are satisfied:
86 // - |DetachFromOwnerNoLock()| has been called; 87 // - |DetachFromOwnerNoLock()| has been called;
87 // - there is no pending read; 88 // - there is no pending read;
88 // - there is no pending write. 89 // - there is no pending write.
89 class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler { 90 class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler {
90 public: 91 public:
92 // TODO(yzshen): This is for debugging http://crbug.com/385795.
93 // This code should be removed once the issue is fixed or nothing is
94 // revealed by it. (No later than Aug 1, 2014.)
95 struct WriteStats {
96 WriteStats()
97 : write_no_lock_call(0),
98 schedule_write_no_lock_call(0),
99 os_write_call(0),
100 os_write_pending(0),
101 os_write_failure(0),
102 task_posted_by_schedule_write(0),
103 write_completion(0),
104 write_completion_failure(0) {}
105
106 uint32_t write_no_lock_call;
107 uint32_t schedule_write_no_lock_call;
108 uint32_t os_write_call;
109 uint32_t os_write_pending;
110 uint32_t os_write_failure;
111 uint32_t task_posted_by_schedule_write;
112 uint32_t write_completion;
113 uint32_t write_completion_failure;
114 };
115
91 RawChannelIOHandler(RawChannelWin* owner, 116 RawChannelIOHandler(RawChannelWin* owner,
92 embedder::ScopedPlatformHandle handle); 117 embedder::ScopedPlatformHandle handle);
93 118
94 HANDLE handle() const { return handle_.get().handle; } 119 HANDLE handle() const { return handle_.get().handle; }
95 120
96 // The following methods are only called by the owner on the I/O thread. 121 // The following methods are only called by the owner on the I/O thread.
97 bool pending_read() const; 122 bool pending_read() const;
98 base::MessageLoopForIO::IOContext* read_context(); 123 base::MessageLoopForIO::IOContext* read_context();
99 // Instructs the object to wait for an |OnIOCompleted()| notification. 124 // Instructs the object to wait for an |OnIOCompleted()| notification.
100 void OnPendingReadStarted(); 125 void OnPendingReadStarted();
101 126
102 // The following methods are only called by the owner under 127 // The following methods are only called by the owner under
103 // |owner_->write_lock()|. 128 // |owner_->write_lock()|.
104 bool pending_write_no_lock() const; 129 bool pending_write_no_lock() const;
105 base::MessageLoopForIO::IOContext* write_context_no_lock(); 130 base::MessageLoopForIO::IOContext* write_context_no_lock();
106 // Instructs the object to wait for an |OnIOCompleted()| notification. 131 // Instructs the object to wait for an |OnIOCompleted()| notification.
107 void OnPendingWriteStartedNoLock(); 132 void OnPendingWriteStartedNoLock();
133 WriteStats* write_stats_no_lock();
108 134
109 // |base::MessageLoopForIO::IOHandler| implementation: 135 // |base::MessageLoopForIO::IOHandler| implementation:
110 // Must be called on the I/O thread. It could be called before or after 136 // Must be called on the I/O thread. It could be called before or after
111 // detached from the owner. 137 // detached from the owner.
112 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, 138 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
113 DWORD bytes_transferred, 139 DWORD bytes_transferred,
114 DWORD error) OVERRIDE; 140 DWORD error) OVERRIDE;
115 141
116 // Must be called on the I/O thread under |owner_->write_lock()|. 142 // Must be called on the I/O thread under |owner_->write_lock()|.
117 // After this call, the owner must not make any further calls on this 143 // After this call, the owner must not make any further calls on this
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 175
150 bool pending_read_; 176 bool pending_read_;
151 base::MessageLoopForIO::IOContext read_context_; 177 base::MessageLoopForIO::IOContext read_context_;
152 178
153 // The following members must be used under |owner_->write_lock()| while the 179 // The following members must be used under |owner_->write_lock()| while the
154 // object is still attached to the owner, and only on the I/O thread 180 // object is still attached to the owner, and only on the I/O thread
155 // afterwards. 181 // afterwards.
156 bool pending_write_; 182 bool pending_write_;
157 base::MessageLoopForIO::IOContext write_context_; 183 base::MessageLoopForIO::IOContext write_context_;
158 184
185 WriteStats write_stats_;
186
159 DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler); 187 DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler);
160 }; 188 };
161 189
162 // |RawChannel| private methods: 190 // |RawChannel| private methods:
163 virtual IOResult Read(size_t* bytes_read) OVERRIDE; 191 virtual IOResult Read(size_t* bytes_read) OVERRIDE;
164 virtual IOResult ScheduleRead() OVERRIDE; 192 virtual IOResult ScheduleRead() OVERRIDE;
165 virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( 193 virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles(
166 size_t num_platform_handles, 194 size_t num_platform_handles,
167 const void* platform_handle_table) OVERRIDE; 195 const void* platform_handle_table) OVERRIDE;
168 virtual IOResult WriteNoLock(size_t* platform_handles_written, 196 virtual IOResult WriteNoLock(size_t* platform_handles_written,
(...skipping 23 matching lines...) Expand all
192 pending_write_(false) { 220 pending_write_(false) {
193 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); 221 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
194 read_context_.handler = this; 222 read_context_.handler = this;
195 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); 223 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped));
196 write_context_.handler = this; 224 write_context_.handler = this;
197 225
198 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); 226 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this);
199 } 227 }
200 228
201 RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() { 229 RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() {
202 DCHECK(ShouldSelfDestruct()); 230 CHECK(ShouldSelfDestruct());
231
232 VLOG(4) << "write_no_lock_call: " << write_stats_.write_no_lock_call << "\n"
233 << "schedule_write_no_lock_call: "
234 << write_stats_.schedule_write_no_lock_call << "\n"
235 << "os_write_call: " << write_stats_.os_write_call << "\n"
236 << "os_write_pending: " << write_stats_.os_write_pending << "\n"
237 << "os_write_failure: " << write_stats_.os_write_failure << "\n"
238 << "task_posted_by_schedule_write: "
239 << write_stats_.task_posted_by_schedule_write << "\n"
240 << "write_completion: " << write_stats_.write_completion << "\n"
241 << "write_completion_failure: "
242 << write_stats_.write_completion_failure << "\n";
203 } 243 }
204 244
205 bool RawChannelWin::RawChannelIOHandler::pending_read() const { 245 bool RawChannelWin::RawChannelIOHandler::pending_read() const {
206 DCHECK(owner_); 246 CHECK(owner_);
207 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); 247 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
208 return pending_read_; 248 return pending_read_;
209 } 249 }
210 250
211 base::MessageLoopForIO::IOContext* 251 base::MessageLoopForIO::IOContext*
212 RawChannelWin::RawChannelIOHandler::read_context() { 252 RawChannelWin::RawChannelIOHandler::read_context() {
213 DCHECK(owner_); 253 CHECK(owner_);
214 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); 254 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
215 return &read_context_; 255 return &read_context_;
216 } 256 }
217 257
218 void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() { 258 void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() {
219 DCHECK(owner_); 259 CHECK(owner_);
220 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); 260 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
221 DCHECK(!pending_read_); 261 CHECK(!pending_read_);
222 pending_read_ = true; 262 pending_read_ = true;
223 } 263 }
224 264
225 bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const { 265 bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const {
226 DCHECK(owner_); 266 CHECK(owner_);
227 owner_->write_lock().AssertAcquired(); 267 owner_->write_lock().AssertAcquired();
228 return pending_write_; 268 return pending_write_;
229 } 269 }
230 270
231 base::MessageLoopForIO::IOContext* 271 base::MessageLoopForIO::IOContext*
232 RawChannelWin::RawChannelIOHandler::write_context_no_lock() { 272 RawChannelWin::RawChannelIOHandler::write_context_no_lock() {
233 DCHECK(owner_); 273 CHECK(owner_);
234 owner_->write_lock().AssertAcquired(); 274 owner_->write_lock().AssertAcquired();
235 return &write_context_; 275 return &write_context_;
236 } 276 }
237 277
238 void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock() { 278 void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock() {
239 DCHECK(owner_); 279 CHECK(owner_);
240 owner_->write_lock().AssertAcquired(); 280 owner_->write_lock().AssertAcquired();
241 DCHECK(!pending_write_); 281 CHECK(!pending_write_);
242 pending_write_ = true; 282 pending_write_ = true;
243 } 283 }
244 284
285 RawChannelWin::RawChannelIOHandler::WriteStats*
286 RawChannelWin::RawChannelIOHandler::write_stats_no_lock() {
287 CHECK(owner_);
288 owner_->write_lock().AssertAcquired();
289 return &write_stats_;
290 }
291
245 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( 292 void RawChannelWin::RawChannelIOHandler::OnIOCompleted(
246 base::MessageLoopForIO::IOContext* context, 293 base::MessageLoopForIO::IOContext* context,
247 DWORD bytes_transferred, 294 DWORD bytes_transferred,
248 DWORD error) { 295 DWORD error) {
249 DCHECK(!owner_ || 296 CHECK(!owner_ ||
250 base::MessageLoop::current() == owner_->message_loop_for_io()); 297 base::MessageLoop::current() == owner_->message_loop_for_io());
251 298
252 { 299 {
253 // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they 300 // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they
254 // result in a call to |Shutdown()|). 301 // result in a call to |Shutdown()|).
255 base::AutoReset<bool> resetter(&suppress_self_destruct_, true); 302 base::AutoReset<bool> resetter(&suppress_self_destruct_, true);
256 303
257 if (context == &read_context_) 304 if (context == &read_context_)
258 OnReadCompleted(bytes_transferred, error); 305 OnReadCompleted(bytes_transferred, error);
259 else if (context == &write_context_) 306 else if (context == &write_context_)
260 OnWriteCompleted(bytes_transferred, error); 307 OnWriteCompleted(bytes_transferred, error);
261 else 308 else
262 NOTREACHED(); 309 NOTREACHED();
263 } 310 }
264 311
265 if (ShouldSelfDestruct()) 312 if (ShouldSelfDestruct())
266 delete this; 313 delete this;
267 } 314 }
268 315
269 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( 316 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock(
270 scoped_ptr<ReadBuffer> read_buffer, 317 scoped_ptr<ReadBuffer> read_buffer,
271 scoped_ptr<WriteBuffer> write_buffer) { 318 scoped_ptr<WriteBuffer> write_buffer) {
272 DCHECK(owner_); 319 CHECK(owner_);
273 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); 320 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io());
274 owner_->write_lock().AssertAcquired(); 321 owner_->write_lock().AssertAcquired();
275 322
276 // If read/write is pending, we have to retain the corresponding buffer. 323 // If read/write is pending, we have to retain the corresponding buffer.
277 if (pending_read_) 324 if (pending_read_)
278 preserved_read_buffer_after_detach_ = read_buffer.Pass(); 325 preserved_read_buffer_after_detach_ = read_buffer.Pass();
279 if (pending_write_) 326 if (pending_write_)
280 preserved_write_buffer_after_detach_ = write_buffer.Pass(); 327 preserved_write_buffer_after_detach_ = write_buffer.Pass();
281 328
282 owner_ = NULL; 329 owner_ = NULL;
283 if (ShouldSelfDestruct()) 330 if (ShouldSelfDestruct())
284 delete this; 331 delete this;
285 } 332 }
286 333
287 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { 334 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const {
288 if (owner_ || suppress_self_destruct_) 335 if (owner_ || suppress_self_destruct_)
289 return false; 336 return false;
290 337
291 // Note: Detached, hence no lock needed for |pending_write_|. 338 // Note: Detached, hence no lock needed for |pending_write_|.
292 return !pending_read_ && !pending_write_; 339 return !pending_read_ && !pending_write_;
293 } 340 }
294 341
295 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, 342 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read,
296 DWORD error) { 343 DWORD error) {
297 DCHECK(!owner_ || 344 CHECK(!owner_ ||
298 base::MessageLoop::current() == owner_->message_loop_for_io()); 345 base::MessageLoop::current() == owner_->message_loop_for_io());
299 DCHECK(suppress_self_destruct_); 346 CHECK(suppress_self_destruct_);
300 347
301 CHECK(pending_read_); 348 CHECK(pending_read_);
302 pending_read_ = false; 349 pending_read_ = false;
303 if (!owner_) 350 if (!owner_)
304 return; 351 return;
305 352
306 if (error != ERROR_SUCCESS) { 353 if (error != ERROR_SUCCESS) {
307 DCHECK_EQ(bytes_read, 0u); 354 CHECK_EQ(bytes_read, 0u);
308 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) 355 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE)
309 << "ReadFile: " << logging::SystemErrorCodeToString(error); 356 << "ReadFile: " << logging::SystemErrorCodeToString(error);
310 owner_->OnReadCompleted(false, 0); 357 owner_->OnReadCompleted(false, 0);
311 } else { 358 } else {
312 DCHECK_GT(bytes_read, 0u); 359 CHECK_GT(bytes_read, 0u);
313 owner_->OnReadCompleted(true, bytes_read); 360 owner_->OnReadCompleted(true, bytes_read);
314 } 361 }
315 } 362 }
316 363
317 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, 364 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written,
318 DWORD error) { 365 DWORD error) {
319 DCHECK(!owner_ || 366 CHECK(!owner_ ||
320 base::MessageLoop::current() == owner_->message_loop_for_io()); 367 base::MessageLoop::current() == owner_->message_loop_for_io());
321 DCHECK(suppress_self_destruct_); 368 CHECK(suppress_self_destruct_);
369
370 WriteStats stack_copy;
371 base::debug::Alias(&stack_copy);
322 372
323 if (!owner_) { 373 if (!owner_) {
324 // No lock needed. 374 // No lock needed.
375
376 write_stats_.write_completion++;
377 if (error != ERROR_SUCCESS)
378 write_stats_.write_completion_failure++;
379 stack_copy = write_stats_;
380
325 CHECK(pending_write_); 381 CHECK(pending_write_);
326 pending_write_ = false; 382 pending_write_ = false;
327 return; 383 return;
328 } 384 }
329 385
330 { 386 {
331 base::AutoLock locker(owner_->write_lock()); 387 base::AutoLock locker(owner_->write_lock());
388
389 write_stats_.write_completion++;
390 if (error != ERROR_SUCCESS)
391 write_stats_.write_completion_failure++;
392 stack_copy = write_stats_;
393
332 CHECK(pending_write_); 394 CHECK(pending_write_);
333 pending_write_ = false; 395 pending_write_ = false;
334 } 396 }
335 397
336 if (error != ERROR_SUCCESS) { 398 if (error != ERROR_SUCCESS) {
337 LOG(ERROR) << "WriteFile: " << logging::SystemErrorCodeToString(error); 399 LOG(ERROR) << "WriteFile: " << logging::SystemErrorCodeToString(error);
338 owner_->OnWriteCompleted(false, 0, 0); 400 owner_->OnWriteCompleted(false, 0, 0);
339 } else { 401 } else {
340 owner_->OnWriteCompleted(true, 0, bytes_written); 402 owner_->OnWriteCompleted(true, 0, bytes_written);
341 } 403 }
342 } 404 }
343 405
344 RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle) 406 RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle)
345 : handle_(handle.Pass()), 407 : handle_(handle.Pass()),
346 io_handler_(NULL), 408 io_handler_(NULL),
347 skip_completion_port_on_success_( 409 skip_completion_port_on_success_(
348 g_vista_or_higher_functions.Get().is_vista_or_higher()) { 410 g_vista_or_higher_functions.Get().is_vista_or_higher()) {
349 DCHECK(handle_.is_valid()); 411 CHECK(handle_.is_valid());
350 } 412 }
351 413
352 RawChannelWin::~RawChannelWin() { 414 RawChannelWin::~RawChannelWin() {
353 DCHECK(!io_handler_); 415 CHECK(!io_handler_);
354 } 416 }
355 417
356 size_t RawChannelWin::GetSerializedPlatformHandleSize() const { 418 size_t RawChannelWin::GetSerializedPlatformHandleSize() const {
357 // TODO(vtl): Implement. 419 // TODO(vtl): Implement.
358 return 0; 420 return 0;
359 } 421 }
360 422
361 RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) { 423 RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) {
362 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); 424 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
363 DCHECK(io_handler_); 425 CHECK(io_handler_);
364 DCHECK(!io_handler_->pending_read()); 426 CHECK(!io_handler_->pending_read());
365 427
366 char* buffer = NULL; 428 char* buffer = NULL;
367 size_t bytes_to_read = 0; 429 size_t bytes_to_read = 0;
368 read_buffer()->GetBuffer(&buffer, &bytes_to_read); 430 read_buffer()->GetBuffer(&buffer, &bytes_to_read);
369 431
370 DWORD bytes_read_dword = 0; 432 DWORD bytes_read_dword = 0;
371 BOOL result = ReadFile(io_handler_->handle(), 433 BOOL result = ReadFile(io_handler_->handle(),
372 buffer, 434 buffer,
373 static_cast<DWORD>(bytes_to_read), 435 static_cast<DWORD>(bytes_to_read),
374 &bytes_read_dword, 436 &bytes_read_dword,
375 &io_handler_->read_context()->overlapped); 437 &io_handler_->read_context()->overlapped);
376 if (!result) { 438 if (!result) {
377 DCHECK_EQ(bytes_read_dword, 0u); 439 CHECK_EQ(bytes_read_dword, 0u);
378 DWORD error = GetLastError(); 440 DWORD error = GetLastError();
379 if (error != ERROR_IO_PENDING) { 441 if (error != ERROR_IO_PENDING) {
380 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) 442 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE)
381 << "ReadFile: " << logging::SystemErrorCodeToString(error); 443 << "ReadFile: " << logging::SystemErrorCodeToString(error);
382 return IO_FAILED; 444 return IO_FAILED;
383 } 445 }
384 } 446 }
385 447
386 if (result && skip_completion_port_on_success_) { 448 if (result && skip_completion_port_on_success_) {
387 *bytes_read = bytes_read_dword; 449 *bytes_read = bytes_read_dword;
388 return IO_SUCCEEDED; 450 return IO_SUCCEEDED;
389 } 451 }
390 452
391 // If the read is pending or the read has succeeded but we don't skip 453 // If the read is pending or the read has succeeded but we don't skip
392 // completion port on success, instruct |io_handler_| to wait for the 454 // completion port on success, instruct |io_handler_| to wait for the
393 // completion packet. 455 // completion packet.
394 // 456 //
395 // TODO(yzshen): It seems there isn't document saying that all error cases 457 // TODO(yzshen): It seems there isn't document saying that all error cases
396 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion 458 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion
397 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| 459 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()|
398 // will crash so we will learn about it. 460 // will crash so we will learn about it.
399 461
400 io_handler_->OnPendingReadStarted(); 462 io_handler_->OnPendingReadStarted();
401 return IO_PENDING; 463 return IO_PENDING;
402 } 464 }
403 465
404 RawChannel::IOResult RawChannelWin::ScheduleRead() { 466 RawChannel::IOResult RawChannelWin::ScheduleRead() {
405 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); 467 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
406 DCHECK(io_handler_); 468 CHECK(io_handler_);
407 DCHECK(!io_handler_->pending_read()); 469 CHECK(!io_handler_->pending_read());
408 470
409 size_t bytes_read = 0; 471 size_t bytes_read = 0;
410 IOResult io_result = Read(&bytes_read); 472 IOResult io_result = Read(&bytes_read);
411 if (io_result == IO_SUCCEEDED) { 473 if (io_result == IO_SUCCEEDED) {
412 DCHECK(skip_completion_port_on_success_); 474 CHECK(skip_completion_port_on_success_);
413 475
414 // We have finished reading successfully. Queue a notification manually. 476 // We have finished reading successfully. Queue a notification manually.
415 io_handler_->OnPendingReadStarted(); 477 io_handler_->OnPendingReadStarted();
416 // |io_handler_| won't go away before the task is run, so it is safe to use 478 // |io_handler_| won't go away before the task is run, so it is safe to use
417 // |base::Unretained()|. 479 // |base::Unretained()|.
418 message_loop_for_io()->PostTask( 480 message_loop_for_io()->PostTask(
419 FROM_HERE, 481 FROM_HERE,
420 base::Bind(&RawChannelIOHandler::OnIOCompleted, 482 base::Bind(&RawChannelIOHandler::OnIOCompleted,
421 base::Unretained(io_handler_), 483 base::Unretained(io_handler_),
422 base::Unretained(io_handler_->read_context()), 484 base::Unretained(io_handler_->read_context()),
(...skipping 11 matching lines...) Expand all
434 // TODO(vtl): Implement. 496 // TODO(vtl): Implement.
435 NOTIMPLEMENTED(); 497 NOTIMPLEMENTED();
436 return embedder::ScopedPlatformHandleVectorPtr(); 498 return embedder::ScopedPlatformHandleVectorPtr();
437 } 499 }
438 500
439 RawChannel::IOResult RawChannelWin::WriteNoLock( 501 RawChannel::IOResult RawChannelWin::WriteNoLock(
440 size_t* platform_handles_written, 502 size_t* platform_handles_written,
441 size_t* bytes_written) { 503 size_t* bytes_written) {
442 write_lock().AssertAcquired(); 504 write_lock().AssertAcquired();
443 505
444 DCHECK(io_handler_); 506 RawChannelIOHandler::WriteStats stack_copy(
445 DCHECK(!io_handler_->pending_write_no_lock()); 507 *io_handler_->write_stats_no_lock());
508 base::debug::Alias(&stack_copy);
509
510 io_handler_->write_stats_no_lock()->write_no_lock_call++;
511 stack_copy.write_no_lock_call++;
512
513 CHECK(io_handler_);
514 CHECK(!io_handler_->pending_write_no_lock());
446 515
447 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { 516 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) {
448 // TODO(vtl): Implement. 517 // TODO(vtl): Implement.
449 NOTIMPLEMENTED(); 518 NOTIMPLEMENTED();
450 } 519 }
451 520
452 std::vector<WriteBuffer::Buffer> buffers; 521 std::vector<WriteBuffer::Buffer> buffers;
453 write_buffer_no_lock()->GetBuffers(&buffers); 522 write_buffer_no_lock()->GetBuffers(&buffers);
454 DCHECK(!buffers.empty()); 523 CHECK(!buffers.empty());
524
525 io_handler_->write_stats_no_lock()->os_write_call++;
526 stack_copy.os_write_call++;
455 527
456 // TODO(yzshen): Handle multi-segment writes more efficiently. 528 // TODO(yzshen): Handle multi-segment writes more efficiently.
457 DWORD bytes_written_dword = 0; 529 DWORD bytes_written_dword = 0;
458 BOOL result = WriteFile(io_handler_->handle(), 530 BOOL result = WriteFile(io_handler_->handle(),
459 buffers[0].addr, 531 buffers[0].addr,
460 static_cast<DWORD>(buffers[0].size), 532 static_cast<DWORD>(buffers[0].size),
461 &bytes_written_dword, 533 &bytes_written_dword,
462 &io_handler_->write_context_no_lock()->overlapped); 534 &io_handler_->write_context_no_lock()->overlapped);
463 if (!result && GetLastError() != ERROR_IO_PENDING) { 535
464 PLOG(ERROR) << "WriteFile"; 536 if (!result) {
465 return IO_FAILED; 537 if (GetLastError() == ERROR_IO_PENDING) {
538 io_handler_->write_stats_no_lock()->os_write_pending++;
539 stack_copy.os_write_pending++;
540 } else {
541 io_handler_->write_stats_no_lock()->os_write_failure++;
542 stack_copy.os_write_failure++;
543
544 PLOG(ERROR) << "WriteFile";
545 return IO_FAILED;
546 }
466 } 547 }
467 548
468 if (result && skip_completion_port_on_success_) { 549 if (result && skip_completion_port_on_success_) {
469 *platform_handles_written = 0; 550 *platform_handles_written = 0;
470 *bytes_written = bytes_written_dword; 551 *bytes_written = bytes_written_dword;
471 return IO_SUCCEEDED; 552 return IO_SUCCEEDED;
472 } 553 }
473 554
474 // If the write is pending or the write has succeeded but we don't skip 555 // If the write is pending or the write has succeeded but we don't skip
475 // completion port on success, instruct |io_handler_| to wait for the 556 // completion port on success, instruct |io_handler_| to wait for the
476 // completion packet. 557 // completion packet.
477 // 558 //
478 // TODO(yzshen): it seems there isn't document saying that all error cases 559 // TODO(yzshen): it seems there isn't document saying that all error cases
479 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion 560 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion
480 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| 561 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()|
481 // will crash so we will learn about it. 562 // will crash so we will learn about it.
482 563
483 io_handler_->OnPendingWriteStartedNoLock(); 564 io_handler_->OnPendingWriteStartedNoLock();
484 return IO_PENDING; 565 return IO_PENDING;
485 } 566 }
486 567
487 RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() { 568 RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() {
488 write_lock().AssertAcquired(); 569 write_lock().AssertAcquired();
489 570
490 DCHECK(io_handler_); 571 RawChannelIOHandler::WriteStats stack_copy(
491 DCHECK(!io_handler_->pending_write_no_lock()); 572 *io_handler_->write_stats_no_lock());
573 base::debug::Alias(&stack_copy);
574
575 io_handler_->write_stats_no_lock()->schedule_write_no_lock_call++;
576 stack_copy.schedule_write_no_lock_call++;
577
578 CHECK(io_handler_);
579 CHECK(!io_handler_->pending_write_no_lock());
492 580
493 // TODO(vtl): Do something with |platform_handles_written|. 581 // TODO(vtl): Do something with |platform_handles_written|.
494 size_t platform_handles_written = 0; 582 size_t platform_handles_written = 0;
495 size_t bytes_written = 0; 583 size_t bytes_written = 0;
496 IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); 584 IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written);
497 if (io_result == IO_SUCCEEDED) { 585 if (io_result == IO_SUCCEEDED) {
498 DCHECK(skip_completion_port_on_success_); 586 CHECK(skip_completion_port_on_success_);
499 587
500 // We have finished writing successfully. Queue a notification manually. 588 // We have finished writing successfully. Queue a notification manually.
501 io_handler_->OnPendingWriteStartedNoLock(); 589 io_handler_->OnPendingWriteStartedNoLock();
590
591 io_handler_->write_stats_no_lock()->task_posted_by_schedule_write++;
592 stack_copy.task_posted_by_schedule_write++;
593
502 // |io_handler_| won't go away before that task is run, so it is safe to use 594 // |io_handler_| won't go away before that task is run, so it is safe to use
503 // |base::Unretained()|. 595 // |base::Unretained()|.
504 message_loop_for_io()->PostTask( 596 message_loop_for_io()->PostTask(
505 FROM_HERE, 597 FROM_HERE,
506 base::Bind(&RawChannelIOHandler::OnIOCompleted, 598 base::Bind(&RawChannelIOHandler::OnIOCompleted,
507 base::Unretained(io_handler_), 599 base::Unretained(io_handler_),
508 base::Unretained(io_handler_->write_context_no_lock()), 600 base::Unretained(io_handler_->write_context_no_lock()),
509 static_cast<DWORD>(bytes_written), 601 static_cast<DWORD>(bytes_written),
510 ERROR_SUCCESS)); 602 ERROR_SUCCESS));
511 return IO_PENDING; 603 return IO_PENDING;
512 } 604 }
513 605
514 return io_result; 606 return io_result;
515 } 607 }
516 608
517 bool RawChannelWin::OnInit() { 609 bool RawChannelWin::OnInit() {
518 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); 610 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
519 611
520 DCHECK(handle_.is_valid()); 612 CHECK(handle_.is_valid());
521 if (skip_completion_port_on_success_ && 613 if (skip_completion_port_on_success_ &&
522 !g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes( 614 !g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes(
523 handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { 615 handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
524 return false; 616 return false;
525 } 617 }
526 618
527 DCHECK(!io_handler_); 619 CHECK(!io_handler_);
528 io_handler_ = new RawChannelIOHandler(this, handle_.Pass()); 620 io_handler_ = new RawChannelIOHandler(this, handle_.Pass());
529 621
530 return true; 622 return true;
531 } 623 }
532 624
533 void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, 625 void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer,
534 scoped_ptr<WriteBuffer> write_buffer) { 626 scoped_ptr<WriteBuffer> write_buffer) {
535 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); 627 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io());
536 DCHECK(io_handler_); 628 CHECK(io_handler_);
537 629
538 write_lock().AssertAcquired(); 630 write_lock().AssertAcquired();
539 631
540 if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) { 632 if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) {
541 // |io_handler_| will be alive until pending read/write (if any) completes. 633 // |io_handler_| will be alive until pending read/write (if any) completes.
542 // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as 634 // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as
543 // soon as possible. 635 // soon as possible.
544 // Note: |CancelIo()| only cancels read/write requests started from this 636 // Note: |CancelIo()| only cancels read/write requests started from this
545 // thread. 637 // thread.
546 if (g_vista_or_higher_functions.Get().is_vista_or_higher()) 638 if (g_vista_or_higher_functions.Get().is_vista_or_higher())
(...skipping 12 matching lines...) Expand all
559 651
560 // Static factory method declared in raw_channel.h. 652 // Static factory method declared in raw_channel.h.
561 // static 653 // static
562 scoped_ptr<RawChannel> RawChannel::Create( 654 scoped_ptr<RawChannel> RawChannel::Create(
563 embedder::ScopedPlatformHandle handle) { 655 embedder::ScopedPlatformHandle handle) {
564 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); 656 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass()));
565 } 657 }
566 658
567 } // namespace system 659 } // namespace system
568 } // namespace mojo 660 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/system/raw_channel.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698