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

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

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

Powered by Google App Engine
This is Rietveld 408576698