Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
| 6 #if defined(TARGET_OS_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
| 7 | 7 |
| 8 #include "bin/eventhandler.h" | 8 #include "bin/eventhandler.h" |
| 9 | 9 |
| 10 #include <process.h> // NOLINT | 10 #include <process.h> // NOLINT |
| 11 #include <winsock2.h> // NOLINT | 11 #include <winsock2.h> // NOLINT |
| 12 #include <ws2tcpip.h> // NOLINT | 12 #include <ws2tcpip.h> // NOLINT |
| 13 #include <mswsock.h> // NOLINT | 13 #include <mswsock.h> // NOLINT |
| 14 #include <io.h> // NOLINT | 14 #include <io.h> // NOLINT |
| 15 #include <fcntl.h> // NOLINT | 15 #include <fcntl.h> // NOLINT |
| 16 | 16 |
| 17 #include "bin/builtin.h" | 17 #include "bin/builtin.h" |
| 18 #include "bin/dartutils.h" | 18 #include "bin/dartutils.h" |
| 19 #include "bin/log.h" | 19 #include "bin/log.h" |
| 20 #include "bin/socket.h" | 20 #include "bin/socket.h" |
| 21 #include "bin/utils.h" | 21 #include "bin/utils.h" |
| 22 #include "platform/thread.h" | 22 #include "platform/thread.h" |
| 23 #include "vm/thread.h" | |
| 23 | 24 |
| 24 | 25 |
| 25 namespace dart { | 26 namespace dart { |
| 26 namespace bin { | 27 namespace bin { |
| 27 | 28 |
| 28 static const int kBufferSize = 64 * 1024; | 29 static const int kBufferSize = 64 * 1024; |
| 29 static const int kStdOverlappedBufferSize = 16 * 1024; | 30 static const int kStdOverlappedBufferSize = 16 * 1024; |
| 30 | 31 |
| 31 static const int kInfinityTimeout = -1; | 32 static const int kInfinityTimeout = -1; |
| 32 static const int kTimeoutId = -1; | 33 static const int kTimeoutId = -1; |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 552 ScopedLock lock(this); | 553 ScopedLock lock(this); |
| 553 if (data_ready_ == NULL) return 0; | 554 if (data_ready_ == NULL) return 0; |
| 554 num_bytes = data_ready_->Read(buffer, num_bytes); | 555 num_bytes = data_ready_->Read(buffer, num_bytes); |
| 555 if (data_ready_->IsEmpty()) { | 556 if (data_ready_->IsEmpty()) { |
| 556 OverlappedBuffer::DisposeBuffer(data_ready_); | 557 OverlappedBuffer::DisposeBuffer(data_ready_); |
| 557 data_ready_ = NULL; | 558 data_ready_ = NULL; |
| 558 } | 559 } |
| 559 return num_bytes; | 560 return num_bytes; |
| 560 } | 561 } |
| 561 | 562 |
| 562 | 563 |
|
Søren Gjesse
2013/10/02 08:49:22
Please add these static variables to the Windows E
Anders Johnsen
2013/10/02 10:16:59
Done.
| |
| 564 static Monitor* write_monitor = new Monitor(); | |
| 565 static bool write_thread_exists = false; | |
| 566 static bool write_thread_running = false; | |
| 567 static Handle* write_handle = NULL; | |
| 568 | |
| 563 static unsigned int __stdcall WriteFileThread(void* args) { | 569 static unsigned int __stdcall WriteFileThread(void* args) { |
| 564 Handle* handle = reinterpret_cast<Handle*>(args); | 570 MonitorLocker locker(write_monitor); |
| 565 handle->WriteSyncCompleteAsync(); | 571 write_thread_running = true; |
| 572 // Notify we have started. | |
| 573 locker.Notify(); | |
| 574 | |
| 575 while (write_thread_running) { | |
| 576 locker.Wait(Monitor::kNoTimeout); | |
| 577 if (write_handle) { | |
| 578 // We woke up and had a handle. Complete it. | |
| 579 write_handle->WriteSyncCompleteAsync(); | |
| 580 write_handle = NULL; | |
| 581 } | |
| 582 } | |
| 583 write_thread_exists = false; | |
| 584 locker.Notify(); | |
| 566 return 0; | 585 return 0; |
| 567 } | 586 } |
| 568 | 587 |
| 569 | 588 |
| 570 void Handle::WriteSyncCompleteAsync() { | 589 void Handle::WriteSyncCompleteAsync() { |
| 571 ASSERT(pending_write_ != NULL); | 590 ASSERT(pending_write_ != NULL); |
| 572 | 591 |
| 573 DWORD bytes_written = -1; | 592 DWORD bytes_written = -1; |
| 574 BOOL ok = WriteFile(handle_, | 593 BOOL ok = WriteFile(handle_, |
| 575 pending_write_->GetBufferStart(), | 594 pending_write_->GetBufferStart(), |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 599 if (pending_write_ != NULL) return 0; | 618 if (pending_write_ != NULL) return 0; |
| 600 if (num_bytes > kBufferSize) num_bytes = kBufferSize; | 619 if (num_bytes > kBufferSize) num_bytes = kBufferSize; |
| 601 if (SupportsOverlappedIO()) { | 620 if (SupportsOverlappedIO()) { |
| 602 if (completion_port_ == INVALID_HANDLE_VALUE) return 0; | 621 if (completion_port_ == INVALID_HANDLE_VALUE) return 0; |
| 603 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); | 622 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); |
| 604 pending_write_->Write(buffer, num_bytes); | 623 pending_write_->Write(buffer, num_bytes); |
| 605 if (!IssueWrite()) return -1; | 624 if (!IssueWrite()) return -1; |
| 606 return num_bytes; | 625 return num_bytes; |
| 607 } else { | 626 } else { |
| 608 // In the case of stdout and stderr, OverlappedIO is not supported. | 627 // In the case of stdout and stderr, OverlappedIO is not supported. |
| 609 // Here we'll instead spawn a new thread for each write, to make it async. | 628 // Here we'll instead use a thread, to make it async. |
| 610 // This code is actually never exposed to the user, as stdout and stderr is | 629 // This code is actually never exposed to the user, as stdout and stderr is |
| 611 // not available as a RawSocket, but only wrapped in a Socket. | 630 // not available as a RawSocket, but only wrapped in a Socket. |
| 612 // Note that we return '0', unless a thread have already completed a write. | 631 // Note that we return '0', unless a thread have already completed a write. |
| 613 // TODO(ajohnsen): Don't spawn a new thread per write. Issue 13541. | |
| 614 if (thread_wrote_ > 0) { | 632 if (thread_wrote_ > 0) { |
| 615 if (num_bytes > thread_wrote_) num_bytes = thread_wrote_; | 633 if (num_bytes > thread_wrote_) num_bytes = thread_wrote_; |
| 616 thread_wrote_ -= num_bytes; | 634 thread_wrote_ -= num_bytes; |
| 617 return num_bytes; | 635 return num_bytes; |
| 618 } | 636 } |
| 619 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); | 637 // Double-checked locking, to avoid taking the lock in most cases. |
|
Søren Gjesse
2013/10/02 08:49:22
You need to hold the lock before accessing shared
Anders Johnsen
2013/10/02 10:16:59
Done.
| |
| 620 pending_write_->Write(buffer, num_bytes); | 638 if (!write_thread_exists) { |
| 621 // Completing asynchronously through thread. | 639 MonitorLocker locker(write_monitor); |
| 622 uint32_t tid; | 640 if (!write_thread_exists) { |
| 623 uintptr_t thread_handle = | 641 write_thread_exists = true; |
| 624 _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid); | 642 uint32_t tid; |
| 625 if (thread_handle == -1) { | 643 uintptr_t thread_handle = |
| 626 FATAL("Failed to start write file thread"); | 644 _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid); |
| 645 // Completing asynchronously through thread. | |
| 646 if (thread_handle == -1) { | |
| 647 FATAL("Failed to start write file thread"); | |
| 648 } | |
| 649 while (!write_thread_running) { | |
| 650 // Wait until we the thread is running. | |
| 651 locker.Wait(Monitor::kNoTimeout); | |
| 652 } | |
| 653 } | |
| 654 } | |
| 655 // Double-checked locking, to avoid taking the lock in most cases. | |
| 656 if (write_handle == NULL) { | |
| 657 MonitorLocker locker(write_monitor); | |
| 658 if (write_handle == NULL) { | |
| 659 // Create buffer and notify thread about the new handle. | |
| 660 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); | |
| 661 pending_write_->Write(buffer, num_bytes); | |
| 662 write_handle = this; | |
| 663 locker.Notify(); | |
| 664 } | |
| 627 } | 665 } |
| 628 return 0; | 666 return 0; |
| 629 } | 667 } |
| 630 } | 668 } |
| 631 | 669 |
| 632 | 670 |
| 633 bool ClientSocket::LoadDisconnectEx() { | 671 bool ClientSocket::LoadDisconnectEx() { |
| 634 // Load the DisconnectEx function into memory using WSAIoctl. | 672 // Load the DisconnectEx function into memory using WSAIoctl. |
| 635 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; | 673 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; |
| 636 DWORD bytes; | 674 DWORD bytes; |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 991 intptr_t result; | 1029 intptr_t result; |
| 992 completion_port_ = | 1030 completion_port_ = |
| 993 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); | 1031 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); |
| 994 if (completion_port_ == NULL) { | 1032 if (completion_port_ == NULL) { |
| 995 FATAL("Completion port creation failed"); | 1033 FATAL("Completion port creation failed"); |
| 996 } | 1034 } |
| 997 shutdown_ = false; | 1035 shutdown_ = false; |
| 998 } | 1036 } |
| 999 | 1037 |
| 1000 | 1038 |
| 1001 EventHandlerImplementation::~EventHandlerImplementation() { | 1039 EventHandlerImplementation::~EventHandlerImplementation() { |
|
Søren Gjesse
2013/10/02 08:49:22
Take the lock before looking at shared data.
Anders Johnsen
2013/10/02 10:16:59
Done.
| |
| 1040 if (write_thread_exists) { | |
| 1041 ASSERT(write_handle == NULL); | |
| 1042 MonitorLocker locker(write_monitor); | |
| 1043 write_thread_running = false; | |
| 1044 locker.Notify(); | |
| 1045 while (write_thread_exists) { | |
| 1046 locker.Wait(Monitor::kNoTimeout); | |
| 1047 } | |
| 1048 } | |
| 1002 CloseHandle(completion_port_); | 1049 CloseHandle(completion_port_); |
| 1003 } | 1050 } |
| 1004 | 1051 |
| 1005 | 1052 |
| 1006 int64_t EventHandlerImplementation::GetTimeout() { | 1053 int64_t EventHandlerImplementation::GetTimeout() { |
| 1007 if (!timeout_queue_.HasTimeout()) { | 1054 if (!timeout_queue_.HasTimeout()) { |
| 1008 return kInfinityTimeout; | 1055 return kInfinityTimeout; |
| 1009 } | 1056 } |
| 1010 int64_t millis = timeout_queue_.CurrentTimeout() - | 1057 int64_t millis = timeout_queue_.CurrentTimeout() - |
| 1011 TimerUtils::GetCurrentTimeMilliseconds(); | 1058 TimerUtils::GetCurrentTimeMilliseconds(); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1099 | 1146 |
| 1100 | 1147 |
| 1101 void EventHandlerImplementation::Shutdown() { | 1148 void EventHandlerImplementation::Shutdown() { |
| 1102 SendData(kShutdownId, 0, 0); | 1149 SendData(kShutdownId, 0, 0); |
| 1103 } | 1150 } |
| 1104 | 1151 |
| 1105 } // namespace bin | 1152 } // namespace bin |
| 1106 } // namespace dart | 1153 } // namespace dart |
| 1107 | 1154 |
| 1108 #endif // defined(TARGET_OS_WINDOWS) | 1155 #endif // defined(TARGET_OS_WINDOWS) |
| OLD | NEW |