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