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

Side by Side Diff: runtime/platform/thread_win.cc

Issue 294193003: Fix thread-interrupter shutdown on Windows. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cleanup based on typedef fix. Created 6 years, 7 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 | « runtime/platform/thread_win.h ('k') | runtime/vm/os_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "platform/thread.h" 8 #include "platform/thread.h"
9 9
10 #include <process.h> // NOLINT 10 #include <process.h> // NOLINT
(...skipping 15 matching lines...) Expand all
26 uword parameter_; 26 uword parameter_;
27 27
28 DISALLOW_COPY_AND_ASSIGN(ThreadStartData); 28 DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
29 }; 29 };
30 30
31 31
32 // Dispatch to the thread start function provided by the caller. This trampoline 32 // Dispatch to the thread start function provided by the caller. This trampoline
33 // is used to ensure that the thread is properly destroyed if the thread just 33 // is used to ensure that the thread is properly destroyed if the thread just
34 // exits. 34 // exits.
35 static unsigned int __stdcall ThreadEntry(void* data_ptr) { 35 static unsigned int __stdcall ThreadEntry(void* data_ptr) {
36 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr); 36 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr);
37 37
38 Thread::ThreadStartFunction function = data->function(); 38 Thread::ThreadStartFunction function = data->function();
39 uword parameter = data->parameter(); 39 uword parameter = data->parameter();
40 delete data; 40 delete data;
41 41
42 ASSERT(ThreadInlineImpl::thread_id_key != Thread::kUnsetThreadLocalKey);
43
44 ThreadId thread_id = ThreadInlineImpl::CreateThreadId();
45 // Set thread ID in TLS.
46 Thread::SetThreadLocal(ThreadInlineImpl::thread_id_key,
47 reinterpret_cast<DWORD>(thread_id));
48 MonitorData::GetMonitorWaitDataForThread(); 42 MonitorData::GetMonitorWaitDataForThread();
49 43
50 // Call the supplied thread start function handing it its parameters. 44 // Call the supplied thread start function handing it its parameters.
51 function(parameter); 45 function(parameter);
52 46
53 // Clean up the monitor wait data for this thread. 47 // Clean up the monitor wait data for this thread.
54 MonitorWaitData::ThreadExit(); 48 MonitorWaitData::ThreadExit();
55 49
56 // Clear thread ID in TLS.
57 Thread::SetThreadLocal(ThreadInlineImpl::thread_id_key, NULL);
58 ThreadInlineImpl::DestroyThreadId(thread_id);
59
60 return 0; 50 return 0;
61 } 51 }
62 52
63 53
64 int Thread::Start(ThreadStartFunction function, uword parameter) { 54 int Thread::Start(ThreadStartFunction function, uword parameter) {
65 ThreadStartData* start_data = new ThreadStartData(function, parameter); 55 ThreadStartData* start_data = new ThreadStartData(function, parameter);
66 uint32_t tid; 56 uint32_t tid;
67 uintptr_t thread = _beginthreadex(NULL, Thread::GetMaxStackSize(), 57 uintptr_t thread = _beginthreadex(NULL, Thread::GetMaxStackSize(),
68 ThreadEntry, start_data, 0, &tid); 58 ThreadEntry, start_data, 0, &tid);
69 if (thread == -1L || thread == 0) { 59 if (thread == -1L || thread == 0) {
70 #ifdef DEBUG 60 #ifdef DEBUG
71 fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno)); 61 fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno));
72 #endif 62 #endif
73 return errno; 63 return errno;
74 } 64 }
75 65
66 // Close the handle, so we don't leak the thread object.
67 CloseHandle(reinterpret_cast<HANDLE>(thread));
68
76 return 0; 69 return 0;
77 } 70 }
78 71
79
80 ThreadId ThreadInlineImpl::CreateThreadId() {
81 // Create an ID for this thread that can be shared with other threads.
82 HANDLE thread_id = OpenThread(THREAD_GET_CONTEXT |
83 THREAD_SUSPEND_RESUME |
84 THREAD_QUERY_INFORMATION,
85 false,
86 GetCurrentThreadId());
87 ASSERT(thread_id != NULL);
88 return thread_id;
89 }
90
91
92 void ThreadInlineImpl::DestroyThreadId(ThreadId thread_id) {
93 ASSERT(thread_id != NULL);
94 // Destroy thread ID.
95 CloseHandle(thread_id);
96 }
97
98
99 ThreadLocalKey ThreadInlineImpl::thread_id_key = Thread::kUnsetThreadLocalKey;
100
101 ThreadLocalKey Thread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES; 72 ThreadLocalKey Thread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
102 ThreadId Thread::kInvalidThreadId = 73 ThreadId Thread::kInvalidThreadId = 0;
103 reinterpret_cast<ThreadId>(INVALID_HANDLE_VALUE);
104 74
105 ThreadLocalKey Thread::CreateThreadLocal() { 75 ThreadLocalKey Thread::CreateThreadLocal() {
106 ThreadLocalKey key = TlsAlloc(); 76 ThreadLocalKey key = TlsAlloc();
107 if (key == kUnsetThreadLocalKey) { 77 if (key == kUnsetThreadLocalKey) {
108 FATAL1("TlsAlloc failed %d", GetLastError()); 78 FATAL1("TlsAlloc failed %d", GetLastError());
109 } 79 }
110 return key; 80 return key;
111 } 81 }
112 82
113 83
114 void Thread::DeleteThreadLocal(ThreadLocalKey key) { 84 void Thread::DeleteThreadLocal(ThreadLocalKey key) {
115 ASSERT(key != kUnsetThreadLocalKey); 85 ASSERT(key != kUnsetThreadLocalKey);
116 BOOL result = TlsFree(key); 86 BOOL result = TlsFree(key);
117 if (!result) { 87 if (!result) {
118 FATAL1("TlsFree failed %d", GetLastError()); 88 FATAL1("TlsFree failed %d", GetLastError());
119 } 89 }
120 } 90 }
121 91
122 92
123 intptr_t Thread::GetMaxStackSize() { 93 intptr_t Thread::GetMaxStackSize() {
124 const int kStackSize = (128 * kWordSize * KB); 94 const int kStackSize = (128 * kWordSize * KB);
125 return kStackSize; 95 return kStackSize;
126 } 96 }
127 97
128 98
129 ThreadId Thread::GetCurrentThreadId() { 99 ThreadId Thread::GetCurrentThreadId() {
130 ThreadId id = reinterpret_cast<ThreadId>( 100 return ::GetCurrentThreadId();
131 Thread::GetThreadLocal(ThreadInlineImpl::thread_id_key)); 101 }
132 ASSERT(id != NULL); 102
133 return id; 103
104 bool Thread::Join(ThreadId id) {
105 HANDLE handle = OpenThread(SYNCHRONIZE, false, id);
106 if (handle == INVALID_HANDLE_VALUE) {
107 return false;
108 }
109 DWORD res = WaitForSingleObject(handle, INFINITE);
110 CloseHandle(handle);
111 return res == WAIT_OBJECT_0;
134 } 112 }
135 113
136 114
137 intptr_t Thread::ThreadIdToIntPtr(ThreadId id) { 115 intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
138 ASSERT(sizeof(id) == sizeof(intptr_t)); 116 ASSERT(sizeof(id) <= sizeof(intptr_t));
139 return reinterpret_cast<intptr_t>(id); 117 return static_cast<intptr_t>(id);
140 } 118 }
141 119
142 120
143 bool Thread::Compare(ThreadId a, ThreadId b) { 121 bool Thread::Compare(ThreadId a, ThreadId b) {
144 return a == b; 122 return a == b;
145 } 123 }
146 124
147 125
148 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) { 126 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
149 static const int64_t kTimeEpoc = 116444736000000000LL; 127 static const int64_t kTimeEpoc = 116444736000000000LL;
150 static const int64_t kTimeScaler = 10; // 100 ns to us. 128 static const int64_t kTimeScaler = 10; // 100 ns to us.
151 // Although win32 uses 64-bit integers for representing timestamps, 129 // Although win32 uses 64-bit integers for representing timestamps,
152 // these are packed into a FILETIME structure. The FILETIME 130 // these are packed into a FILETIME structure. The FILETIME
153 // structure is just a struct representing a 64-bit integer. The 131 // structure is just a struct representing a 64-bit integer. The
154 // TimeStamp union allows access to both a FILETIME and an integer 132 // TimeStamp union allows access to both a FILETIME and an integer
155 // representation of the timestamp. The Windows timestamp is in 133 // representation of the timestamp. The Windows timestamp is in
156 // 100-nanosecond intervals since January 1, 1601. 134 // 100-nanosecond intervals since January 1, 1601.
157 union TimeStamp { 135 union TimeStamp {
158 FILETIME ft_; 136 FILETIME ft_;
159 int64_t t_; 137 int64_t t_;
160 }; 138 };
161 ASSERT(cpu_usage != NULL); 139 ASSERT(cpu_usage != NULL);
162 TimeStamp created; 140 TimeStamp created;
163 TimeStamp exited; 141 TimeStamp exited;
164 TimeStamp kernel; 142 TimeStamp kernel;
165 TimeStamp user; 143 TimeStamp user;
166 BOOL result = GetThreadTimes(thread_id, 144 HANDLE handle = OpenThread(THREAD_QUERY_INFORMATION, false, thread_id);
145 BOOL result = GetThreadTimes(handle,
167 &created.ft_, 146 &created.ft_,
168 &exited.ft_, 147 &exited.ft_,
169 &kernel.ft_, 148 &kernel.ft_,
170 &user.ft_); 149 &user.ft_);
150 CloseHandle(handle);
171 if (!result) { 151 if (!result) {
172 FATAL1("GetThreadCpuUsage failed %d\n", GetLastError()); 152 FATAL1("GetThreadCpuUsage failed %d\n", GetLastError());
173 } 153 }
174 *cpu_usage = (user.t_ - kTimeEpoc) / kTimeScaler; 154 *cpu_usage = (user.t_ - kTimeEpoc) / kTimeScaler;
175 } 155 }
176 156
177 157
178 void Thread::SetThreadLocal(ThreadLocalKey key, uword value) { 158 void Thread::SetThreadLocal(ThreadLocalKey key, uword value) {
179 ASSERT(key != kUnsetThreadLocalKey); 159 ASSERT(key != kUnsetThreadLocalKey);
180 BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value)); 160 BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value));
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 // timeout before we signal it, that object will get an extra 430 // timeout before we signal it, that object will get an extra
451 // signal. This will be treated as a spurious wake-up and is OK 431 // signal. This will be treated as a spurious wake-up and is OK
452 // since all uses of monitors should recheck the condition after a 432 // since all uses of monitors should recheck the condition after a
453 // Wait. 433 // Wait.
454 data_.SignalAndRemoveAllWaiters(); 434 data_.SignalAndRemoveAllWaiters();
455 } 435 }
456 436
457 } // namespace dart 437 } // namespace dart
458 438
459 #endif // defined(TARGET_OS_WINDOWS) 439 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/platform/thread_win.h ('k') | runtime/vm/os_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698