| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |